Skip to content

Comments

Participant 애그리거트 분리 작업#54

Open
xjvmdutl wants to merge 3 commits intodevelopfrom
feature-53/participant/aggregate-seperate
Open

Participant 애그리거트 분리 작업#54
xjvmdutl wants to merge 3 commits intodevelopfrom
feature-53/participant/aggregate-seperate

Conversation

@xjvmdutl
Copy link
Contributor

@xjvmdutl xjvmdutl commented Jul 29, 2025

🔍 PR 타입 선택

아래 타입 중 해당하는 하나를 선택해 주세요. 반드시 하나만 선택해 주세요.

  • feat: 새로운 기능 추가
  • fix: 버그 수정
  • refactor: 코드 리팩토링
  • test: 테스트 코드 추가 또는 수정

📝 변경 사항 요약

변경 사항을 간단히 요약해 주세요.

  • Refectoring
  • Participant 애그리거트 분리
  • 비지니스 로직 수정

🛠 관련 이슈

Resolves: #53
Ref: #48

추가 설명 (선택 사항)

  • 각자 본인이 작업한 API 변경 부분 확인해주세요
  • 누락된 테스트 코드나 비지니스 로직 빠진 부분 확인해주세요
  • @mandykr 님 TripService에서 ParticipantService를 주입 받아서 사용하는 방식으로 사용했는데, 검토 부탁드립니다(Repository를 주입 받는거 보다 좋은 방식인지..!)

junhokim added 3 commits July 27, 2025 18:26
- 수정 필요
- 테스트 코드 수정 필요
- 테스트 코드 수정
- Approve 비지니스 수정
@xjvmdutl xjvmdutl added this to the Sprint 1 milestone Jul 29, 2025
@xjvmdutl xjvmdutl requested a review from a team July 29, 2025 03:43
@xjvmdutl xjvmdutl requested review from ekfrehd, jisubaek and mandykr and removed request for a team July 29, 2025 03:43
@xjvmdutl xjvmdutl requested a review from pparkjs July 29, 2025 03:43
@xjvmdutl xjvmdutl changed the title 애그리거트 분리 작업 Participant 애그리거트 분리 작업 Jul 29, 2025
Comment on lines 46 to +61
public Page<InvitationsResponse> getTripInvitations(
UUID tripId, UUID leaderId, String status, Pageable page, TripInvitationOrder order, String sort) {
invitationPolicy.canViewInvitations(findTripWithParticipants(tripId), leaderId);
UUID tripId,
UUID leaderId,
String status,
Pageable page,
TripInvitationOrder order,
String sort) {
participantService.requireLeaderOrElseThrow(tripId, leaderId);
Pageable pageable = PaginationUtils.createPageRequest(page, order.getField(), sort);
Page<Invitation> tripInvitations =
invitationRepository.findByTripIdAndStatus(tripId, InvitationStatus.valueOf(status), pageable);
invitationRepository.findByTripIdAndStatus(
tripId, InvitationStatus.valueOf(status), pageable);
Copy link
Contributor

Choose a reason for hiding this comment

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

서비스간의 참조는 순환 참조 위험이 있어서 제한하는게 좋을것 같아요.
반드시 호출이 필요한 상황인지 먼저 확인하고 필요하다면 같은 서비스 내에 별도로 생성하는건 어떨까요?

Comment on lines +88 to +105
@Override
public Participant delegateLeader(UUID tripId, UUID currentLeaderId, UUID newLeaderId) {

Participant oldLeader =
participantQueryRepository
.findByTripIdAndMemberId(tripId, currentLeaderId)
.orElseThrow(() -> new NotParticipantException("현재 리더를 찾을 수 없습니다."));
Participant newLeader =
participantQueryRepository
.findByTripIdAndMemberId(tripId, newLeaderId)
.orElseThrow(
() ->
new NotParticipantException(
"새로운 리더가 될 멤버가 여행에 참여하고 있지 않습니다."));
participantPolicy.validateDelegate(oldLeader, newLeader);
participantPolicy.changeLeader(oldLeader, newLeader);
return newLeader;
}
Copy link
Contributor

@mandykr mandykr Aug 2, 2025

Choose a reason for hiding this comment

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

리더 위임도 TripService에서 호출하고 있네요. controller 부터 ParticipantService를 호출하는게 올바르게 분리된것 같아요. 전체적으로 설계에 대해 같이 논의해볼 필요가 있을것 같네요.

participantPolicy.changeLeader(oldLeader, newLeader);
이부분은 Participants의 책임인것 같아요

Copy link
Contributor

@mandykr mandykr left a comment

Choose a reason for hiding this comment

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

애그리거트 분리와 Policy 도메인 서비스 활용이 잘 된것 같아요.
다만 서비스간의 참조와 일급 컬렉션 활용만 참고해주시면 좋을것 같습니다.

Comment on lines +114 to +123
@Override
public List<Participant> banMembers(UUID tripId, UUID loginMemberId, List<UUID> memberIds) {
requireLeaderOrElseThrow(tripId, loginMemberId);
List<Participant> participants = participantRepository.findByTripId(tripId);
participantPolicy.validateBan(participants, memberIds);
List<Participant> participantsToBan =
participants.stream().filter(m -> memberIds.contains(m.getMemberId())).toList();
participantsToBan.forEach(Participant::ban);
return participantsToBan;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

List participants 리스트를 다루는 부분은 Participants 일급컬렉션을 활용하는것도 좋을것 같아요

Copy link
Contributor

@pparkjs pparkjs left a comment

Choose a reason for hiding this comment

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

분리하느라 고생하셨습니다!!
TripService에서 ParticipantService를 호출하는 문제는 제가 답변 적은 부분에서 한 번 고려해보시는 것도 좋을 거 같아요!

Comment on lines +129 to +135
@Override
public void banMembers(UUID loginMemberId, UUID tripId, List<UUID> memberIds) {
Trip trip = findTrip(tripId);
trip.canBan();
List<Participant> participants =
participantService.banMembers(tripId, loginMemberId, memberIds);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

홍석님의 비밀번호 관련 PR을 보면 참가자 애그리거트 분리를 대비하여 참가자 controller를 만드셔서 참가자 추방 API는 참가자 Controller에 뺴면 tripService에서 participantService를 호출 하여 순환참조에 위험이 있을 수 있는 문제를 해결 할 수 있을 거 같습니다!

Comment on lines +78 to +95
@Override
public TripDemandApproveResponse approve(
UUID memberId, UUID approverMemberId, UUID tripId, UUID tripDemandId) {
TripDemand tripDemand = findTripDemandByTripIdAndTripDemandId(tripId, tripDemandId);
participantService.requireLeaderOrElseThrow(tripId, memberId);
tripDemand.approve();
participantService.createParticipant(
tripId, approverMemberId, tripDemand.getTrip().getMaxParticipants());
return TripDemandApproveResponse.of(tripDemand);
}

@Override
public TripDemandRejectResponse reject(UUID memberId, UUID tripId, UUID joinRequestId) {
TripDemand tripDemand = findTripDemandByTripIdAndTripDemandId(tripId, joinRequestId);
participantService.requireLeaderOrElseThrow(tripId, memberId);
tripDemand.reject();
return TripDemandRejectResponse.of(tripDemand);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

해당 API도 참가자 controller로 이동시키면 위와 같은 문제 해결 될 거 같습니다!

Comment on lines +51 to +56
public Participant createParticipant(UUID tripId, UUID memberId, int maxParticipants) {
Long currentCount = participantQueryRepository.findByTripIdCount(memberId);
participantPolicy.validate(maxParticipants, currentCount + 1);
return participantRepository.save(
Participant.create(tripId, memberId, ParticipantRole.PARTICIPANT));
}
Copy link
Contributor

Choose a reason for hiding this comment

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

참가자 승인을 동시에 눌렀을떄 인원이 넘어도 저장되는 문제 상관없겠죠?? 리더는 어차피 한명이니 승인을 동시에 누를일이 없으니

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Trip Participant 애그리거트 분리

4 participants