Skip to content

[#112] docs. 재매칭 중복 방지를 방 생성 시점으로 결정 (ADR 0013) - #113

Merged
howudong merged 1 commit into
mainfrom
feature/112
Jul 29, 2026
Merged

howudong merged 1 commit into
mainfrom
feature/112

Conversation

@howudong

@howudong howudong commented Jul 28, 2026 •

Copy link
Copy Markdown
Contributor

무엇을

재매칭 중복을 어디서 막을지 정하고 기록합니다. 코드 변경 없음 — 문서 2개뿐입니다.

Refs #112

문제

같은 두 사람이 한 주에 서로 다른 그룹에서 함께 만날 수 있습니다(퀴즈셋당 여러 그룹 + 한 멤버의 다중 그룹 참여, ADR 0008). 양쪽 평가에서 서로를 선택하면 rematch 두 행이 각각 MATCHED가 되고, 같은 주말에 같은 쌍의 방이 두 개 열립니다. DB는 정상으로 받아들이지만(chat_room 유일키가 rematch.id 기준), 두 사람이 서로 다른 방에 말을 걸어 상대가 답하지 않는다고 오해합니다.

기획 확인 결과 횟수 제한은 없었습니다(2026-07-27) — 한 주에 여러 명과 성사 가능, 같은 상대와 다른 주말 재성사도 허용. 막을 것은 중복 하나입니다.

결정

방을 만드는 시점(I2)에서 막습니다. 성사 트랜잭션은 중복을 신경 쓰지 않고 두 행 모두 MATCHED로 남깁니다(둘 다 사실). I2는 단일 스케줄러라 순차 처리되므로 잠금·유일키 같은 동시성 장치가 필요 없습니다.

검토했으나 채택하지 않은 대안

ADR에 근거를 남겼습니다.

  1. 성사 시점 slot 테이블 — 유일키 보유가 유일한 역할인데 테이블·엔티티·리포지토리·마이그레이션이 늘었고, 결정적으로 확보 실패를 save()의 유일키 위반 예외로 판정할 수 없습니다(제약 위반 예외 → Spring이 트랜잭션을 롤백 전용으로 마킹 → 같은 트랜잭션의 취소 전이가 커밋되지 못하고 제출 결과까지 유실, 재시도가 같은 경로를 반복하는 고착). 회피에 INSERT IGNORE + H2 MODE=MySQL이 필요했습니다.
  2. rematch에 nullable 컬럼 + UK — NULL-distinct로 조건부 유일성을 흉내낼 수 있으나, native 쓰기가 같은 행의 JPA 더티체킹과 충돌하고(@DynamicUpdate 필요, 또는 성사 로직을 SQL로 해체) 채팅 시각을 rematch에 두지 않는다는 ADR 0012 결정과 어긋납니다.
  3. 방을 둘 만들고 읽을 때 숨김 — 규칙이 모든 읽기 경로(목록·상세·전송 검증·STOMP 구독·A3)로 퍼지고, 두 사용자가 같은 방을 고르도록 결정적 규칙을 공유해야 하며, 숨긴 방도 멤버십 인가는 통과하므로 아무도 못 보는 곳에 메시지가 쌓입니다.

I2로 이월한 요구사항

  1. 방 생성 시 같은 쌍의 방이 이미 있으면 건너뜀 (두 성사가 방 하나 공유)
  2. A3는 성사 2건에 같은 chatRoomId를 채움
  3. 개방 시각이 지났고 종료 전이면 즉시 개방 (주말 중 성사 + 스케줄러 지연·운영 복구)
  4. 채팅 기간 계산은 I2 단일 책임, SSOT는 chat_room.opens_at/expires_at(C1)

부수 효과

  • Rematch의 취소 사유가 NOT_MUTUAL 하나로 유지되어 ADR 0012의 "cancel_reason 컬럼을 두지 않는다" 결정이 그대로 갑니다.
  • A2(리뷰 제출 API)가 슬롯을 만질 필요가 없어져 선행 조건이 모두 충족됐습니다.

이전 리비전

이 브랜치에 rematch_slot 구현이 올라가 있었으나 위 재검토로 폐기하고 force-push했습니다. 남은 것은 결정 기록뿐입니다.

🤖 Generated with Claude Code

같은 두 사람이 한 주에 여러 그룹에서 만나 양쪽 다 선택하면 rematch 두 행이 각각
성사되고, 같은 주말에 방이 둘 열려 대화가 갈라진다. 이 중복을 어디서 막을지 정한다.

성사 트랜잭션이 아니라 방을 만드는 I2 에서 막는다. 두 성사는 모두 MATCHED 로
남기고(둘 다 사실이다) 방만 하나 만든다. I2 는 단일 스케줄러라 잠금·유일키 같은
동시성 장치가 필요 없다.

검토했으나 채택하지 않은 대안 셋과 근거를 ADR 에 남긴다.

- 성사 시점 slot 테이블: 유일키 보유가 유일한 역할인데 대가가 컸고, 확보 실패를
  유일키 위반 예외로 판정하면 트랜잭션이 롤백 전용이 되어 취소 전이가 유실된다
- rematch 에 nullable 컬럼 + UK: native 쓰기가 같은 행의 더티체킹과 충돌하고,
  채팅 시각을 rematch 에 두지 않는다는 ADR 0012 결정과도 어긋난다
- 방을 둘 만들고 읽을 때 숨김: 규칙이 모든 읽기 경로로 퍼지고 숨긴 방에 메시지가
  쌓인다

취소 사유가 NOT_MUTUAL 하나로 유지되므로 ADR 0012 의 cancel_reason 유예 결정도
그대로 간다.

Refs #112

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@howudong howudong changed the title [#112] feat. 재매칭 slot — 같은 쌍·같은 채팅 기간 중복 성사 차단 [#112] docs. 재매칭 중복 방지를 방 생성 시점으로 결정 (ADR 0013) Jul 29, 2026
@sonarqubecloud

Copy link
Copy Markdown

@howudong
howudong merged commit 6ea0e60 into main Jul 29, 2026
2 checks passed
@howudong
howudong deleted the feature/112 branch July 29, 2026 05:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant