문제 상황
저는 현재 소모임과 비슷한 백엔드 서비스를 팀프로젝트로 진행중입니다. 그 과정에서 모임 삭제 로직 내부에서 발견한 오류입니다.
문제 상황은 다음과 같습니다.
1. 모임 삭제 시 참가자 컬럼 또한 삭제가 필요
2. 애그리거트 루트가 Meeting 이기 때문에 엔티티 클래스에
메서드를 생성해 삭제하는 로직 작성
3. column 'meeting_id' cannot be null 에러 발생
문제 원인
1 : N 단방향 관계에서 쉽게 일어날 수 있는 문제이며, 직접적으로 1:N 단방향을 설정하며 개발을 많이 안해왔기 때문에 파악하지 못했던 문제입니다.
Jpa에서 위와 같이 JoinColumn을 통해서 연관관계를 1:N 을 정했을 때, Jpa는 관계를 우선적으로 정리하기 위해서
UPDATE meeting_participants SET meeting_id = NULL WHERE meeting_id = 1;
위와 같이 null로 set 해주는 query가 내부적으로 실행합니다.
그러나 MeetingParticipant Table의 meetingId는 NOT NULL 로 설정되어 있습니다.
따라서 조건이 위배되기 때문에 cannot be null 에러가 발생하는 것입니다.
해결방안
- 완전한 양방향 관계 설정
- meetingId NOT NULL 조건 해제 -> 올바르지 않은 해결 방안
- 단방향이지만 관계의 주인을 하위 테이블로 변경
- clear로 삭제 대신 removeIf로 개별 삭제 -> 실패
선택한 해결방안
기존 DDD 방식으로 내부적으로는 애그리거트 루트를 지정하여 객체지향적인 코드를 작성하기 위해 루트를 통해서만 하위 애그리거트 로직을 탈 수 있습니다.
그런데 양방향으로 관계를 수정한다는 것 자체가 그냥 문제만 해결하기 위해 정해진 룰을 깬다 생각했습니다.
따라서 3번을 선택했습니다.
물론 3번 또한 관계의 주인은 MeetingParticipant인 것은 1번과 동일하지만, 실제로 양방향 관계는 아니며 Jpa의 관점에서 관계의 주인이 MeetingParticipant인 것이고 실제 로직은 Meeting (애그리거트 루트) 를 통해서만 실행 되기 때문에 선택하게 되었습니다.
+ 결과적으로 팀 회의를 통해 양방향으로 정의하여 해결하게 되었습니다. 그 이유는 위와 같은 방법으로는 명확하지 않다라고 판단되었기 때문입니다. 문제 해결만을 위한 Table 설정이라고 판단이 되었으며, 실무에서 또한 양방향 설정을 해서 더 명확하게 판단할 수 있게 설정한다고 합니다.