[SB 3기] 코드잇 스프린트 위클리페이퍼 10주차
카테고리
프로그래밍/소프트웨어 개발
서브카테고리
개발 툴
대상자
백엔드 개발자, 테스트 엔지니어, 프레임워크 사용자
난이도: 중간 (Spring/Java 기초 지식 필수)
핵심 요약
- 계층별 입력값 검증 분리
- DTO: @Valid
, @NotNull
등 Bean Validation 사용 (형식 검증)
- 서비스: 비즈니스 규칙 검증 (이메일 중복, 권한 체크)
- 도메인: 생성자/팩토리 메서드에서 불변 조건 검증 (null, enum 범위 등)
- Mockito의 3가지 개념 차이
- Mock
: 완전히 가짜 객체, 행위 기반 테스트 (ex. verify(mock).upload()
)
- Stub
: 예측 가능한 결과 반환 (ex. when(stub).upload().thenReturn(true)
)
- Spy
: 실제 객체를 감싸며 특정 메서드만 조작 (ex. doReturn(false).when(spy).upload()
)
- 중복 검증 방지 전략
- 계층적 책임 분리 (DB UNIQUE
제약으로 최종 무결성 보장)
- 의도적 중첩 방어 (중복 체크 + DB 제약 조합)
섹션별 세부 요약
1. 계층별 입력값 검증 범위
- Presentation 계층 (Controller/DTO)
- 사용자 입력 형식 검증: @NotBlank
, @Email
, @Size
등
- 예: @Valid @RequestBody MessageUpdateRequest
- Business 계층 (Service)
- 비즈니스 규칙 검증: 이메일 중복, 권한 체크, 상태값 검증
- 예: if (userRepository.existsByEmail(email)) { throw ... }
- Domain 계층 (Entity)
- 객체 불변 조건 검증: 생성자/팩토리 메서드 내 null
, enum
범위 검증
- 예: if (email == null) throw new IllegalArgumentException()
- Persistence 계층 (DB)
- 데이터 무결성 보장: UNIQUE
, NOT NULL
, FOREIGN KEY
, CHECK
제약 조건
2. 중복 검증 방지와 트레이드오프
- 중복 검증 문제
- 이메일 형식 체크, 중복 여부 검증 등 코드 중복 가능성
- 유지보수 비용 증가, 버그 유발 가능성
- 해결 방안
- 계층 간 책임 분리 (DTO → Service → Entity → DB 순으로 검증)
- 의도적 중첩 방어 (ex. Service 중복 체크 + DB UNIQUE
제약 조합)
- 트레이드오프
- 장점: 유지보수성 향상, 일관성 확보
- 단점: 책임 분리 미흡 시 중복/누락 가능성, 예외 상황 대응력 저하
3. Mockito 개념과 사용 시나리오
- Mock
- 완전히 가짜 객체, 내부 로직 실행 X
- 행위 검증 주도 (ex. verify(mock).upload("file")
)
- 사용 시나리오: 외부 시스템 호출 여부 확인 (이메일 전송 등)
- Stub
- 행위 기반 테스트 + 예측 가능한 결과 반환
- ex: when(stub.upload(anyString())).thenReturn(true)
- 사용 시나리오: 외부 API 테스트, 예외 유도 테스트
- Spy
- 실제 객체 감싸기, 특정 메서드만 조작
- ex: doReturn(false).when(spy).upload("bad/file.txt")
- 사용 시나리오: 상태/행위 검증 동시 수행, 일부 상황만 제어 필요 시
결론
- 검증 전략:
@Valid
로 DTO 형식 검증 → Service로 비즈니스 규칙 체크 → Entity 생성자에서 불변 조건 검증 → DB 제약 조건으로 최종 무결성 보장 - Mockito 팁:
- Mock
은 행위 검증에, Stub
은 결과 제어에, Spy
는 부분 모의에 적합
- 의도적 중첩 방어가 필요한 경우 주석/문서로 명시 (ex. // 의도적 중첩: Service + DB UNIQUE
)
- Spy
사용 시 복잡한 로직 테스트 회피 권장