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: 스터디 공지 관련 API 구현 #933

Merged
merged 4 commits into from
Feb 26, 2025

Conversation

Sangwook02
Copy link
Member

@Sangwook02 Sangwook02 commented Feb 26, 2025

🌱 관련 이슈

📌 작업 내용 및 특이사항

  • 공지 생성할 때는 수정과 달리 studyId가 필요해서 request dto를 분리했습니다.

📝 참고사항

📚 기타

Summary by CodeRabbit

  • 새로운 기능
    • 멘토용 스터디 공지사항 관리 기능이 추가되어, 멘토가 스터디 관련 공지사항을 생성, 수정, 삭제할 수 있습니다.
    • 공지사항 등록 시 데이터 유효성 검사가 강화되어 보다 안정적인 공지 관리가 가능합니다.

@Sangwook02 Sangwook02 requested a review from a team as a code owner February 26, 2025 03:24
@Sangwook02 Sangwook02 added the ✨ feature 새로운 기능 추가 및 수정 label Feb 26, 2025
Copy link

coderabbitai bot commented Feb 26, 2025

📝 Walkthrough

Walkthrough

이번 PR은 기존 MentorStudyServiceV2 클래스에서 변수 선언 순서를 조정하고 로깅 메시지의 오타를 수정하는 변경과 함께, 멘토 스터디 공지사항 기능을 위한 새로운 Controller, Service, Repository, DTO가 추가되었습니다. 새로 추가된 코드는 공지사항의 생성, 수정, 삭제 기능을 지원하며, 멘토 권한 검증 및 관련 데이터 처리를 수행합니다.

Changes

파일 변경 요약
.../studyv2/application/MentorStudyServiceV2.java studyValidatorV2 뒤에 studyV2Repository 변수 선언 순서 조정 및 로깅 메시지 오타("MentoryStudyServiceV2" → "MentorStudyServiceV2") 수정
.../studyv2/dao/StudyAnnouncementV2Repository.java 스터디 공지사항 관리를 위한 새로운 JpaRepository 인터페이스 추가
.../studyv2/api/MentorStudyAnnouncementControllerV2.java 공지사항 생성, 수정, 삭제를 위한 REST API Controller 추가 (Swagger 어노테이션 포함)
.../studyv2/application/MentorStudyAnnouncementServiceV2.java 공지사항 생성, 수정, 삭제 로직을 처리하는 서비스 클래스 추가 (트랜잭션 처리 포함)
.../studyv2/dto/request/StudyAnnouncementCreateRequest.java 스터디 공지사항 생성 요청을 위한 DTO(레코드) 추가, 필드에 유효성 검사 어노테이션 적용

Sequence Diagram(s)

sequenceDiagram
    participant C as MentorStudyAnnouncementControllerV2
    participant S as MentorStudyAnnouncementServiceV2
    participant M as MemberUtil
    participant R as Repository

    C->>S: createStudyAnnouncement(request)
    S->>M: getCurrentMember()
    S->>R: StudyV2 조회 및 StudyAnnouncementV2 생성
    S-->>C: HTTP 200 OK 응답
Loading

Possibly related PRs

Poem

당근밭을 달리며 코드를 손질해요,
스터디 공지 새싹이 피어나는 날,
로깅 오타도 깔끔하게 고쳐두고,
멘토의 길 따라 함께 나아가요,
귀여운 토끼 발자국, 코드 위에 춤추네요! 🐰🌟

Tip

CodeRabbit's docstrings feature is now available as part of our Pro Plan! Simply use the command @coderabbitai generate docstrings to have CodeRabbit automatically generate docstrings for your pull request. We would love to hear your feedback on Discord.

✨ 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

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

@Sangwook02 Sangwook02 self-assigned this Feb 26, 2025
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 (8)
src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyControllerV2.java (3)

44-50: 생성 엔드포인트는 201 응답 코드를 반환하는 것이 더 적절합니다.

리소스 생성 시 HTTP 규약에 따르면 201 Created 상태 코드를 반환하는 것이 좋습니다.

다음과 같이 수정하는 것을 고려해보세요:

@PostMapping("/{studyId}/announcements")
public ResponseEntity<Void> createStudyAnnouncement(
        @PathVariable Long studyId, @Valid @RequestBody StudyAnnouncementCreateUpdateRequest request) {
    mentorStudyServiceV2.createStudyAnnouncement(studyId, request);
-   return ResponseEntity.ok().build();
+   return ResponseEntity.status(201).build();
}

52-58: API 패턴이 일관되지 않습니다.

생성 API는 /{studyId}/announcements 형태인데 비해, 수정 API는 /announcements/{studyAnnouncementId} 형태입니다. 일관된 패턴을 사용하는 것이 좋습니다.

리소스 식별자를 좀 더 일관되게 관리하는 방식으로 변경하는 것을 고려해보세요. 예를 들어:

-@PutMapping("/announcements/{studyAnnouncementId}")
+@PutMapping("/{studyId}/announcements/{studyAnnouncementId}")
public ResponseEntity<Void> updateStudyAnnouncement(
-       @PathVariable Long studyAnnouncementId, @Valid @RequestBody StudyAnnouncementCreateUpdateRequest request) {
+       @PathVariable Long studyId, @PathVariable Long studyAnnouncementId, 
+       @Valid @RequestBody StudyAnnouncementCreateUpdateRequest request) {
    mentorStudyServiceV2.updateStudyAnnouncement(studyAnnouncementId, request);
    return ResponseEntity.ok().build();
}

서비스 메서드 서명도 함께 수정해야 합니다.


60-65: API 패턴이 일관되지 않습니다.

삭제 API도 생성 API와 다른 패턴을 사용하고 있습니다. 일관된 패턴을 사용하는 것이 좋습니다.

-@DeleteMapping("/announcements/{studyAnnouncementId}")
+@DeleteMapping("/{studyId}/announcements/{studyAnnouncementId}")
public ResponseEntity<Void> deleteStudyAnnouncement(
-       @PathVariable Long studyAnnouncementId) {
+       @PathVariable Long studyId, @PathVariable Long studyAnnouncementId) {
    mentorStudyServiceV2.deleteStudyAnnouncement(studyAnnouncementId);
    return ResponseEntity.ok().build();
}

서비스 메서드 서명도 함께 수정해야 합니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (5)

59-60: findFetchById 대신 findById를 사용하고 있습니다.

updateStudy 메서드에서는 findFetchById를 사용하고 있는데, 여기서는 findById를 사용하고 있습니다. 일관성을 위해 동일한 메서드를 사용하는 것이 좋습니다.

-StudyV2 study = studyV2Repository.findById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));
+StudyV2 study = studyV2Repository.findFetchById(studyId).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));

66-67: 로그 메시지에 오타가 있습니다.

로그 메시지에 "Mentory"라는 오타가 있습니다. 클래스 이름과 일치하도록 "Mentor"로 수정해야 합니다.

-log.info("[MentoryStudyServiceV2] 스터디 공지 생성: studyAnnouncementId={}", studyAnnouncement.getId());
+log.info("[MentorStudyServiceV2] 스터디 공지 생성: studyAnnouncementId={}", studyAnnouncement.getId());

82-83: 로그 메시지에 오타가 있습니다.

로그 메시지에 "Mentory"라는 오타가 있습니다. 클래스 이름과 일치하도록 "Mentor"로 수정해야 합니다.

-log.info("[MentoryStudyServiceV2] 스터디 공지 수정 완료: studyAnnouncementId={}", studyAnnouncement.getId());
+log.info("[MentorStudyServiceV2] 스터디 공지 수정 완료: studyAnnouncementId={}", studyAnnouncement.getId());

97-98: 로그 메시지에 오타가 있습니다.

로그 메시지에 "Mentory"라는 오타가 있습니다. 클래스 이름과 일치하도록 "Mentor"로 수정해야 합니다.

-log.info("[MentoryStudyServiceV2] 스터디 공지 삭제 완료: studyAnnouncementId={}", studyAnnouncement.getId());
+log.info("[MentorStudyServiceV2] 스터디 공지 삭제 완료: studyAnnouncementId={}", studyAnnouncement.getId());

31-31: DDD 원칙에 따른 설계 고려 필요

이전 리뷰에서 배운 내용을 참고하면, StudyV2는 애그리게이트 루트이고 StudySession은 자식 엔티티로서 StudyV2Repository를 통해서만 접근해야 한다고 명시되어 있습니다. 비슷한 맥락에서 StudyAnnouncementV2도 같은 원칙을 적용해야 할 수 있습니다.

애그리게이트 패턴에 따라 StudyAnnouncementV2Repository를 별도로 생성하는 대신, StudyV2Repository를 통해 StudyAnnouncementV2에 접근하는 방식을 고려해보세요. 이는 DDD 원칙을 더 잘 따르는 방식일 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d211311 and 70ffe0e.

📒 Files selected for processing (3)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyControllerV2.java (2 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (3 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyAnnouncementV2Repository.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dao/StudyAnnouncementV2Repository.java
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (1)
Learnt from: uwoobeat
PR: GDSC-Hongik/gdsc-server#889
File: src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyControllerV2.java:35-39
Timestamp: 2025-02-12T11:11:19.196Z
Learning: In the GDSC server project's V2 domain, following DDD principles, StudyV2 is an aggregate root and StudySession is its child entity. Therefore, StudySession should only be accessed through StudyV2 aggregate root using StudyV2Repository, not directly via a separate StudySessionRepository.

Copy link
Member

@kckc0608 kckc0608 left a comment

Choose a reason for hiding this comment

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

lgtm

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 (1)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (1)

56-97: 코드 중복 감소를 위한 리팩토링 고려

세 개의 메서드(createStudyAnnouncement, updateStudyAnnouncement, deleteStudyAnnouncement)가 유사한 패턴(현재 멤버 조회, 유효성 검증, 작업 수행, 로깅)을 따르고 있습니다. 이러한 공통 로직을 추출하여 코드 중복을 줄이는 것을 고려해보세요.

예를 들어, 공지사항 ID로 공지사항과 관련 스터디를 조회하고 멘토 권한을 검증하는 헬퍼 메서드를 만들 수 있습니다:

private StudyAnnouncementV2 validateAndGetAnnouncement(Long announcementId) {
    Member currentMember = memberUtil.getCurrentMember();
    StudyAnnouncementV2 announcement = studyAnnouncementV2Repository
            .findById(announcementId)
            .orElseThrow(() -> new CustomException(STUDY_ANNOUNCEMENT_NOT_FOUND));
    StudyV2 study = announcement.getStudy();
    
    studyValidatorV2.validateStudyMentor(currentMember, study);
    
    return announcement;
}

이를 사용하면 업데이트와 삭제 메서드의 코드를 간소화할 수 있습니다.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 70ffe0e and a730aec.

📒 Files selected for processing (1)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (1)
Learnt from: uwoobeat
PR: GDSC-Hongik/gdsc-server#889
File: src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyControllerV2.java:35-39
Timestamp: 2025-02-12T11:11:19.196Z
Learning: In the GDSC server project's V2 domain, following DDD principles, StudyV2 is an aggregate root and StudySession is its child entity. Therefore, StudySession should only be accessed through StudyV2 aggregate root using StudyV2Repository, not directly via a separate StudySessionRepository.
🔇 Additional comments (4)
src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (4)

6-7: 의존성 주입 및 임포트 추가가 적절합니다.

StudyAnnouncementV2 관련 기능을 구현하기 위한 필요한 클래스들이 적절하게 임포트되었으며, repository 의존성이 주입되었습니다.

Also applies to: 9-9, 31-31


56-67: 스터디 공지 생성 기능이 잘 구현되었습니다.

스터디 공지 생성 메서드가 다음과 같은 적절한 로직을 포함하고 있습니다:

  1. 현재 인증된 멤버 확인
  2. 스터디 존재 여부 확인
  3. 멘토 권한 검증
  4. 공지사항 생성 및 저장
  5. 로그 기록

한 가지 고려사항으로는 59번 줄에서 findById를 사용하고 있는데, 44번 줄의 updateStudy 메서드에서는 findFetchById를 사용합니다. 연관 엔티티의 즉시 로딩이 필요하지 않다면 현재 구현도 충분하지만, 일관성을 위해 검토해보세요.


69-83: 스터디 공지 수정 기능이 적절하게 구현되었습니다.

스터디 공지 수정 메서드는 다음과 같은 필수 로직을 포함합니다:

  1. 현재 인증된 멤버 확인
  2. 공지사항 존재 여부 확인
  3. 관련 스터디 조회
  4. 멘토 권한 검증
  5. 공지사항 업데이트 및 저장
  6. 로그 기록

Domain-Driven Design 원칙에 따라 StudyV2 애그리게이트 루트를 통해 StudyAnnouncementV2 엔티티에 접근하는 방식이 잘 구현되어 있습니다.


85-97: 스터디 공지 삭제 기능이 잘 구현되었습니다.

스터디 공지 삭제 메서드도 다른 메서드들과 일관된 패턴으로 구현되었습니다:

  1. 현재 인증된 멤버 확인
  2. 공지사항 존재 여부 확인
  3. 관련 스터디 조회
  4. 멘토 권한 검증
  5. 공지사항 삭제
  6. 로그 기록

트랜잭션 관리가 잘 되어 있고, 적절한 예외 처리와 로깅이 포함되어 있습니다.

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: 1

🧹 Nitpick comments (4)
src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/StudyAnnouncementCreateRequest.java (1)

8-11: 유효성 검증 일관성 개선이 필요합니다.

link 필드에는 URL 유효성 검증이 없습니다. 링크 URL이 유효한지 확인하는 @url 어노테이션을 추가하는 것이 좋겠습니다.

또한 일관성을 위해 studyId에도 에러 메시지를 추가하고, 모든 필드에 @Schema 어노테이션을 사용하는 것이 좋겠습니다:

 public record StudyAnnouncementCreateRequest(
-        @NotNull @Positive Long studyId,
+        @NotNull(message = "스터디 ID가 필요합니다.") @Positive(message = "스터디 ID는 양수여야 합니다.") @Schema(description = "스터디 ID") Long studyId,
         @NotBlank(message = "공지제목이 비었습니다.") @Schema(description = "공지제목") String title,
-        @Schema(description = "공지링크") String link) {}
+        @URL(message = "유효한 URL 형식이어야 합니다.") @Schema(description = "공지링크") String link) {}
src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyAnnouncementControllerV2.java (1)

29-32: 생성 API의 응답 코드 개선이 필요합니다.

리소스 생성 시 HTTP 상태 코드로 200(OK) 대신 201(Created)을 반환하는 것이 REST API 설계 관행에 더 적합합니다. 또한 생성된 리소스의 위치를 location 헤더에 포함시키는 것이 좋습니다.

 @PostMapping
 public ResponseEntity<Void> createStudyAnnouncement(@Valid @RequestBody StudyAnnouncementCreateRequest request) {
-    mentorStudyAnnouncementServiceV2.createStudyAnnouncement(request);
-    return ResponseEntity.ok().build();
+    Long announcementId = mentorStudyAnnouncementServiceV2.createStudyAnnouncement(request);
+    return ResponseEntity.created(URI.create("/v2/mentor/study-announcements/" + announcementId)).build();
 }

이를 위해 service 메서드도 생성된 ID를 반환하도록 수정해야 합니다.

src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyAnnouncementServiceV2.java (2)

30-42: createStudyAnnouncement 메서드 반환 값 개선이 필요합니다.

생성된 공지사항의 ID를 반환하면 컨트롤러에서 location 헤더 설정 등에 활용할 수 있습니다.

 @Transactional
-public void createStudyAnnouncement(StudyAnnouncementCreateRequest request) {
+public Long createStudyAnnouncement(StudyAnnouncementCreateRequest request) {
     Member currentMember = memberUtil.getCurrentMember();
     StudyV2 study =
             studyV2Repository.findById(request.studyId()).orElseThrow(() -> new CustomException(STUDY_NOT_FOUND));

     studyValidatorV2.validateStudyMentor(currentMember, study);

     StudyAnnouncementV2 studyAnnouncement = StudyAnnouncementV2.create(request.title(), request.link(), study);
     studyAnnouncementV2Repository.save(studyAnnouncement);

     log.info("[MentorStudyAnnouncementServiceV2] 스터디 공지 생성: studyAnnouncementId={}", studyAnnouncement.getId());
+    return studyAnnouncement.getId();
 }

55-55: 불필요한 저장소 호출이 있습니다.

JPA의 영속성 컨텍스트 내에서 엔티티 변경은 자동으로 감지되어 트랜잭션 종료 시 DB에 반영됩니다. @Transactional 애노테이션이 있으므로 별도의 save 호출은 불필요합니다.

 studyAnnouncement.update(request.title(), request.link());
-studyAnnouncementV2Repository.save(studyAnnouncement);
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between a730aec and c635141.

📒 Files selected for processing (4)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/api/MentorStudyAnnouncementControllerV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyAnnouncementServiceV2.java (1 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java (2 hunks)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/dto/request/StudyAnnouncementCreateRequest.java (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • src/main/java/com/gdschongik/gdsc/domain/studyv2/application/MentorStudyServiceV2.java

Comment on lines +3 to +5
import com.gdschongik.gdsc.domain.study.dto.request.StudyAnnouncementCreateUpdateRequest;
import com.gdschongik.gdsc.domain.studyv2.application.MentorStudyAnnouncementServiceV2;
import com.gdschongik.gdsc.domain.studyv2.dto.request.StudyAnnouncementCreateRequest;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

패키지 일관성 문제가 있습니다.

StudyAnnouncementCreateUpdateRequest는 study 패키지에서 가져오고, StudyAnnouncementCreateRequest는 studyv2 패키지에서 가져오고 있습니다. 일관성을 위해 모두 studyv2 패키지로 통일하는 것이 좋겠습니다.

@Sangwook02 Sangwook02 merged commit e74d5c6 into develop Feb 26, 2025
2 checks passed
@Sangwook02 Sangwook02 deleted the feature/932-announcement-api branch February 26, 2025 06:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
✨ feature 새로운 기능 추가 및 수정
Projects
None yet
Development

Successfully merging this pull request may close these issues.

✨ 스터디 공지 V2 API 구현
2 participants