Spring 7기 프로젝트/코드 개선 + 테스트 코드 프로젝트

[트러블슈팅] Spring JPA에서 연관관계 null 체크의 중요성

JuNo_12 2025. 6. 5. 15:04

문제 상황

과제 진행 중, 다음과 같은 테스트가 실패했습니다.

@Test
void todo의_user가_null인_경우_예외가_발생한다() {
    // given
    Todo todo = new Todo();
    ReflectionTestUtils.setField(todo, "user", null);
    
    // when & then
    assertThrows(InvalidRequestException.class, () -> 
        managerService.saveManager(authUser, todoId, request)
    );
}

 

원인 분석

기존 서비스 코드에서는 null 체크 없이 바로 연관관계 객체의 메서드를 호출했습니다.

// 문제가 있는 코드
if (!ObjectUtils.nullSafeEquals(user.getId(), todo.getUser().getId())) {
    // todo.getUser()가 null이면 NPE 발생!
}

 

해결 방법

연관관계 객체에 접근하기 전 null 체크를 추가했습니다.

// 개선된 코드
if (todo.getUser() == null) {
    throw new InvalidRequestException("유효하지 않은 일정입니다.");
}

if (!ObjectUtils.nullSafeEquals(user.getId(), todo.getUser().getId())) {
    throw new InvalidRequestException("권한이 없습니다.");
}

왜 이런 상황이 발생할까?

@JoinColumn(nullable = false)로 설정했어도 다음 상황에서 null이 가능합니다:

  • 동시성 문제: 트랜잭션 처리 중 중간 상태
  • 데이터 마이그레이션: 불완전한 데이터 임시 저장
  • 외부 시스템 연동: 불완전한 데이터 수신
  • 개발/테스트 환경: 수동 데이터 입력

 

느낀점

DB 제약조건만으로는 완벽하지 않다.

애플리케이션 레벨에서의 방어적 프로그래밍이 필요하며, 특히 연관관계 객체에 접근할 때는 항상 null 체크를 하는 것이 안전합니다.

// 좋은 패턴
if (entity.getRelatedEntity() == null) {
    throw new BusinessException("적절한 에러 메시지");
}
// 이후 안전하게 사용
entity.getRelatedEntity().someMethod();