Skip to content

fix: 시트 동기화 시 사전 회원 유지#490

Merged
JanooGwan merged 5 commits intodevelopfrom
fix/sheet-sync-preserve-pre-members
Apr 1, 2026
Merged

fix: 시트 동기화 시 사전 회원 유지#490
JanooGwan merged 5 commits intodevelopfrom
fix/sheet-sync-preserve-pre-members

Conversation

@JanooGwan
Copy link
Copy Markdown
Contributor

🔍 개요

  • POST /clubs/{clubId}/members/sheet-sync 실행 시 club_member만 기준으로 시트를 다시 써서, 기존 club_pre_member 인명부가 시트에서 사라지던 문제를 수정했습니다.

🚀 주요 변경 내용

  • SheetSyncExecutorclub_memberclub_pre_member를 함께 읽어 공통 row 모델로 정렬 후 시트에 기록하도록 수정했습니다.
  • ClubMemberSheetService가 동기화 응답의 syncedMemberCount에 사전 회원 수까지 포함하도록 보정했습니다.
  • ClubPreMemberRepositorycountByClubId를 추가하고, API/응답 Swagger 문구를 실제 동작에 맞게 회원+사전 회원 기준으로 정리했습니다.
  • SheetSyncExecutorTest에 회원과 사전 회원이 함께 시트에 기록되는 테스트를 추가했고, ClubMemberSheetServiceTest를 추가해 응답 카운트 보정을 검증했습니다.

💬 참고 사항

  • 사전 회원은 이메일·전화번호가 없으므로 시트에는 해당 컬럼을 빈 값으로 기록합니다.
  • 정렬 기준은 기존 sortKey 규칙을 유지하되, 사전 회원도 동일 기준으로 함께 정렬됩니다.
  • 검증은 ./gradlew.bat test --tests "gg.agit.konect.domain.club.service.SheetSyncExecutorTest" --tests "gg.agit.konect.domain.club.service.ClubMemberSheetServiceTest"./gradlew.bat checkstyleMain으로 확인했습니다.

✅ Checklist (완료 조건)

  • 코드 스타일 가이드 준수
  • 테스트 코드 포함됨
  • Reviewers / Assignees / Labels 지정 완료
  • 보안 및 민감 정보 검증 (API 키, 환경 변수, 개인정보 등)

@JanooGwan JanooGwan added the 버그 정상적으로 동작하지 않는 문제 상황 관련 이슈입니다. label Apr 1, 2026
@JanooGwan JanooGwan self-assigned this Apr 1, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 1, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: ab0d42d2-92ea-4e49-87b2-4a523be630b4

📥 Commits

Reviewing files that changed from the base of the PR and between 1271b37 and f82a468.

📒 Files selected for processing (3)
  • src/main/java/gg/agit/konect/domain/club/dto/ClubMemberSheetSyncResponse.java
  • src/main/java/gg/agit/konect/domain/club/service/ClubMemberSheetService.java
  • src/test/java/gg/agit/konect/domain/club/service/SheetSyncExecutorTest.java

📝 Walkthrough

Walkthrough

Google Sheets 동기화가 기존의 동아리 회원에 더해 사전 회원을 포함하도록 확장되었습니다. 리포지토리(countByClubId), 서비스(총합 계산), 실행자(통합 행 매핑·정렬·쓰기)와 관련 테스트 및 Swagger 문서가 업데이트되었습니다.

변경 사항

Cohort / File(s) Summary
API 문서 및 응답 DTO
src/main/java/gg/agit/konect/domain/club/controller/ClubMemberSheetApi.java, src/main/java/gg/agit/konect/domain/club/dto/ClubMemberSheetSyncResponse.java
동기화 설명 및 응답 스키마 메타데이터를 사전 회원 포함으로 수정(주석/Swagger 텍스트 변경).
리포지토리 계층
src/main/java/gg/agit/konect/domain/club/repository/ClubPreMemberRepository.java
countByClubId(Integer clubId) 메서드 추가로 특정 동아리의 사전 회원 수 조회 기능 확장.
서비스 계층
src/main/java/gg/agit/konect/domain/club/service/ClubMemberSheetService.java
ClubPreMemberRepository 주입 및 동기화 시 멤버/사전멤버 수를 합산하여 응답 생성하도록 변경.
실행자 클래스
src/main/java/gg/agit/konect/domain/club/service/SheetSyncExecutor.java
사전 회원 로드 추가, SheetSyncRow 레코드 도입으로 ClubMember/ClubPreMember를 통합 매핑·정렬·시트 작성 로직으로 전환. 로그에 preMembers 카운트 추가.
테스트 추가/수정
src/test/java/gg/agit/konect/domain/club/service/ClubMemberSheetServiceTest.java, src/test/java/gg/agit/konect/domain/club/service/SheetSyncExecutorTest.java
사전 회원 포함 동기화 동작과 시트에 쓰여지는 행을 검증하는 단위 테스트 및 테스트 헬퍼(리플렉션) 추가.

시퀀스 다이어그램

sequenceDiagram
    actor User
    participant ClubMemberSheetService
    participant ClubMemberRepository
    participant ClubPreMemberRepository
    participant SheetSyncExecutor
    participant GoogleSheetsAPI as "Google Sheets API"

    User->>ClubMemberSheetService: syncMembersToSheet(clubId, sortKey, includePreMembers)
    ClubMemberSheetService->>ClubMemberRepository: count(clubId)
    ClubMemberRepository-->>ClubMemberSheetService: memberCount
    ClubMemberSheetService->>ClubPreMemberRepository: countByClubId(clubId)
    ClubPreMemberRepository-->>ClubMemberSheetService: preMemberCount
    Note over ClubMemberSheetService: totalCount = memberCount + preMemberCount
    ClubMemberSheetService->>SheetSyncExecutor: executeWithSort(clubId, sortKey, includePreMembers)
    SheetSyncExecutor->>ClubMemberRepository: findAllByClubId(clubId)
    ClubMemberRepository-->>SheetSyncExecutor: clubMembers
    SheetSyncExecutor->>ClubPreMemberRepository: findAllByClubId(clubId)
    ClubPreMemberRepository-->>SheetSyncExecutor: preMembers
    Note over SheetSyncExecutor: map -> SheetSyncRow[] -> sort -> build ValueRange
    SheetSyncExecutor->>GoogleSheetsAPI: clear(spreadsheetId) + update(values)
    GoogleSheetsAPI-->>SheetSyncExecutor: updateResponse
    SheetSyncExecutor-->>ClubMemberSheetService: success
    ClubMemberSheetService-->>User: ClubMemberSheetSyncResponse(totalCount, sheetUrl)
Loading

예상 코드 리뷰 난이도

🎯 4 (Complex) | ⏱️ ~45 minutes

관련 PR

개요

Google Sheets 동기화 기능을 확장하여 일반 동아리 회원("동아리 회원")에 더하여 사전 회원("사전 회원 인명부")도 포함하도록 업데이트했습니다. 리포지토리, 서비스, 실행자 클래스에서 사전 회원을 처리하기 위한 로직을 추가하고, 관련 Swagger 문서를 수정하였으며, 새로운 기능에 대한 포괄적인 테스트를 추가했습니다.

변경 사항 (요약 한국어)

Cohort / File(s) 요약
API 문서 및 응답 DTO
src/main/java/gg/agit/konect/domain/club/controller/ClubMemberSheetApi.java, src/main/java/gg/agit/konect/domain/club/dto/ClubMemberSheetSyncResponse.java
Google Sheets 동기화 작업에 사전 회원 포함을 반영하여 Swagger @Operation 설명과 @Schema 메타데이터를 업데이트했습니다.
리포지토리 계층
src/main/java/gg/agit/konect/domain/club/repository/ClubPreMemberRepository.java
countByClubId(Integer clubId) 메서드를 추가하여 특정 동아리의 사전 회원 수를 조회할 수 있도록 확장했습니다.
서비스 계층
src/main/java/gg/agit/konect/domain/club/service/ClubMemberSheetService.java
ClubPreMemberRepository 의존성을 추가하고, 동기화 시 사전 회원 수를 포함하여 총 회원 수를 계산하도록 수정했습니다.
실행자 클래스
src/main/java/gg/agit/konect/domain/club/service/SheetSyncExecutor.java
사전 회원을 추가로 로드하고, 일반 회원과 사전 회원을 통합된 내부 행 표현(SheetSyncRow)으로 변환하여 처리하는 로직을 추가했습니다. 새로운 SheetSyncRow 레코드를 도입하여 양쪽 회원 유형을 일관되게 처리합니다.
테스트 추가
src/test/java/gg/agit/konect/domain/club/service/ClubMemberSheetServiceTest.java, src/test/java/gg/agit/konect/domain/club/service/SheetSyncExecutorTest.java
사전 회원을 포함한 동기화 기능과 행 생성 로직을 검증하는 새로운 테스트 케이스와 헬퍼 메서드를 추가했습니다.

시 🐰

동아리와 사전 회원 손잡고,
시트 위에 줄지어 모였네,
작은 발자국으로 정리하고,
SheetSyncRow로 깔끔히 정렬해,
당근 한 입, 변화 축하해요! 🥕🐇

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 '시트 동기화 시 사전 회원 유지'로, 변경사항의 핵심인 sheet sync 실행 시 기존 pre-member 명단이 사라지던 문제 해결을 정확히 설명하고 있습니다.
Description check ✅ Passed PR 설명은 문제 상황, 주요 변경 내용, 구현 세부사항, 테스트 검증, 체크리스트 등을 상세히 기재하여 변경사항과 직접적으로 관련이 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sheet-sync-preserve-pre-members

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

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

POST /clubs/{clubId}/members/sheet-sync 실행 시 시트에 **사전 회원(ClubPreMember)**까지 함께 기록되어, 동기화 과정에서 사전 회원 인명부가 사라지던 문제를 해결하는 PR입니다.

Changes:

  • SheetSyncExecutorclub_member + club_pre_member를 통합(Row 모델로 변환)해 정렬/기록하도록 변경
  • ClubMemberSheetService 동기화 응답의 syncedMemberCount에 사전 회원 수를 합산하도록 보정
  • 사전 회원 카운트용 ClubPreMemberRepository.countByClubId 추가 및 Swagger 문구/테스트 보강

Reviewed changes

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

Show a summary per file
File Description
src/main/java/gg/agit/konect/domain/club/service/SheetSyncExecutor.java 회원/사전회원 통합 Row로 변환 후 동일 정렬 규칙으로 시트에 기록하도록 수정
src/main/java/gg/agit/konect/domain/club/service/ClubMemberSheetService.java 응답 카운트에 사전 회원 수를 합산하도록 변경
src/main/java/gg/agit/konect/domain/club/repository/ClubPreMemberRepository.java 사전 회원 수 집계를 위한 countByClubId 추가
src/main/java/gg/agit/konect/domain/club/dto/ClubMemberSheetSyncResponse.java syncedMemberCount 설명을 “회원 및 사전 회원” 기준으로 정리
src/main/java/gg/agit/konect/domain/club/controller/ClubMemberSheetApi.java 시트 동기화 API 설명을 실제 동작(회원+사전회원)과 일치시킴
src/test/java/gg/agit/konect/domain/club/service/SheetSyncExecutorTest.java 회원+사전회원이 함께 시트에 기록되는 케이스 테스트 추가
src/test/java/gg/agit/konect/domain/club/service/ClubMemberSheetServiceTest.java 응답 카운트 보정(회원+사전회원 합산) 검증 테스트 추가

sheetSyncExecutor.executeWithSort(clubId, sortKey, ascending);

return ClubMemberSheetSyncResponse.of((int)memberCount, spreadsheetId);
return ClubMemberSheetSyncResponse.of((int)(memberCount + preMemberCount), spreadsheetId);
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

memberCount/preMemberCount가 long인데 (int)(memberCount + preMemberCount)로 캐스팅하면 범위 초과 시 값이 잘려서 syncedMemberCount가 잘못될 수 있습니다. 최소한 Math.toIntExact(memberCount + preMemberCount)로 변환해 오버플로우를 즉시 감지하거나, 응답 DTO 타입을 long으로 올려 안전하게 처리하는 쪽을 검토해 주세요.

Suggested change
return ClubMemberSheetSyncResponse.of((int)(memberCount + preMemberCount), spreadsheetId);
return ClubMemberSheetSyncResponse.of(Math.toIntExact(memberCount + preMemberCount), spreadsheetId);

Copilot uses AI. Check for mistakes.
}

private void setCreatedAt(Object target, LocalDateTime createdAt) throws Exception {
Field createdAtField = target.getClass().getSuperclass().getDeclaredField("createdAt");
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

테스트의 setCreatedAt()이 target.getClass().getSuperclass()에 createdAt 필드가 있다고 가정하고 있어(직접 상속 구조가 바뀌면 즉시 깨짐) 리팩터링에 취약합니다. BaseEntity.class에서 필드를 가져오거나, 상위 클래스를 따라 올라가며 createdAt을 찾는 방식으로 의존을 줄이는 편이 안전합니다.

Suggested change
Field createdAtField = target.getClass().getSuperclass().getDeclaredField("createdAt");
Class<?> current = target.getClass();
Field createdAtField = null;
while (current != null) {
try {
createdAtField = current.getDeclaredField("createdAt");
break;
} catch (NoSuchFieldException e) {
current = current.getSuperclass();
}
}
if (createdAtField == null) {
throw new NoSuchFieldException(
"Field 'createdAt' not found in class hierarchy of " + target.getClass()
);
}

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

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

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

Comment on lines 80 to 86
@@ -80,7 +84,12 @@ public void executeWithSort(Integer clubId, ClubSheetSortKey sortKey, boolean as
clearAndWriteAll(spreadsheetId, sorted);
applyFormat(spreadsheetId);
}
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

현재 추가된 테스트는 club.getSheetColumnMapping()이 null인 경우(전체 clear 후 values.update로 덮어쓰기)만 검증합니다. 실제 운영에서는 시트 등록 시 sheetColumnMapping이 저장되어 updateMappedColumns(values.batchUpdate 경로)로 동작하는 경우가 많으니, 해당 경로에서도 사전 회원이 함께 반영되는지(예: BatchUpdateValuesRequest에 preMember row가 포함되는지) 테스트를 추가하는 것이 좋겠습니다.

Copilot uses AI. Check for mistakes.

public record ClubMemberSheetSyncResponse(
@Schema(description = "동기화된 회원 수", example = "42")
@Schema(description = "동기화된 회원 및 사전 회원 수", example = "42")
Copy link

Copilot AI Apr 1, 2026

Choose a reason for hiding this comment

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

syncMembersToSheet는 @async로 시트 동기화를 비동기로 실행하지만, 응답 필드/Swagger 설명은 '동기화된' 것으로 표기되어 실제로는 '요청 시점 기준 동기화 대상(또는 예상) 인원'에 가깝습니다. 비동기 실행 사실을 반영해 description 문구를 조정하거나(예: "동기화 요청된 회원 및 사전 회원 수"), 동기화 완료 후의 결과를 반환하도록 동작을 맞추는 쪽 중 하나로 정합성을 맞춰주세요.

Suggested change
@Schema(description = "동기화된 회원 및 사전 회원 수", example = "42")
@Schema(description = "동기화 요청된 회원 및 사전 회원 수", example = "42")

Copilot uses AI. Check for mistakes.
@JanooGwan JanooGwan merged commit 6782851 into develop Apr 1, 2026
3 of 4 checks passed
@JanooGwan JanooGwan deleted the fix/sheet-sync-preserve-pre-members branch April 1, 2026 12:16
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.

2 participants