Skip to content

[feat] socialLinks 구현#363

Merged
Zepelown merged 2 commits intodevelop/befrom
feat/#362-social-links
May 3, 2025
Merged

[feat] socialLinks 구현#363
Zepelown merged 2 commits intodevelop/befrom
feat/#362-social-links

Conversation

@Due-IT
Copy link
Collaborator

@Due-IT Due-IT commented May 1, 2025

#️⃣연관된 이슈

#362

📝 작업 내용

동아리 관리자는 동아리 관련 SNS 관련 링크를 제공할 수 있습니다.

  • Club 엔티티에 socialLinks: Map<String, String> 필드 추가
  • 동아리의 인스타그램, 페이스북 등 다양한 SNS 링크를 저장할 수 있도록 지원
  • ClubInfoRequest에 socialLinks 필드 추가
  • 클라이언트로부터 소셜 링크 데이터를 전달받을 수 있도록 요청 객체 수정
  • Club.update() 메서드에 socialLinks 업데이트 로직 반영
  • ClubDetailedResult DTO에 socialLinks 필드 추가 및 of() 메서드에 매핑 로직 적용
  • 사용되지 않는 recruitmentForm 필드 제거 및 관련 코드 정리

⚠️ 주의사항

  • ClubRecruitmentInformation의 recruitmentForm 필드를 삭제했으므로, 해당 필드를 사용하는 기존 클라이언트 코드가 있다면 에러가 발생할 수 있습니다. 배포 전 반드시 프론트엔드와 연동 여부를 확인해주세요.
  • socialLinks는 Map<String, String> 타입이므로, 입력 데이터의 key-value 구조가 클라이언트와 사전 합의되어야 합니다. 예: {"instagram": "url", "youtube": "url"}.

Summary by CodeRabbit

  • 신규 기능

    • 동아리 정보에 여러 소셜 링크를 저장할 수 있는 기능이 추가되었습니다.
  • 변경 사항

    • 기존에 단일 모집 양식(recruitmentForm) 필드가 여러 소셜 링크(socialLinks) 필드로 대체되었습니다.
    • 동아리 상세 정보 및 등록/수정 시 소셜 링크 정보를 입력 및 확인할 수 있습니다.

@Due-IT Due-IT added ✨ Feature 기능 개발 💾 BE Backend labels May 1, 2025
@Due-IT Due-IT self-assigned this May 1, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented May 1, 2025

Walkthrough

이번 변경 사항에서는 동아리(Club) 관련 데이터 구조에서 기존의 recruitmentForm(모집 양식) 필드를 삭제하고, 대신 socialLinks(소셜 링크)라는 Map<String, String> 타입의 필드를 새롭게 도입하였습니다. 이 변경은 엔티티, DTO, 요청/응답 객체 등 관련 클래스 전반에 반영되었으며, 각 클래스의 생성 및 업데이트 로직도 이에 맞게 수정되었습니다. import 구문도 Map 타입 추가에 맞추어 조정되었습니다.

Changes

파일/경로 변경 요약
.../entity/Club.java socialLinks(Map<String, String>) 필드 추가, update 메서드에서 socialLinks 할당, import 정리
.../entity/ClubRecruitmentInformation.java recruitmentForm 필드 및 관련 업데이트 로직 삭제, import 및 포매팅 소폭 조정
.../payload/dto/ClubDetailedResult.java recruitmentFormsocialLinks(Map<String, String>) 필드 교체, factory 메서드 로직 수정
.../payload/request/ClubInfoRequest.java recruitmentFormsocialLinks(Map<String, String>) 필드 교체, import 추가

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant Club Entity

    Client->>Controller: ClubInfoRequest (socialLinks 포함)
    Controller->>Service: ClubInfoRequest 전달
    Service->>Club Entity: update(ClubInfoRequest)
    Club Entity-->>Service: socialLinks 필드 업데이트
    Service-->>Controller: 처리 결과 반환
    Controller-->>Client: ClubDetailedResult (socialLinks 포함)
Loading

📜 Recent review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between fdaec60 and 430dfa5.

📒 Files selected for processing (1)
  • backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java
✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in 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.

@github-actions
Copy link

github-actions bot commented May 1, 2025

Test Results

1 tests   1 ✅  0s ⏱️
1 suites  0 💤
1 files    0 ❌

Results for commit 430dfa5.

♻️ This comment has been updated with latest results.

Copy link
Contributor

@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: 4

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 829ae77 and fdaec60.

📒 Files selected for processing (4)
  • backend/src/main/java/moadong/club/entity/Club.java (3 hunks)
  • backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java (3 hunks)
  • backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java (3 hunks)
  • backend/src/main/java/moadong/club/payload/request/ClubInfoRequest.java (2 hunks)
🔇 Additional comments (8)
backend/src/main/java/moadong/club/payload/request/ClubInfoRequest.java (1)

5-5: Map 타입 추가 확인

Map 타입이 정상적으로 import 되었습니다.

backend/src/main/java/moadong/club/entity/Club.java (1)

9-9: Map 타입 추가 확인

Map 타입이 정상적으로 import 되었습니다.

backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java (4)

18-18: import 순서 변경

import 순서가 변경되었지만 코드 기능에는 영향을 미치지 않습니다.


91-93: 메서드 포맷팅 변경

메서드 포맷팅이 변경되었지만 로직은 동일하게 유지됩니다.


95-97: 메서드 포맷팅 변경

메서드 포맷팅이 변경되었지만 로직은 동일하게 유지됩니다.


99-104:

Details

❓ Verification inconclusive

recruitmentForm 필드 관련 로직 제거

update 메서드에서 recruitmentForm 관련 로직이 제거되었습니다. 기존 데이터에 대한 마이그레이션 계획이 필요합니다.

기존 데이터베이스에 recruitmentForm 값이 있는 레코드가 있을 경우, 이 값들을 새로운 socialLinks 필드로 마이그레이션하는 계획을 수립하세요. 데이터 손실을 방지하기 위해 마이그레이션 스크립트를 작성하는 것이 좋습니다.


🏁 Script executed:

#!/bin/bash
# 기존 recruitmentForm 데이터가 있는지 확인
# MongoDB 컬렉션을 조회하여 recruitmentForm 필드를 사용하고 있는 문서가 있는지 확인

echo "기존 recruitmentForm 데이터를 확인하고 있습니다..."
mongo --eval "db.clubs.find({\"clubRecruitmentInformation.recruitmentForm\": {\$exists: true}}).count()"

Length of output: 282


recruitmentForm 필드 마이그레이션 검토 필요

update() 메서드에서 recruitmentForm 관련 로직이 제거되었습니다. 기존 DB에 해당 필드 값이 남아있는지 확인하고, 새로운 socialLinks 필드로 안전하게 마이그레이션할 계획을 수립하세요.

  • 위치:
    backend/src/main/java/moadong/club/entity/ClubRecruitmentInformation.java
    public void update(ClubInfoRequest request) 메서드
  • 검증 예시 (운영 DB에서 수동 실행):
    mongo --eval 'db.clubs.find({"clubRecruitmentInformation.recruitmentForm": {$exists: true}}).count()'
  • 확인 후 데이터 손실 방지를 위해 마이그레이션 스크립트 작성 권장

실제 운영 환경에서 수동으로 남아있는 recruitmentForm 데이터를 확인하고, 필요한 경우 이를 socialLinks로 이전하는 스크립트를 작성해 주세요.

backend/src/main/java/moadong/club/payload/dto/ClubDetailedResult.java (2)

5-5: Map 타입 추가 확인

Map 타입이 정상적으로 import 되었습니다.


25-25: socialLinks 필드 추가

socialLinks 필드가 올바르게 추가되었습니다.

String presidentName,
String presidentPhoneNumber,
String recruitmentForm
Map<String, String> socialLinks
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

socialLinks 필드에 유효성 검증 추가 필요

socialLinks 필드에 유효성 검증 로직이 없습니다. 지정된 소셜 미디어 키와 URL 형식을 검증하는 로직이 필요합니다.

다음과 같이 Jakarta Validation API의 @Valid와 커스텀 검증기를 사용하는 방법을 고려해 보세요:

 import jakarta.validation.constraints.NotBlank;
 import java.util.List;
 import java.util.Map;
+import jakarta.validation.Valid;

 public record ClubInfoRequest(
     @NotBlank
     String id,
     @NotBlank
     String name,
     @NotBlank
     String category,
     @NotBlank
     String division,
     List<String> tags,
     String introduction,
     String presidentName,
     String presidentPhoneNumber,
+    @Valid
     Map<String, String> socialLinks
 ) {

 }

또한 socialLinks 필드에 대한 JavaDoc 또는 주석을 추가하여 허용되는 키 형식(예: "instagram", "facebook")과 URL 형식을 명시하는 것이 좋습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Map<String, String> socialLinks
import jakarta.validation.constraints.NotBlank;
import java.util.List;
import java.util.Map;
+import jakarta.validation.Valid;
public record ClubInfoRequest(
@NotBlank
String id,
@NotBlank
String name,
@NotBlank
String category,
@NotBlank
String division,
List<String> tags,
String introduction,
String presidentName,
String presidentPhoneNumber,
+ @Valid
Map<String, String> socialLinks
) {
}

this.category = request.category();
this.division = request.division();
this.state = ClubState.AVAILABLE;
this.socialLinks = request.socialLinks();
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

null 체크 없이 socialLinks 업데이트

request.socialLinks()가 null일 경우 NPE가 발생할 수 있습니다.

다음과 같이 방어적 코딩을 추가하세요:

public void update(ClubInfoRequest request) {
    this.name = request.name();
    this.category = request.category();
    this.division = request.division();
    this.state = ClubState.AVAILABLE;
-   this.socialLinks = request.socialLinks();
+   this.socialLinks = request.socialLinks() != null ? request.socialLinks() : new HashMap<>();
    this.clubRecruitmentInformation.update(request);
}

또는 Optional을 사용하는 방법도 고려할 수 있습니다.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
this.socialLinks = request.socialLinks();
public void update(ClubInfoRequest request) {
this.name = request.name();
this.category = request.category();
this.division = request.division();
this.state = ClubState.AVAILABLE;
this.socialLinks = request.socialLinks() != null
? request.socialLinks()
: new HashMap<>();
this.clubRecruitmentInformation.update(request);
}


private String userId;

private Map<String, String> socialLinks;
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

socialLinks 필드 추가

socialLinks 필드가 올바르게 추가되었습니다. 그러나 생성자에서 초기화되지 않아 NPE 위험이 있습니다.

생성자에서 빈 맵으로 초기화하는 것이 좋습니다:

public Club() {
    this.name = "";
    this.category = "";
    this.division = "";
    this.state = ClubState.UNAVAILABLE;
    this.clubRecruitmentInformation = ClubRecruitmentInformation.builder().build();
+   this.socialLinks = new HashMap<>();
}

public Club(String userId) {
    this.name = "";
    this.category = "";
    this.division = "";
    this.state = ClubState.UNAVAILABLE;
    this.clubRecruitmentInformation = ClubRecruitmentInformation.builder().build();
    this.userId = userId;
+   this.socialLinks = new HashMap<>();
}

또한 Builder 사용 시에도 초기화를 고려하세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private Map<String, String> socialLinks;
public Club() {
this.name = "";
this.category = "";
this.division = "";
this.state = ClubState.UNAVAILABLE;
this.clubRecruitmentInformation = ClubRecruitmentInformation.builder().build();
this.socialLinks = new HashMap<>();
}
public Club(String userId) {
this.name = "";
this.category = "";
this.division = "";
this.state = ClubState.UNAVAILABLE;
this.clubRecruitmentInformation = ClubRecruitmentInformation.builder().build();
this.userId = userId;
this.socialLinks = new HashMap<>();
}


private String userId;

private Map<String, String> socialLinks;
Copy link
Member

Choose a reason for hiding this comment

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

객체를 쓰지 않고 해시맵을 사용하신 이유가 있나요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

객체를 쓰게 되면 SNS의 확장성을 제한한다고 생각하였습니다. 대신 Map을 사용한다면 사용자들이 원하는 SNS에 대한 정보를 보다 자유롭게 제공할 수 있을것 같아요.

Copy link
Member

Choose a reason for hiding this comment

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

만약 Map을 사용한다면 링크 검증같은 것이 불가능해질 것 같습니다. 클래스로 바꾸는 것이 확장성을 오히려 고려하는 건 아닐까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

클래스를 꼭 만들지 않고도 링크 검증은 가능할것 같습니다만, 검증이 추가될거라면 자가검증 방식을 사용하는게 좋아보이긴 합니다. 다만 링크검증의 필요성에 대해 의문이 생기네요. 어떤 이유로 링크 검증이 필요하다고 생각하시나요?

Copy link
Member

Choose a reason for hiding this comment

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

인스타 아이콘을 눌렀는데 유튜브나 블로그가 나오는 건 사용자 경험 측면에서 안좋을 것 같아요. 그래서 검증이 필요하다고 생각했습니다.

Copy link
Member

Choose a reason for hiding this comment

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

추가로 클래스가 좋다고 생각한 이유는 검증 로직이 엔티티안에 있으면 깔끔할 거 같아서 그랬습니다.

PororoAndFriends

This comment was marked as abuse.


private String userId;

private Map<String, String> socialLinks;
Copy link
Collaborator

@PororoAndFriends PororoAndFriends May 2, 2025

Choose a reason for hiding this comment

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

주로 사용되는 SNS의 종류가 몇 종류 없다는 점과 키값 일관성과 검증도 된다는 점에서 키를 enum으로 구성해보는건 어떨까요? e.g. 키값이 "Youtube"인 곳도 있고 "yotube" 인 곳도 생길 것 같습니다
SNS의 확장성을 고려한다면 비주류 SNS들은 사용자가 선택지 추가를 요청하게 해서 확장성을 확보하는 방식으로 구성하는건 어떨까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

key를 enum으로 규제하는건 일관성을 지키기에 좋은 방법인것 같네요.

다만, 저는 사용자가 요청후 확장같은 번거로운 절차 없이 자유롭게 sns를 지정하는게 좋지 않을까 싶었습니다. 만약 사전에 정의된 SNS내에서 사용한다고 해도 사용자가 api요청을 직접하지 않는 이상 클라이언트 선에서 일관성을 유지하는게 가능하다고도 생각하는데 어떻게 생각하시나요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

말씀 들어보니 자유로운 확장성을 위해 클라이언트측에서 일관성을 유지하도록하고 저희는 가능성을 열어두는게 더 좋아보이네요!

Copy link
Collaborator

@PororoAndFriends PororoAndFriends left a comment

Choose a reason for hiding this comment

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

고생하셨습니다!

@Zepelown Zepelown dismissed their stale review May 3, 2025 13:08

이대로 올리기로 함

@Zepelown Zepelown self-requested a review May 3, 2025 13:08
Copy link
Member

@Zepelown Zepelown left a comment

Choose a reason for hiding this comment

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

고생하셨습니다

@Zepelown Zepelown merged commit 793c11f into develop/be May 3, 2025
3 checks passed
@lepitaaar lepitaaar deleted the feat/#362-social-links branch January 18, 2026 20:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💾 BE Backend ✨ Feature 기능 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

Comments