일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- BEAN
- 오블완
- Token
- devpi
- springboot
- Component
- 클래스
- OOP
- 객체지향
- 소프트웨어설계
- 코틀린
- kotlin
- 자바
- 스프링
- entity
- JPA
- JWT
- Stream
- Configuration
- SpringFramework
- 스프링 부트
- java
- javamailsender
- Spring Boot
- map
- JPQL
- 토큰
- Spring
- 티스토리챌린지
- ava백엔드
- Today
- Total
DeveloPiano
JPA 엔티티 - new 사용 지양 & Static 메서드 활용 본문
Spring JPA로 개발을 하다 보면 new Entity()를 통해 엔티티 객체를 직접 생성하고 싶은 유혹에 빠지기 쉽습니다. 그런데 실무에서는 보통 이렇게 하지 않도록 유도하거나 제한을 둡니다. 왜 그런 걸까요?
이번 글에서는 다음과 같은 내용을 중심으로 정리해보겠습니다.
- @NoArgsConstructor(access = AccessLevel.PROTECTED)를 사용하는 이유
- 무분별한 빈 객체 생성을 피해야 하는 이유
- static 팩토리 메서드가 필요한 이유
기본 생성자에 protected를 설정하면 어떤 문제가 발생할까?
JPA에서는 기본 생성자가 반드시 필요합니다. 그런데 그 생성자가 protected여서 다음 코드가 컴파일 에러를 발생시키는 경우가 있습니다.
// 컴파일 에러 발생
MemberEntity entity = new MemberEntity();
이유는 간단합니다. 엔티티 클래스가 다음과 같이 선언되어 있기 때문입니다.
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class MemberEntity {
// 필드 생략
}
이 경우 MemberEntity는 외부에서 직접 new로 생성할 수 없습니다. 대신, 정적 팩토리 메서드나 빌더 패턴을 사용해야 합니다.
무분별한 빈 객체 생성을 피해야 하는 이유
1. 도메인 불변식(invariant) 위반
엔티티는 생성 시점에 반드시 채워져야 할 필드들이 존재합니다. 예를 들어 로그인 아이디, 비밀번호, 권한 등은 비워둘 수 없는 값입니다.
그런데 new를 통해 아무 값 없이 빈 객체를 만들면 이러한 불변식을 쉽게 위반할 수 있습니다.
2. 코드 가독성과 유지보수의 어려움
여러 곳에서 new를 직접 호출하고, setter로 값을 채운다면 어떤 필드를 꼭 초기화해야 하는지 알기 어렵습니다. 실수로 필드를 빼먹거나 순서를 잘못 지정하는 문제가 생기기 쉽습니다.
3. 디버깅과 테스트 복잡도 증가
객체가 어떤 상태로 생성됐는지를 파악하기 어려워집니다. 필드가 나중에 채워지는 구조라면 디버깅할 때 값이 어디서 세팅됐는지 추적하기 번거롭습니다.
4. 생성자 또는 팩토리 메서드에서의 검증 누락
비밀번호 복잡도 검사나 기본 권한 할당 등 중요한 초기화 로직을 놓칠 수 있습니다. 팩토리 메서드를 사용하면 이런 검증을 내부에서 처리할 수 있습니다.
static 메서드는 왜 사용할까?
public static MemberEntity createAdminMember(RequestDto dto) {
MemberEntity entity = new MemberEntity();
entity.loginId = dto.getLoginId();
entity.password = dto.getPassword();
// 기타 필드 설정
return entity;
}
이처럼 static 메서드를 사용하면 다음과 같은 이점이 있습니다.
1. 객체 없이 호출 가능
static 메서드는 인스턴스를 만들지 않아도 클래스 이름만으로 호출할 수 있습니다:
MemberEntity admin = MemberEntity.createAdminMember(dto);
2. 생성 목적이 명확한 메서드 이름
createAdminMember라는 이름만 봐도 어떤 역할을 하는 객체인지 명확히 알 수 있습니다. 생성자의 오버로딩보다 의미 전달력이 높습니다.
3. 내부 구현 유연성 확보
정적 메서드 안에서는 필요하면 서브타입을 반환하거나 캐싱 로직을 넣는 등 유연한 확장이 가능합니다. 생성자 방식은 이런 구조를 갖기 어렵습니다.
4. 도메인 일관성과 정합성 확보
팩토리 메서드 내부에서 필요한 필드를 모두 초기화하고, 검증까지 마치면 안정된 객체만 외부로 노출할 수 있습니다. 이는 도메인의 무결성을 유지하는 데 큰 도움이 됩니다.
결론
- JPA에서는 기본 생성자를 protected로 두고 외부에서 직접 new를 호출하지 않도록 유도합니다.
- 빈 객체 생성을 허용하면 불완전한 상태의 객체가 만들어져 데이터 정합성이 무너질 수 있습니다.
- 이를 해결하기 위해 static 팩토리 메서드나 @Builder 패턴을 사용하는 것이 좋습니다.
현업에서는 도메인 객체의 생성 방식을 통제하고, 객체가 올바른 상태로만 존재하도록 관리하는 것이 중요합니다. new 대신 목적이 명확한 팩토리 메서드를 사용하는 습관을 들이면, 코드의 품질과 유지보수성이 크게 향상될 수 있습니다.
'Develop > Spring' 카테고리의 다른 글
Spring @Component, @Configuration, 커스텀 리졸버 이해하기 (1) | 2025.07.12 |
---|---|
Spring Boot 프로젝트에서 SSR과 클라이언트 스크립트의 혼합 사용 (2) | 2025.07.11 |
Spring의 Bean, Container, Component, Configuration 개념 정리 (1) | 2025.04.18 |
[Spring] 인스턴스화에 대해서 클래스, 객체와 비교해보기 (0) | 2025.04.17 |
Web server failed to start: Port 8080 was already in use 에러 해결 방법 (0) | 2025.03.31 |