개발/피드 한 줌

데이터 일관성 문제 회고

조금씩 차근차근 2025. 3. 1. 22:58

팀 프로젝트 일정 관리에서의 데이터 일관성 유지 회고

프로젝트를 진행하면서 겪은 가장 큰 도전 중 하나는 팀 프로젝트 기간과 개별 일정 간의 일관성 문제였습니다. 우리 서비스는 단순 피드백을 넘어서 대학생들이 팀 내에서 자유롭게 일정과 할 일을 관리하며 능동적으로 소통할 수 있도록 설계되었는데요, 그만큼 비즈니스 로직에 따른 세밀한 제약 조건을 고려해야 했습니다.


비즈니스 로직의 핵심 요구사항

image

  • 팀 프로젝트 기간 수정: 오직 팀장만 프로젝트 기간을 수정할 수 있습니다.
  • 일정 추가: 팀원 누구나 일정을 추가할 수 있습니다.

이러한 제약은 단순한 피드백 시스템이 아니라, 팀원들이 스스로 일정 관리 및 피드백을 주고받음으로써 리텐션을 높이는 핵심 기능을 수행하도록 돕기 위해 고안되었습니다.

image

하지만 이 요구사항 때문에 두 가지 중요한 문제에 직면했습니다.

  1. 동시성 문제: 팀장이 프로젝트 기간을 수정하는 순간, 팀원이 일정을 추가하면 일정이 팀 프로젝트 기간 범위를 벗어날 위험이 있습니다.
  2. 검증의 최신성 문제: 일정 생성 시, 팀 프로젝트 기간을 조회해 검증하는 사이 값이 변경되면, 유효하지 않은 일정이 생성될 수 있습니다.

image

문제의 본질:

  • 일정 생성 중에는 프로젝트 기간이 변경되면 안 된다.
  • 프로젝트 기간 변경 시에는 새로운 일정 생성이 없어야 한다.

아키텍쳐 설계: 도메인 모델의 분리

image

처음에는 일정이 단순히 팀의 하위 도메인처럼 보였지만, 실제로는 일정이 우리 서비스의 핵심 기능임이 분명했습니다. 일정은 단순히 시간 관리가 아니라,

  • 할 일 관리,
  • 종료 이벤트 발행, 그리고
  • 피드백 애그리거트와의 빈번한 이벤트 주고받기등 중요한 역할을 수행합니다.

따라서 일정은 팀과 독립적인 애그리거트 루트로 분리하였습니다.

image

이렇게 분리함으로써, 각 도메인이 자신만의 불변 조건(예: 일정 종료)을 스스로 책임질 수 있도록 설계했습니다.


데이터 일관성 문제 해결 전략

두 애그리거트 간의 일관성을 유지하기 위해 다양한 전략을 고민했습니다.

1. 도메인 이벤트 방식

  • 장점: 여러 엔티티 간의 이벤트 기반 연동 가능
  • 단점: 상태 전이, 롤백, 트랜잭션 커밋 후 재검증 등 복잡성이 증가하여 오히려 모놀리식의 장점을 잃게 됨
    image
  • 상태 패턴과 도메인 이벤트, Transition 시 이벤트 발행 방식으로 구현하게 될 경우, 구현해야 하는 상태 기계들. 매우 양이 방대하다.

2. 도메인 서비스 도입

결국 TeamPlanOrchestrator라는 도메인 서비스를 도입하여 스프링 트랜잭션으로 간단하게 관리하는 방식을 선택했습니다.

image


일관성 유지 전략: 다양한 Lock 전략 비교

여러 트랜잭션 격리 수준과 락 전략을 고민한 결과, 최종적으로 select for update 방식을 선택하게 되었습니다.

  • Serializable:
    • 장점: 팀 정보의 최신성을 보장
    • 단점: 성능 저하, 롤백 가능성 증가
    • 결론: 폐기
  • LockModeType.OPTIMISTIC:
    • 장점: 버전 기반 충돌 감지 가능
    • 단점: 일정 생성 시 팀의 변경 사항을 반영할 방법이 없음
    • 결론: 폐기
  • LockModeType.OPTIMISTIC_FORCE_INCREMENT:
    • 장점: 일정 생성 사실을 팀 도메인에 알릴 수 있음
    • 단점: 불필요한 충돌 및 롤백 발생, 직관성 부족
    • 결론: 폐기
  • DB 레벨 Check:
    • 단점: 특정 DB 기능에 종속되어 이식성 문제 발생
    • 결론: 폐기

image

  • select for update:
    • 장점:
      • 명시적이고 단순한 구현
      • 2PL(두 단계 락킹)을 통해 일관성 보장
      • 팀 레코드에 Shared Lock(일정 생성 시)과 Exclusive Lock(팀 정보 수정 시)을 통해 필요한 동시성 제어 수행
      image

실행 전략:

  • 일정 생성 시: 먼저 팀에 Shared Lock을 걸어 일정 생성 가능 여부를 확인
  • 팀 정보 수정 시: 팀에 Exclusive Lock을 걸어 다른 일정 생성과의 충돌을 차단
  • TeamPlanOrchestrationService에서 반드시 팀 레코드에 락을 먼저 획득하여 데드락 발생 가능성을 최소화