본문 바로가기
개발관련

<캡슐화> JPA 엔티티 생성시 Setter를 지양하는이유

by 수바니 2024. 9. 24.

JPA 엔티티 생성시  setter 메서드를 지양해야 하는 이유는 객체 지향 프로그래밍의 원칙 중 하나인 캡슐화와 깊은 관련이 있습니다.

 

JPA 엔티티는 데이터베이스 테이블과 매핑되는 객체로, 데이터의 상태와 비즈니스 로직을 담습니다. 엔티티에서 setter를 무분별하게 사용하는 것은 다음과 같은 문제를 초래할 수 있습니다.

  1. 캡슐화 원칙 위반
     setter 메서드를 통해 엔티티의 상태를 쉽게 변경할 수 있게 하면, 객체의 내부 상태가 외부에서 쉽게 조작될 수 있습니다. 이렇게 되면 엔티티의 데이터 무결성을 유지하기가 어렵고, 예기치 않은 상태 변경이 발생할 수 있습니다. 엔티티의 데이터를 수정할 때는 반드시 해당 수정이 비즈니스 로직에 부합하는지 확인해야 하는데, setter는 이러한 검증 과정을 우회합니다.
  2. 불변성 위반
    엔티티가 한 번 생성된 후에는 가능한 한 상태를 변경하지 않는 것이 좋습니다. 하지만 setter를 통해 언제든지 필드를 수정할 수 있다면, 엔티티는 불필요하게 변할 가능성이 커지며, 이로 인해 디버깅과 유지보수가 어려워집니다.

  3. 프록시 객체 문제
    JPA에서는 엔티티를 지연로딩하기 위해 프록시 객체를 생성할 수 있습니다. 이때 setter를 남용하면 프록시 객체의 일관성을 해칠 수 있으며, 이는 데이터베이스 상태와 메모리 상의 엔티티 상태가 불일치하는 문제를 일으킬 수 있습니다.

해결방안

더보기
생성자나 빌더 패턴 사용: 생성자를 통해 필수 필드만 설정하거나, 빌더 패턴을 사용해 생성 시점에 필요한 값을 설정하고 이후에는 상태 변경을 최소화하는 것이 좋습니다. 이렇게 하면 객체의 일관성과 무결성을 유지할 수 있습니다.

 

더불어, 서비스계층에서 Builder 패턴을 지양해야하는 이유

 

  1. 비즈니스 로직 분리 실패
    서비스 계층은 비즈니스 로직을 처리하는 곳입니다. 만약 서비스 단에서 builder 패턴을 사용하면 비즈니스 로직이 엔티티의 생성 방식에 묶일 수 있어 코드의 응집도가 떨어집니다. 이는 서비스 계층이 객체 생성에 관여하는 것을 의미하며, 결과적으로 서비스 단에서 해야 할 일과 객체 생성이 혼재될 수 있습니다. 객체 생성은 보통 팩토리 패턴이나 별도의 빌더 클래스로 분리하는 것이 좋습니다.


  2. 복잡성 증가
    서비스 레이어는 주로 트랜잭션 관리, 비즈니스 규칙 처리 등의 역할을 담당합니다. 여기서 객체 생성 로직까지 처리하면 서비스 레이어의 책임이 불필요하게 복잡해질 수 있습니다. 따라서 객체 생성을 위한 로직은 도메인 모델이나 DTO 생성 부분으로 분리하는 것이 더 적합합니다.

 

캡슐화와의 관계

캡슐화는 객체 지향 설계의 핵심 원칙 중 하나로, 객체의 상태(데이터)를 외부에서 직접 접근하지 못하게 하고, 객체 내에서만 상태를 관리하도록 하는 원칙입니다. 이를 통해 객체의 일관성을 유지하고, 외부 코드와의 결합도를 낮출 수 있습니다.

  1. 엔티티의 상태 관리
    JPA 엔티티에서 setter 메서드를 제거하고 필드 값을 직접 변경하지 못하게 하여 상태를 안전하게 보호할 수 있습니다. 이렇게 하면 엔티티의 필드가 외부에서 임의로 수정되는 것을 방지하여 엔티티의 일관성을 유지할 수 있습니다.

  2. 책임의 분리
    서비스 단에서 객체 생성 로직을 배제하고, 비즈니스 로직과 객체 생성의 책임을 분리하면 코드의 가독성 및 유지 보수성이 높아집니다. 이는 객체 지향 설계에서의 단일 책임 원칙(Single Responsibility Principle, SRP) 을 따르는 것과도 관련이 있습니다.