Skip to content

Application Service 도메인 로직 누출 제거: Votes·Platform 도메인 객체로 추출#843

Merged
m-a-king merged 2 commits intobe/devfrom
be/refactor/room-application-service
Mar 14, 2026
Merged

Application Service 도메인 로직 누출 제거: Votes·Platform 도메인 객체로 추출#843
m-a-king merged 2 commits intobe/devfrom
be/refactor/room-application-service

Conversation

@m-a-king
Copy link
Copy Markdown
Contributor

배경: 왜 서비스 분리나 엔티티 연관 관계 개선이 아닌 도메인 객체 추출인가

Room → Participant → Vote, Room → Platform은 하나의 애그리거트 경계 안에 있는 올바른 계층 구조입니다. DDD 교과서대로라면 JPA 연관관계를 통해 애그리거트를 통째로 로드하고 루트(Room)가 하위 엔티티를 직접 조율하는 것이 자연스럽습니다.

하지만 현재 설계는 의도적으로 ID 참조 기반을 선택했고, 그 위에 다음 최적화가 구축되어 있습니다:

  • VotePersistable 구현 → 신규 엔티티 INSERT 시 SELECT 제거
  • 배치 deleteAllInBatch / saveAll → 벌크 연산
  • participantRepository.findIdsByRoomId() → 필요한 ID만 조회

JPA 연관관계로 전환하면 이 최적화를 포기하고, 지연 로딩 전략·N+1 문제를 새로 관리해야 합니다. 서비스를 분리하는 것도 같은 애그리거트 내 엔티티를 다루는 이상 책임 경계가 모호해집니다.

따라서 ID 참조와 Application Service의 조율 역할은 유지하되, 서비스에 누출된 도메인 지식만 도메인 객체로 내리는 접근을 선택했습니다.

동기: 서비스에 누출된 도메인 지식 3건

RoomApplicationService가 조율 역할을 넘어 "왜 이렇게 하는가"에 해당하는 도메인 지식까지 직접 수행하고 있었습니다.

  • subtract 두 번 호출 → "기존 대비 변경분 계산"이라는 개념이 숨겨짐
  • Map<DateTimeSlot, Set<Long>> 직접 조작 → 통계 집계·참여자 추출 로직이 서비스에 노출
  • PlatformNotificationType.values() 순회 + 필터링 → "플랫폼이 어떤 알림을 스케줄하는가"라는 규칙이 서비스에 존재

Diff·StatisticVotes의 inner record로 둔 이유

둘 다 Votes의 연산 결과이며 Votes 없이 단독으로 생성되지 않습니다. 별도 파일로 분리하면 파일 수만 늘고 소속이 모호해지지만, inner record로 두면 Votes.Diff, Votes.Statistic이라는 이름에서 소속과 의도가 동시에 드러납니다. 이는 프로젝트의 기존 패턴(DateTimeSlotStatisticOutput.DateTimeParticipantsOutput 등)과도 일관됩니다.

@m-a-king m-a-king changed the title room application service Application Service 도메인 로직 누출 제거: Votes·Platform 도메인 객체로 추출 Mar 14, 2026
@m-a-king m-a-king self-assigned this Mar 14, 2026
@m-a-king m-a-king added BE Backend ♻️ refactor 리팩토링 labels Mar 14, 2026
@m-a-king m-a-king merged commit 6ce347e into be/dev Mar 14, 2026
1 check passed
@m-a-king m-a-king deleted the be/refactor/room-application-service branch March 14, 2026 14:59
@m-a-king m-a-king requested a review from Copilot March 14, 2026 15:00
@m-a-king
Copy link
Copy Markdown
Contributor Author

@codex review

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR moves domain rules that had leaked into RoomApplicationService down into domain objects (Votes, Platform) while keeping the existing ID-reference + bulk-operation approach.

Changes:

  • Extract vote delta calculation into Votes.diff() and vote aggregation into Votes.calculateStatistic() returning Votes.Statistic.
  • Extract platform notification scheduling/outbox creation into Platform.createNotificationOutboxes(...).
  • Update RoomApplicationService to use the new domain APIs and add unit tests for Votes/Platform.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
core/src/main/java/com/estime/room/platform/Platform.java Adds outbox creation logic based on enabled notification types.
core/src/main/java/com/estime/room/participant/vote/Votes.java Introduces Votes.Diff and Votes.Statistic domain results and refactors service-facing logic into Votes.
application/src/main/java/com/estime/room/service/RoomApplicationService.java Replaces in-service domain logic with calls to Platform/Votes domain APIs.
core/src/test/java/com/estime/room/platform/PlatformTest.java Adds tests verifying outbox creation is filtered by notification settings.
core/src/test/java/com/estime/room/participant/vote/VotesDiffTest.java Adds tests for vote diff behavior.
core/src/test/java/com/estime/room/participant/vote/VoteStatisticTest.java Adds tests for vote statistics queries (allParticipantIds, slots, per-slot ids).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Keep it up!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

BE Backend ♻️ refactor 리팩토링

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

2 participants