왜 API에서 Persistence Entities를 노출하는 것이 위험한 지름길인가

발행: (2025년 12월 28일 오후 04:48 GMT+9)
4 분 소요
원문: Dev.to

Source: Dev.to

예시 컨트롤러

@PostMapping("/books")
public BookItem create(@RequestBody BookItem bookItem) {
    return bookService.save(bookItem);
}

왜 그렇게 느꼈는가

  • 엔티티에 이미 모든 필드가 존재했다.
  • 추가 클래스를 작성할 필요가 없었다.
  • 개발 속도가 빨라졌다.
  • 작은 프로젝트에 DTO는 불필요한 보일러플레이트처럼 보였다.

엔티티를 직접 노출할 때의 문제점

엔티티를 요청 본문으로 직접 사용할 경우 모든 필드가 쓰기 가능해진다. 이는 클라이언트가 다음을 할 수 있게 만든다:

  • 데이터베이스 ID를 직접 지정한다.
  • 절대 제어해서는 안 되는 필드를 수정한다.
  • 내부 로직 전용 값들을 전송한다.

프레임워크는 의도를 알지 못하고 단순히 필드를 매핑하므로, API가 클라이언트를 지나치게 신뢰하게 된다.

엔티티별 고려사항

  • 내부 플래그.
  • 감사 타임스탬프.
  • 클라이언트에게는 무관하거나 위험한 필드.

클라이언트가 이러한 필드를 사용하기 시작하면, 해당 필드는 공개 계약의 일부가 된다—예상치 못한 경우라도 말이다. 이것이 가장 치명적인 문제이며, 보통 너무 늦게 드러난다.

예시 엔티티 및 JSON 페이로드

@Entity
public class BookItem {
    @Id
    private String id;
    private String title;
    private String author;
    private int pages;
}
{
  "id": "123",
  "title": "Clean Code",
  "author": "Robert Martin",
  "pages": 464
}

클라이언트는 이 응답을 기반으로 로직을 구성한다.

엔티티를 변경하면 API가 깨진다

예를 들어 pages가 부정확하다고 판단하고 wordCount로 교체했다고 가정해 보자:

@Entity
public class BookItem {
    @Id
    private String id;
    private String title;
    private String author;
    private int wordCount;
}

컨트롤러는 수정하지 않았지만, 응답은 이제 다음과 같이 된다:

{
  "id": "123",
  "title": "Clean Code",
  "author": "Robert Martin",
  "wordCount": 150000
}
  • pages가 사라졌다.
  • wordCount가 새로 등장했다.

결과: 클라이언트가 깨지고, 프론트엔드가 충돌하며, 모바일 앱이 실패한다. 이는 엔티티가 API 역할을 했기 때문에 발생한 일이다.

DTO 사용의 장점

DTO는 내부 모델과 외부 소비자 사이에 안정적인 경계를 만든다.

  • 클라이언트는 허용된 필드만 전송할 수 있다.
  • 응답은 안전한 데이터만 노출한다.
  • 엔티티는 자유롭게 변경할 수 있다.
  • API는 안정성을 유지한다.

결론

엔티티를 API에 직접 사용하는 것은 처음엔 생산적으로 보일 수 있지만, 실제 비용은 나중에 요구사항이 바뀌고 리팩터링이 위험해질 때 나타난다. 엔티티는 API가 아니다. DTO는 몇 개의 추가 클래스를 요구할 뿐이며, 시스템을 조용한 파손과 미래의 고통으로부터 보호한다.

Back to Blog

관련 글

더 보기 »