Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 스터디 출석체크 V2 API 작성 #942

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from

Conversation

kckc0608
Copy link
Member

@kckc0608 kckc0608 commented Feb 26, 2025

🌱 관련 이슈

📌 작업 내용 및 특이사항

  • 스터디 출석체크 API 작성

📝 참고사항

  • 기존에는 StudyDetail 에 있는 출석체크 날짜를 기반으로 검증했는데, 바뀐 명세에 따라 StudySession 에 있는 LessonPeriod 기반으로 출석 가능 기간 검증을 진행했습니다.
  • 일단 기존 api 명세 따라서 /studies 로 뒀는데, studyId 없이 바로 /attend 로 끝내고 study session id 를 쿼리로 받으니까 어색한 것 같더라구요. /study-sessions 로 해볼까 해도 그때는 쿼리 파라미터보다 패스 파라미터로 받아서 /attend 로 끝내는 게 더 자연스러울 것 같고, /study-histories 로 빼면 과거 수강 이력에 대한 api 와 섞이는 것 같아 고민되는데 좋은 네이밍 아이디어 있을까요..

📚 기타

Summary by CodeRabbit

  • 신규 기능
    • 출석 체크 기능이 강화되어, 출석번호 입력 시 자동 검증(시간 제한, 중복 체크, 번호 일치 여부)을 수행합니다.
    • 사용자가 출석 처리 시 적절한 오류 메시지(예: 강의시간 외 출석, 중복 출석 처리)를 확인할 수 있습니다.
    • 학습 세션 별 출석 이력 관리 및 확인 기능이 추가되어 사용자 경험이 개선되었습니다.

@kckc0608 kckc0608 self-assigned this Feb 26, 2025
@kckc0608 kckc0608 requested a review from a team as a code owner February 26, 2025 18:11
Copy link

coderabbitai bot commented Feb 26, 2025

📝 Walkthrough

Walkthrough

이번 PR에서는 스터디 출석 관리 기능이 추가되고 개선되었습니다.
새로운 인터페이스와 클래스들을 도입하여 출석 기록 존재 여부를 확인하고, 출석 유효성을 검증하는 로직이 구현되었습니다.
출석 생성 요청을 위한 DTO가 추가되었으며, 관련 예외 처리를 위한 에러 코드도 보완되어
프론트엔드와의 통신을 위한 REST 컨트롤러와 이를 처리하는 서비스 계층이 구성되었습니다.

Changes

File(s) Change Summary
src/main/java/com/gdschongik/gdsc/.../dao/AttendanceV2Repository.java
src/main/java/com/gdschongik/gdsc/.../dao/StudyHistoryV2Repository.java
Attendance 관련 레포지토리 인터페이스 추가 및 기존 레포지토리에 학생, 스터디/스터디 세션 기반 존재 여부 확인 메서드 도입
src/main/java/com/gdschongik/gdsc/.../domain/AttendanceValidatorV2.java 출석 검증 로직을 담은 도메인 서비스 클래스 추가 – 출석 요청 유효성, 중복 출석, 출석 시간 조건 등의 검증 로직 구현
src/main/java/com/gdschongik/gdsc/.../dto/request/AttendanceCreateRequest.java 출석 생성 요청을 위한 레코드 추가 – 출석 번호 필드에 유효성 검증 어노테이션 적용
src/main/java/com/gdschongik/gdsc/.../global/exception/ErrorCode.java 출석 관련 예외 처리를 위한 두 개의 새로운 에러 코드(ATTENDANCE_PERIOD_INVALID, STUDY_SESSION_ALREADY_ATTENDED) 추가
src/main/java/com/gdschongik/gdsc/.../api/StudentAttendanceControllerV2.java 출석 처리를 위한 REST 컨트롤러 추가 – /v2/attendances 엔드포인트 및 출석 API 구현
src/main/java/com/gdschongik/gdsc/.../application/StudentAttendanceServiceV2.java 출석 처리를 담당하는 서비스 클래스 추가 – 사용자 인증, 스터디 조회, 출석 중복 확인, 검증 및 출석 저장 로직 구현

Sequence Diagram(s)

sequenceDiagram
    participant Student
    participant Controller as StudentAttendanceControllerV2
    participant Service as StudentAttendanceServiceV2
    participant StudyRepo as StudyV2Repository/StudyHistoryV2Repository
    participant AttendanceRepo as AttendanceV2Repository
    participant Validator as AttendanceValidatorV2

    Student->>Controller: POST /v2/attendances/attend?studySessionId\n(AttendanceCreateRequest)
    Controller->>Service: attend(studySessionId, request)
    Service->>StudyRepo: findFetchBySessionId(studySessionId)
    StudyRepo-->>Service: StudyV2 (with StudySessionV2)
    Service->>StudyRepo: existsByStudentAndStudy(currentMember, StudyV2)
    Service->>AttendanceRepo: existsByStudentAndStudySession(currentMember, StudySessionV2)
    Service->>Validator: validateAttendance(StudySessionV2, attendanceNumber, isApplied, isAttended)
    Validator-->>Service: (pass or throw exception)
    Service->>AttendanceRepo: save(new AttendanceV2)
    Service->>Controller: return ResponseEntity OK
    Controller-->>Student: HTTP 200 OK
Loading

Possibly related PRs

Suggested labels

✨ feature, ⚓ Domain: Study

Poem

안녕, 나의 귀여운 토끼 친구,
새 출석 시스템이 춤추듯 탄생했네,
Validator와 Repository가 깔끔하게 맞물리고,
컨트롤러와 서비스가 한 목소리로 노래하네.
당근 같은 성공을 향해 달려가며,
우리 코드 세상에 즐거운 발자취를 남기네 🥕✨
늘 행복한 스터디, 함께 뛰놀자!

✨ Finishing Touches
  • 📝 Generate Docstrings

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Hello @kckc0608, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

Summary of Changes

This pull request implements the Study Attendance Check V2 API. It includes a new controller, service, repository interfaces, a validator, and a request DTO. The changes involve validating attendance based on the StudySession's LessonPeriod instead of the StudyDetail's attendance date, as per the updated specifications. It also includes checks for study application status and existing attendance records.

Highlights

  • New API Endpoint: A new API endpoint /v2/studies/{studyId}/attend is created to handle student attendance checks for studies.
  • Attendance Validation: Attendance validation is now based on StudySession and its LessonPeriod, ensuring checks for attendance period, attendance number, study application status, and existing attendance records.
  • Data Access Layers: New repository interfaces (AttendanceV2Repository, StudyHistoryV2Repository) are added to handle data access for attendance and study history.

Changelog

Click here to see the changelog
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentStudyControllerV2.java
    • Created a new StudentStudyControllerV2 to handle the attendance check API endpoint.
    • Implemented the attend method to receive studyId, studySessionId, and AttendanceCreateRequest.
    • The controller uses the StudentStudyServiceV2 to process the attendance check.
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java
    • Created a new StudentStudyServiceV2 to handle the business logic for attendance checks.
    • Implemented the attend method to validate and record student attendance.
    • The service retrieves study and session information, validates attendance, and saves the attendance record.
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/AttendanceV2Repository.java
    • Created AttendanceV2Repository interface to manage AttendanceV2 entities.
    • Added a method to check if a student has already attended a specific study session.
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java
    • Added existsByStudentAndStudy method to check if a student has applied to a study.
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java
    • Created AttendanceValidatorV2 to encapsulate attendance validation logic.
    • Implemented validateAttendance method to check attendance period, number, study application, and existing attendance.
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/AttendanceCreateRequest.java
    • Created AttendanceCreateRequest record to encapsulate the attendance number.
    • Added validation constraints to ensure the attendance number matches the expected format.
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java
    • Added ATTENDANCE_PERIOD_INVALID error code for invalid attendance periods.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point in your pull request via creating an issue comment (i.e. comment on the pull request page) using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in issue comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist is currently in preview and may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments to provide feedback.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Trivia time!

What is the purpose of the @Transactional annotation in Spring?

Click here for the answer
The `@Transactional` annotation in Spring is used to define the scope of a transaction. When a method is annotated with `@Transactional`, Spring automatically begins a new transaction before the method execution and commits the transaction upon successful completion of the method. In the event of an exception, the transaction is rolled back.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The code changes introduce a new API endpoint for student attendance check-in. The implementation is generally well-structured, but I've left a few suggestions for improvement. It's recommended to address these comments before requesting a review from someone else. Feel free to request another review from Gemini via /gemini review when you have addressed these comments and I'll take another look! Remember to have others review and approve this code before merging.

Summary of Findings

  • Exception Handling: Consider centralizing exception handling or providing more specific error messages for better debugging.
  • Code Readability: Improve code readability by adding comments to explain complex logic or non-obvious operations.
  • Logging: Ensure logging is consistent and provides sufficient information for monitoring and troubleshooting.

Assessment

The code introduces a new API endpoint for student attendance check-in, which is a valuable addition to the application. The implementation appears to be well-structured and includes necessary validations. However, there are a few areas where improvements can be made to enhance code clarity and maintainability. Addressing these comments before merging is recommended, and it's crucial to have another team member review and approve this code before merging.

Comment on lines 40 to 42
.filter(studySession -> Objects.equals(studySession.getId(), studySessionId))
.findFirst()
.orElseThrow(() -> new CustomException(STUDY_NOT_UPDATABLE_SESSION_NOT_FOUND));

Choose a reason for hiding this comment

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

medium

Consider adding a more descriptive message to the CustomException to provide better context when the StudySession is not found. This can aid in debugging and troubleshooting.

For example, include the studyId and studySessionId in the error message.

                .orElseThrow(() -> new CustomException(STUDY_NOT_UPDATABLE_SESSION_NOT_FOUND, "StudySession not found for studyId: " + studyId + ", studySessionId: " + studySessionId));

Comment on lines +11 to +13
@Pattern(regexp = ATTENDANCE_NUMBER, message = "출석번호는 " + ATTENDANCE_NUMBER + " 형식이어야 합니다.")
@Schema(description = "출석번호")
String attendanceNumber) {}

Choose a reason for hiding this comment

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

medium

Consider extracting the message "출석번호는 " + ATTENDANCE_NUMBER + " 형식이어야 합니다." to a constant to avoid duplication and improve maintainability. This also makes it easier to update the message in one place if needed.

import static com.gdschongik.gdsc.global.common.constant.RegexConstant.ATTENDANCE_NUMBER;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;

public record AttendanceCreateRequest(
        @NotBlank
                @Pattern(regexp = ATTENDANCE_NUMBER, message = AttendanceCreateRequest.ATTENDANCE_NUMBER_MESSAGE)
                @Schema(description = "출석번호")
                String attendanceNumber) {

    private static final String ATTENDANCE_NUMBER_MESSAGE = "출석번호는 " + ATTENDANCE_NUMBER + " 형식이어야 합니다.";
}

Copy link

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentStudyControllerV2.java (1)

17-33: 컨트롤러 구현이 잘 되어 있습니다.

컨트롤러 구현이 RESTful 원칙을 잘 따르고 있으며, 관심사 분리가 명확합니다. 컨트롤러는 HTTP 요청 처리만 담당하고 비즈니스 로직은 서비스 계층에 위임하고 있습니다.

한 가지 개선점으로는 Swagger 문서에 발생 가능한 오류 응답에 대한 정보를 추가하는 것이 좋겠습니다. API 사용자가 어떤 에러코드를 기대할 수 있는지 알 수 있도록 @ApiResponse 애노테이션을 추가하는 것을 고려해보세요.

src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (1)

14-35: 검증 로직이 명확하게 구현되어 있습니다.

검증 메서드가 책임 분리 원칙에 따라 명확하게 구현되어 있으며 필요한 모든 검증을 수행하고 있습니다.

다만 26번 라인의 주석이 실제 검증 내용과 일치하지 않습니다. 해당 부분은 출석체크 번호를 검증하는 것이 아니라 출석 중복 여부를 검증하는 로직입니다.

주석을 다음과 같이 수정하는 것이 좋겠습니다:

-        // 출석체크 번호 검증
+        // 출석 중복 검증
        if (isAlreadyAttended) {
            throw new CustomException(STUDY_DETAIL_ALREADY_ATTENDED);
        }
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (1)

39-42: 스터디 세션 조회 방식 개선 제안

현재 코드는 스터디를 조회한 후 메모리에서 특정 세션을 필터링하는 방식으로 구현되어 있습니다. 스터디 세션이 많은 경우 성능 저하가 발생할 수 있습니다.

레포지토리에 스터디 ID와 세션 ID로 직접 세션을 조회하는 메서드를 추가하여 DB 수준에서 필터링하는 것이 더 효율적일 수 있습니다.

// StudySessionV2Repository에 다음 메서드 추가 제안
Optional<StudySessionV2> findByIdAndStudyId(Long sessionId, Long studyId);

그리고 서비스 코드를 다음과 같이 수정:

-        StudySessionV2 session = study.getStudySessions().stream()
-                .filter(studySession -> Objects.equals(studySession.getId(), studySessionId))
-                .findFirst()
-                .orElseThrow(() -> new CustomException(STUDY_NOT_UPDATABLE_SESSION_NOT_FOUND));
+        StudySessionV2 session = studySessionV2Repository.findByIdAndStudyId(studySessionId, studyId)
+                .orElseThrow(() -> new CustomException(STUDY_NOT_UPDATABLE_SESSION_NOT_FOUND));
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c45e9b2 and 23e6554.

📒 Files selected for processing (7)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentStudyControllerV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/AttendanceV2Repository.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/AttendanceCreateRequest.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java (1 hunks)
🔇 Additional comments (5)
src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java (1)

140-140: 적절한 오류 코드 추가.

ATTENDANCE_PERIOD_INVALID 오류 코드 추가는 StudySessionLessonPeriod를 기반으로 출석 체크의 유효성을 검증하는 새로운 로직을 잘 지원합니다. 기존의 ATTENDANCE_DATE_INVALID와 함께 출석 체크에 대한 보다 세밀한 검증이 가능해졌습니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java (1)

12-12: 메서드 추가 적절.

existsByStudentAndStudy 메서드는 Spring Data JPA 명명 규칙을 잘 따르고 있으며, 기존 findByStudentAndStudy 메서드와 일관성을 유지합니다. 특정 학생과 스터디의 연결 여부를 확인하기 위한 효율적인 방법을 제공합니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/AttendanceCreateRequest.java (1)

1-13: 유효성 검증이 포함된 적절한 요청 클래스.

출석번호에 대한 유효성 검증(@NotBlank, @Pattern)을 포함하고 있어 잘못된 입력을 방지할 수 있습니다. @Schema 어노테이션을 통해 API 문서화도 잘 지원하고 있습니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/AttendanceV2Repository.java (1)

8-11: 적절한 저장소 인터페이스 구현.

AttendanceV2Repository 인터페이스는 Spring Data JPA 규칙을 잘 따르고 있으며, existsByStudentAndStudySession 메서드는 특정 학생과 스터디 세션에 대한 출석 여부를 효율적으로 확인할 수 있게 해줍니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (1)

34-57: 트랜잭션 처리 및 비즈니스 로직 구현이 잘 되어 있습니다.

attend 메서드의 전반적인 구현이 좋습니다. 적절한 트랜잭션 경계 설정, 예외 처리, 로깅 등이 잘 구현되어 있습니다. 특히 검증 로직을 별도의 클래스로 분리하여 단일 책임 원칙을 잘 지키고 있습니다.

API의 핵심 목표인 "출석체크 날짜를 StudyDetail에서 StudySessionLessonPeriod로 전환하여 검증하는 기능"이 잘 구현되어 있습니다.

@kckc0608 kckc0608 changed the title featt: 스터디 출석체크 V2 API 작성 feat: 스터디 출석체크 V2 API 작성 Feb 26, 2025
Copy link

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (2)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (2)

44-45: 변수명 및 로직 의도 명확화 권장
isAppliedToStudyisAlreadyAttended라는 변수명은 간결하지만, 로직 의도를 더 명확하게 드러내려면 hasJoinedStudyhasAttendedSession 등으로 표현을 고려해 보세요.


50-51: 새 엔티티 생성 후 반환값 처리 고려
출석 정보를 생성한 뒤 바로 저장만 하고 있습니다. 이후 작업을 위해 필요한 경우 save() 이후 생성된 엔티티(예: 출석 ID)를 반환하는 방안을 고려해 보시면 좋겠습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 23e6554 and 733bfd0.

📒 Files selected for processing (3)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentStudyControllerV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentStudyControllerV2.java
🔇 Additional comments (3)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (3)

39-39: 에러 메시지에 식별자를 포함하는 것 고려하기
이미 이전 리뷰에서 제안되었듯이, CustomException(STUDY_NOT_FOUND)를 던질 때 studySessionId 또는 studyId를 포함한 구체적인 에러 메시지를 제공하면 문제 파악에 유리합니다.


40-40: getStudySession 결과 검증 필요성 확인
study.getStudySession(studySessionId) 호출 시, 내부적으로 세션이 존재하지 않는 경우 예외가 던져지는지, 또는 null이 반환되는지 확인이 필요합니다. null 반환 시 예외 처리가 누락될 수 있습니다.


47-48: 동시성 처리 여부 확인
attendanceValidatorV2.validateAttendance() 내부에서 이미 출석 여부를 검사하더라도, 동시에 여러 요청이 들어올 경우 중복 출석을 막는 로직이 충분히 처리되는지 재확인이 필요합니다.

Copy link
Member

@Sangwook02 Sangwook02 left a comment

Choose a reason for hiding this comment

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

확인했습니다~


// 출석체크 번호 검증
if (isAlreadyAttended) {
throw new CustomException(STUDY_DETAIL_ALREADY_ATTENDED);
Copy link
Member

Choose a reason for hiding this comment

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

STUDY_DETAIL_ALREADY_ATTENDED도 수정이 필요해 보입니다!

Comment on lines 41 to 44
Optional<StudyHistoryV2> optionalStudyHistory =
studyHistoryV2Repository.findByStudentAndStudy(currentMember, study);

boolean isAppliedToStudy = optionalStudyHistory.isPresent();
Copy link
Member

Choose a reason for hiding this comment

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

이 부분은 exists 메서드로 처리하지 않은 이유가 있나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

원래 exists 로 처리했었는데, #938 로직과 비슷하게 가져가는 게 가독성이 좋을 것 같아서 통일했습니다

Copy link
Member

Choose a reason for hiding this comment

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

938에서 exists를 사용하지 않은 이유는 존재 여부를 검증한 뒤 -> 내부 엔티티 정보를 나중에 get() 으로 가져와야 했기 때문입니다. 여기서는 엔티티 내부 정보가 필요없고 존재성만 검증하며 되기 때문에 exists를 사용하는 게 좋을 듯 합니다.

Copy link

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (3)
src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (3)

26-27: 중복된 주석을 수정해주세요.

두번째 검증 로직의 주석이 "출석체크 번호 검증"으로 첫번째 검증 로직과 동일합니다. 실제로는 출석 중복 여부를 확인하는 로직이므로 해당 주석을 "출석체크 중복 검증"과 같이 수정하는 것이 좋겠습니다.

-        // 출석체크 번호 검증
+        // 출석체크 중복 검증
         if (isAlreadyAttended) {
             throw new CustomException(STUDY_SESSION_ALREADY_ATTENDED);
         }

14-15: 파라미터 명명 개선 고려

출석 유효성 검증에 사용되는 불리언 파라미터들의 이름(isAppliedToStudy, isAlreadyAttended)이 의미를 잘 전달하고 있습니다만, 더 일관된 네이밍을 위해 isEnrolledInStudy와 같이 수정하는 것도 고려해 볼 수 있습니다.


14-35: 검증 로직 순서 개선 고려

현재 검증 순서는 논리적이지만, 성능 최적화를 위해 가장 빠르게 실패할 수 있는 검증을 먼저 수행하는 것이 좋습니다. 예를 들어, 데이터베이스 조회 없이 검증할 수 있는 isAlreadyAttendedattendanceNumber 검증을 먼저 수행하면 성능상 이점이 있을 수 있습니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 733bfd0 and a957b84.

📒 Files selected for processing (2)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/gdschongik/gdsc/global/exception/ErrorCode.java
🔇 Additional comments (2)
src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (2)

1-36: 코드 구조가 잘 정리되어 있습니다.

도메인 서비스로서 출석 유효성 검증 로직이 캡슐화되어 있고, 각 검증 단계마다 적절한 예외 처리가 되어 있어 좋습니다. DomainService 어노테이션을 통해 레이어 구분이 명확합니다.


27-29: ErrorCode 수정 필요

이전 리뷰에서 언급된 것처럼 STUDY_DETAIL_ALREADY_ATTENDEDSTUDY_SESSION_ALREADY_ATTENDED로 수정해야 합니다. 현재 코드에서는 이미 STUDY_SESSION_ALREADY_ATTENDED를 사용하고 있으므로, 이와 관련된 ErrorCode 클래스의 상수 정의도 확인해주세요.

Copy link
Member

@Sangwook02 Sangwook02 left a comment

Choose a reason for hiding this comment

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

하나만 더 확인해주세요
미리 어푸루브 해뒀습니다

ATTENDANCE_NUMBER_MISMATCH(HttpStatus.CONFLICT, "출석번호가 일치하지 않습니다."),
STUDY_DETAIL_ALREADY_ATTENDED(HttpStatus.CONFLICT, "이미 출석 처리된 스터디입니다."),
STUDY_SESSION_ALREADY_ATTENDED(HttpStatus.CONFLICT, "이미 출석 처리된 스터디입니다."),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
STUDY_SESSION_ALREADY_ATTENDED(HttpStatus.CONFLICT, "이미 출석 처리된 스터디입니다."),
STUDY_SESSION_ALREADY_ATTENDED(HttpStatus.CONFLICT, "이미 출석 처리된 스터디 회차입니다."),

Copy link

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

}

// 스터디 신청 여부 검증
if (!isAppliedToStudy) {
Copy link
Member

Choose a reason for hiding this comment

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

로직 상 변경은 아니지만, 신청여부 -> 중복출석 -> 출석가능여부 -> 출석번호 순으로 검증하는 게 의미 상으로 더 적절할 것 같습니다

public void validateAttendance(
StudySessionV2 studySession, String attendanceNumber, boolean isAppliedToStudy, boolean isAlreadyAttended) {
// 출석체크 기간 검증
if (!studySession.getLessonPeriod().isOpen()) {
Copy link
Member

Choose a reason for hiding this comment

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

isOpen 은 deprecation 처리하는 게 좋아보입니다.
대신 isWithin 같이 유즈케이스로부터 독립적인 메서드를 추가하고, now를 인자로 받아서 처리하면 좋을 것 같습니다. '주어진 값이 시작일시와 종료일시 사이에 있다' 라는 걸 '기간이 열려있다' 라고 하지는 않잖아요?

'열려있다' 라는 건 Recruitment 도메인 구현하면서 잘못 추출된 워딩입니다.
해당 모집회차가 '열려있다' 라는 표현이 여기로 넘어온 것이죠.

'기한'은 '열려있다' 라는 표현보다는 '이내에 있다' 라는 표현이 적절하고, 따라서 isWithin 이 적절한 네이밍으로 보입니다. 사실 전에 assignmentPeriod 구현하면서 별도로 이슈 파서 추가할까 고민했는데 선반영하면 좋을 것 같아서 남깁니다.

그리고 기존 isOpen 로직은 오른쪽 끝에 대해서 inclusive하게 동작하는데, exclusive하게 구현을 변경하는 게 더 올바를 것 같아요. 1일 00시 제출 건을 받게 되어버리면 일자가 바뀌기 때문에...

한편 도메인 서비스도 마찬가지로 now를 바깥에서 받아야 합니다.
과제 제출하기 로직 참고해주세요.

Copy link
Member

Choose a reason for hiding this comment

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

-> 이 부분 #913 하면서 제가 처리하겠습니다.

StudySessionV2 studySession, String attendanceNumber, boolean isAppliedToStudy, boolean isAlreadyAttended) {
// 출석체크 기간 검증
if (!studySession.getLessonPeriod().isOpen()) {
throw new CustomException(ATTENDANCE_PERIOD_INVALID);
Copy link
Member

Choose a reason for hiding this comment

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

이제 봤는데 에러코드 네이밍이 조금 이상하네요.
출석기한 이내에 있지 않는데, 이 에러코드만 보면 출석기한 자체가 invalid한 것처럼 네이밍이 되어있어요. 여기서 처리할 내용은 아닌 것 같고 투두 남기고 이슈 별도로 파면 좋을 것 같습니다.

@uwoobeat
Copy link
Member

일단 기존 api 명세 따라서 /studies 로 뒀는데, studyId 없이 바로 /attend 로 끝내고 study session id 를 쿼리로 받으니까 어색한 것 같더라구요.

-> 저번 과제 제출 PR 네이밍 참고해주세요. 네이밍이 스터디 쪽 API스럽지 않은 문제는 앞에 /study 세그먼트를 붙이거나 하는 식으로 고민 중이긴 한데 이것도 나중에 시간 나면 논의해보면 좋을 것 같습니다.

/study-sessions 로 해볼까 해도 그때는 쿼리 파라미터보다 패스 파라미터로 받아서 /attend 로 끝내는 게 더 자연스러울 것 같고,

-> 스터디회차는 스터디 애그리거트의 자식 엔티티이므로, 단독으로 노출할 수 없습니다.
저번 PR에서 설명했듯이 애그리거트 당 하나의 레포지터리만이 존재하고, 스터디 애그리거트는 스터디 루트 엔티티와 스터디세션 자식 엔티티로 구성되기 때문에, 스터디세션만 단독으로 노출하는 것을 지양해야 합니다. /study-details 엔드포인트를 제거하기로 논의했던 것과 마찬가지로 /study-session 도 존재해서는 안됩니다.

/study-histories 로 빼면 과거 수강 이력에 대한 api 와 섞이는 것 같아 고민되는데 좋은 네이밍 아이디어 있을까요..

-> 앞에서 말했듯 (일반적으로) 애그리거트 하나 당 리소스 하나로 보고 있으니 해당 컨벤션을 따르면 될 것 같습니다. 출석이력은 수강이력과 별개입니다.

Comment on lines 41 to 44
Optional<StudyHistoryV2> optionalStudyHistory =
studyHistoryV2Repository.findByStudentAndStudy(currentMember, study);

boolean isAppliedToStudy = optionalStudyHistory.isPresent();
Copy link
Member

Choose a reason for hiding this comment

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

938에서 exists를 사용하지 않은 이유는 존재 여부를 검증한 뒤 -> 내부 엔티티 정보를 나중에 get() 으로 가져와야 했기 때문입니다. 여기서는 엔티티 내부 정보가 필요없고 존재성만 검증하며 되기 때문에 exists를 사용하는 게 좋을 듯 합니다.

Copy link

github-actions bot commented Mar 1, 2025

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

@kckc0608
Copy link
Member Author

kckc0608 commented Mar 1, 2025

앞에 /study 세그먼트 붙이는 건 논의 후에 통일하면 좋을 것 같아서, 일단 엔티티 명인 /attendances 로 설정했습니다

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

♻️ Duplicate comments (1)
src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (1)

14-35: 🛠️ Refactor suggestion

검증 순서 및 메서드 개선 필요

검증 순서가 의미적으로 더 자연스러운 흐름을 가지도록 재배열하는 것이 좋겠습니다:

  1. 스터디 신청 여부
  2. 중복 출석 여부
  3. 출석 가능 기간
  4. 출석 번호 일치

또한 다음과 같은 개선이 필요합니다:

public void validateAttendance(
        StudySessionV2 studySession, String attendanceNumber, boolean isAppliedToStudy, boolean isAlreadyAttended) {
    // 스터디 신청 여부 검증
    if (!isAppliedToStudy) {
        throw new CustomException(STUDY_HISTORY_NOT_FOUND);
    }

    // 스터디 중복 출석체크 여부 검증
    if (isAlreadyAttended) {
        throw new CustomException(STUDY_SESSION_ALREADY_ATTENDED);
    }

    // 출석체크 가능 기간 검증
-   if (!studySession.getLessonPeriod().isOpen()) {
+   // TODO: isOpen() 메서드를 isWithin()으로 대체하는 리팩토링 필요
+   if (!studySession.getLessonPeriod().isOpen()) {
        throw new CustomException(ATTENDANCE_PERIOD_INVALID);
    }

    // 출석체크 번호 검증
    if (!studySession.getLessonAttendanceNumber().equals(attendanceNumber)) {
        throw new CustomException(ATTENDANCE_NUMBER_MISMATCH);
    }
}

이전 리뷰에서도 언급되었듯이, isOpen() 메서드는 deprecated 처리하고 대신 isWithin()과 같이 유스케이스에 독립적인 메서드로 교체하는 것이 좋겠습니다. 또한 에러 코드 네이밍(ATTENDANCE_PERIOD_INVALID)도 더 명확한 것으로 변경을 고려해보세요.

🧹 Nitpick comments (2)
src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentAttendanceControllerV2.java (2)

16-32: API 엔드포인트 경로 설계 재고려 필요

현재 설계된 /v2/attendances/attend 경로는 중복적인 표현이 있고, PR 목표에서 언급된 대로 엔드포인트 명명 규칙에 대한 논의가 있었습니다. 리소스 중심 설계 원칙을 따르면, 다음과 같은 대안을 고려해볼 수 있습니다:

  1. /v2/studies/{studyId}/sessions/{sessionId}/attendances - RESTful한 계층 구조
  2. /v2/study-sessions/{sessionId}/attendances - StudySession 중심
  3. /v2/attendances (현재) - 출석 중심

PR 코멘트에서 언급된 것처럼 스터디 집계(aggregate)의 일관성을 고려하여 적절한 명명 규칙을 선택하는 것이 좋겠습니다.


24-31: 요청 구조 최적화 가능

현재 studySessionId@RequestParam으로 받고 있는데, 이는 REST API 설계 원칙에 따르면 URL 경로의 일부로 포함되는 것이 더 적절할 수 있습니다.

-@PostMapping("/attend")
-public ResponseEntity<Void> attend(
-        @RequestParam(name = "studySessionId") Long studySessionId,
-        @Valid @RequestBody AttendanceCreateRequest request) {
+@PostMapping("/sessions/{studySessionId}")
+public ResponseEntity<Void> attend(
+        @PathVariable Long studySessionId,
+        @Valid @RequestBody AttendanceCreateRequest request) {

이렇게 변경하면 URL이 /v2/attendances/sessions/{studySessionId}가 되어 리소스 식별이 더 명확해집니다.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 19f2c89 and e2cd68d.

📒 Files selected for processing (4)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentAttendanceControllerV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/domain/AttendanceValidatorV2.java (1 hunks)
🔇 Additional comments (5)
src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java (1)

12-12: 메서드 추가 적절합니다.

학생과 스터디를 기준으로 존재 여부를 확인하는 메서드로, Spring Data JPA 네이밍 규칙을 잘 따르고 있습니다. 출석 체크 전에 해당 학생이 스터디에 신청했는지 검증하는 데 사용될 것으로 보입니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentStudyServiceV2.java (4)

35-38: 예외 메시지 개선 필요

예외 발생 시 더 자세한 정보를 제공하면 디버깅과 문제 해결에 도움이 됩니다. studySessionId를 포함한 메시지를 추가하는 것이 좋겠습니다.

StudyV2 study = studyV2Repository
        .findFetchBySessionId(studySessionId)
-       .orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));
+       .orElseThrow(() -> new CustomException(STUDY_NOT_FOUND, 
+               String.format("studySessionId=%d에 해당하는 스터디를 찾을 수 없습니다.", studySessionId)));

40-41: 효율적인 쿼리 사용

existsByStudentAndStudyexistsByStudentAndStudySession 메서드를 사용하여 효율적으로 존재 여부를 확인하고 있습니다. 이는 전체 엔티티를 조회하지 않고 존재 여부만 확인하기 때문에 성능상 좋은 접근법입니다.


46-47: 정적 팩토리 메서드 사용 적절

AttendanceV2.create(currentMember, studySession) 정적 팩토리 메서드를 사용하여 객체 생성을 추상화하고 있습니다. 이는 객체 생성 로직을 캡슐화하고 가독성을 높이는 좋은 패턴입니다.


49-53: 로깅 구현 적절

중요한 비즈니스 이벤트(출석 체크)에 대한 로깅이 잘 구현되어 있습니다. 출석 ID와 사용자 ID를 포함하여 추적 가능성을 높였습니다.

Copy link

github-actions bot commented Mar 1, 2025

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

github-actions bot commented Mar 1, 2025

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

github-actions bot commented Mar 2, 2025

Job Summary for Gradle

Check Style and Test to Develop :: build-test
Gradle Root Project Requested Tasks Gradle Version Build Outcome Build Scan®
gdsc check 8.5 Build Scan published

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (4)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentAttendanceServiceV2.java (4)

49-52: 로그 메시지의 클래스명 불일치

로그 메시지에 사용된 클래스명 [StudentStudyServiceV2]가 실제 클래스명 StudentAttendanceServiceV2와 일치하지 않습니다.

- log.info(
-         "[StudentStudyServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",
-         attendance.getId(),
-         currentMember.getId());
+ log.info(
+         "[StudentAttendanceServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",
+         attendance.getId(),
+         currentMember.getId());

32-53: 메소드 반환값 개선 제안

현재 attend 메소드가 void를 반환하고 있어, 출석 생성 결과에 대한 정보를 호출자에게 제공하지 않습니다. 생성된 AttendanceV2 객체나 관련 정보를 반환하는 것이 좋을 수 있습니다.

- @Transactional
- public void attend(Long studySessionId, AttendanceCreateRequest request) {
+ @Transactional
+ public AttendanceV2 attend(Long studySessionId, AttendanceCreateRequest request) {
      // 기존 코드 유지
      
      AttendanceV2 attendance = AttendanceV2.create(currentMember, studySession);
      attendanceV2Repository.save(attendance);
      
      log.info(
              "[StudentAttendanceServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",
              attendance.getId(),
              currentMember.getId());
+     
+     return attendance;
  }

43-44: 매개변수 명확성 개선

validateAttendance 메소드에 전달되는 인자들의 의미가 메소드 호출만으로는 명확하지 않습니다. 각 매개변수의 의미를 더 명확히 하기 위해 Java 17의 레코드나 빌더 패턴을 고려해 볼 수 있습니다.

현재 방식 대신, 다음과 같이 더 명시적으로 호출하는 것을 고려해 보세요:

attendanceValidatorV2.validateAttendance(
        studySession,
        attendanceNumber: request.attendanceNumber(),
        isStudentApplied: isAppliedToStudy,
        isAlreadyAttended: isAlreadyAttended);

또는 AttendanceValidateRequest 같은 별도의 값 객체를 만드는 것도 고려해볼 수 있습니다.


40-41: 유효성 검사 명확화

isAppliedToStudyisAlreadyAttended 변수는 의미는 명확하지만, 이 두 조건이 어떤 오류 상황과 연결되는지 주석으로 설명하면 코드 이해가 더 쉬울 것입니다.

+ // 학생이 해당 스터디에 신청했는지 확인 (신청하지 않은 학생은 출석 불가)
boolean isAppliedToStudy = studyHistoryV2Repository.existsByStudentAndStudy(currentMember, study);
+ // 이미 해당 세션에 출석했는지 확인 (중복 출석 방지)
boolean isAlreadyAttended = attendanceV2Repository.existsByStudentAndStudySession(currentMember, studySession);
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2f31956 and e3c0c88.

📒 Files selected for processing (3)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentAttendanceControllerV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentAttendanceServiceV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyHistoryV2Repository.java
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/StudentAttendanceControllerV2.java
🔇 Additional comments (2)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/StudentAttendanceServiceV2.java (2)

39-39: StudySession이 존재하지 않는 경우 예외 처리 추가 필요

studySession 변수가 null인 경우에 대한 예외 처리가 없습니다. getStudySession 메소드가 세션을 찾지 못할 경우 발생할 수 있는 문제입니다.

// 이런 식으로 명시적인 예외 처리를 추가하는 것이 좋습니다
if (studySession == null) {
    throw new CustomException(ErrorCode.STUDY_SESSION_NOT_FOUND);
}

21-24: 클래스 역할과 책임 검토

이 클래스는 이름과 함께 출석체크 기능만 담당하고 있어 단일 책임 원칙(SRP)을 잘 따르고 있습니다. 다만, 이후 추가될 출석 관련 기능(수정, 삭제, 조회 등)에 대한 계획도 미리 고려해보는 것이 좋겠습니다.

Copy link
Member

@Sangwook02 Sangwook02 left a comment

Choose a reason for hiding this comment

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

우연히 발견했어요
머지전에 수정 부탁드려요!

attendanceV2Repository.save(attendance);

log.info(
"[StudentStudyServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
"[StudentStudyServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",
"[StudentAttendanceServiceV2] 스터디 출석체크: attendanceId={}, memberId={}",

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.

✨ 스터디 출석체크 V2 API 구현
3 participants