문제 상황
프로젝트 초기 단계에서 기본적인 엔티티를 구현하던 중,
PR 과정에서 코드 리뷰 도구(CodeRabbit)가 엔티티에 검증 로직 추가를 제안하였다.
기존에는 예외 처리는 서비스 레이어에서 수행하는 것이라고 알고 있었기 때문에,
엔티티에서 별도의 검증 로직이 필요한지에 대한 의문이 생겼다.
특히, 서비스에서 검증을 수행할 예정인데
엔티티에서도 검증이 필요한지에 대한 기준이 명확하지 않은 상태였다.
코드 리뷰 피드백
코드 리뷰 도구(CodeRabbit)는 다음과 같은 피드백을 제안하였다.

해당 피드백을 통해,
엔티티 생성 시점에 유효성 검증을 수행하지 않으면
객체 생성 이후 DB 저장 단계에서 예외가 발생할 수 있다는 점을 인지하게 되었다.
원인 분석
해당 의문을 해결하기 위해 관련 자료를 찾아보고 팀 내 논의를 진행하였다.
그 결과, 서비스 레이어와 엔티티의 역할을 명확히 구분하지 못했던 것이 원인이었다.
해결 과정
논의를 통해 각 레이어의 역할을 다음과 같이 정리하였다.
서비스 레이어
- 외부 요청(Request)을 검증
- 잘못된 요청을 필터링하는 역할
엔티티
- 도메인 객체의 상태를 보장
- 유효하지 않은 상태로 생성되는 것을 방지하는 역할
즉,
서비스는 외부 요청을 걸러내는 역할
엔티티는 도메인 자체를 보호하는 역할
이라는 차이를 가지는 것으로 정리하였다.
해결 방법
해당 기준을 바탕으로 엔티티에 최소한의 검증 로직을 추가하였다.
- 엔티티 컬럼 객체 타입(Integer, Long)으로 통일하여 null 검증이 가능하도록 하였다.
- 필수값은 'Objects.requireNonNull'을 사용하여 검증
- 검증 메시지는 "~~는 필수입니다" 형식으로 통일
또한, 검증 로직의 재사용성을 위해 공통 유틸 클래스로 분리하였다.
public class ValidationUtils {
public static void validateNonNull(Object value, String fieldName) {
Objects.requireNonNull(value, fieldName + "(은)는 필수입니다");
}
}
public static Playback create(Long trackId, Long userId, String sessionId, String deviceId) {
ValidationUtils.validateNonNull(trackId, "trackId");
ValidationUtils.validateNonNull(userId, "userId");
ValidationUtils.validateNonNull(sessionId, "sessionId");
...
return playback;
}
이를 통해 엔티티 생성 시점에서 도메인의 유효성을 보장할 수 있도록 하였다.
결과
- 엔티티 생성 시 필수값 검증이 일관되게 적용됨
- 서비스와 엔티티의 역할을 명확히 구분할 수 있게 됨
- 검증 로직의 재사용성과 유지보수성이 향상됨
결론
엔티티 검증은 서비스 레이어의 검증과 중복되는 것이 아니라, 서로 다른 책임을 수행하는 구조이다.
서비스는 외부 요청을 검증하고, 엔티티는 도메인의 상태를 보장한다.
이러한 역할 분리를 통해 보다 안정적인 도메인 설계를 할 수 있었다.
느낀 점
이번 경험을 통해 서비스 레이어와 엔티티 검증의 역할 차이를 명확히 이해할 수 있었다.
기존에는 검증 로직을 서비스 레이어에서만 수행한다고 생각했지만,
코드 리뷰를 계기로 엔티티에서도 도메인의 상태를 보장하기 위한 검증이 필요하다는 점을 알게 되었다.
이를 통해 검증 로직의 위치보다 중요한 것은
각 레이어가 어떤 책임을 가지는지에 대한 설계라는 것을 이해할 수 있었다.
'Fivefy 프로젝트 > 트러블슈팅' 카테고리의 다른 글
| 스케줄러 기반 로직 테스트 설계와 운영 환경 고려 (0) | 2026.04.16 |
|---|---|
| 커버리지 100% 대신 의미 있는 테스트를 선택한 이유 (1) | 2026.04.15 |
| 동시 요청에서 발생할 수 있는 중복 데이터 문제와 DB 유니크 제약으로 해결 (2) | 2026.04.14 |
| 컬럼명 문제로 인한 DDL 오류 및 테이블 생성 실패 해결 (0) | 2026.04.13 |
| 트랙 재생 상태 설계 개선 - SKIP 상태 도입 (0) | 2026.04.09 |