[feature] 관리자 페이지 동아리 SNS 링크 등록 기능 추가#400
Conversation
- InputField 컴포넌트에 isError 및 helperText prop 추가 - 에러 시 시각적 피드백 및 하단 에러 메시지 표시
- SnsConfig 기반 반복 렌더링으로 SNS 입력 필드 추가 - socialLinks 및 snsErrors 상태 관리 로직 적용 - validateSocialLink로 입력값 유효성 검증 - SNS 링크를 updateClub 요청에 포함
✅ Deploy Preview for moadong ready!
To edit notification comments on pull requests, go to your Netlify site configuration. |
Walkthrough이 변경 사항은 관리자 페이지에서 동아리의 SNS(Instagram, YouTube, X) 링크를 입력, 검증, 저장할 수 있도록 입력 UI, 상태 관리, URL 유효성 검사, 관련 데이터 모델 확장, 테스트 코드 추가 및 스타일링 컴포넌트를 도입합니다. 기존 컴포넌트와 타입에 SNS 관련 기능이 통합되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant Admin as AdminUser
participant UI as ClubInfoEditTab
participant Utils as validateSocialLink
participant API as UpdateClubAPI
Admin->>UI: SNS 링크 입력
UI->>Utils: validateSocialLink(플랫폼, 입력값)
Utils-->>UI: 에러 메시지 or ""
UI-->>Admin: 에러 메시지 표시 (있으면)
Admin->>UI: 등록 버튼 클릭
UI->>Utils: 각 SNS validateSocialLink
Utils-->>UI: 에러 메시지들
alt 에러 없음
UI->>API: socialLinks 포함 수정 요청
API-->>UI: 성공/실패 응답
UI-->>Admin: 결과 피드백(토스트 등)
else 에러 있음
UI-->>Admin: 에러 안내 및 등록 중단
end
Assessment against linked issues
Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. ✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Pull Request Overview
This pull request introduces SNS link input and validation functionality to the admin page while also refactoring component folder structures and enhancing type safety.
- Refactored component folder structure for better tab encapsulation.
- Added SNS link input fields with regex-based validation, error messaging, and type inference using SNS_CONFIG.
- Updated the common InputField component to support error styling and helper text display.
Reviewed Changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| frontend/src/types/club.ts | Introduces SNSPlatform type inference and adds socialLinks to ClubDetail. |
| frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx | Updates import paths for Calendar and MarkdownEditor to match new folder structure. |
| frontend/src/pages/AdminPage/tabs/PhotoEditTab/components/ImageUpload/ImageUpload.tsx | Minor reformatting of the onClick handler for clarity. |
| frontend/src/pages/AdminPage/tabs/PhotoEditTab/PhotoEditTab.tsx | Updates import paths of ImageUpload and ImagePreview components. |
| frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx | Adjusts button JSX formatting for consistency. |
| frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx | Adds SNS input fields and validation handling using SNS_CONFIG and updates club update payload. |
| frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.styles.ts | Adds styling for the SNS input section to improve UI layout. |
| frontend/src/constants/snsConfig.ts | Defines constant SNS settings with labels, placeholders, and regex validation. |
| frontend/src/components/common/InputField/InputField.tsx & InputField.styles.ts | Enhances InputField to support error state and helper text display. |
Comments suppressed due to low confidence (2)
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx:56
- [nitpick] Consider checking whether the current state already matches the incoming clubDetail.socialLinks before calling setSocialLinks to avoid unnecessary re-renders.
if (clubDetail?.socialLinks) { setSocialLinks({ instagram: clubDetail.socialLinks.instagram || '', youtube: clubDetail.socialLinks.youtube || '', x: clubDetail.socialLinks.x || '', }); }
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx:26
- [nitpick] If SNS_CONFIG is extended with additional platforms in the future, consider initializing the socialLinks state dynamically to reduce manual updates.
const [socialLinks, setSocialLinks] = useState<Record<SNSPlatform, string>>({ instagram: '', youtube: '', x: '', });
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (4)
frontend/src/pages/AdminPage/tabs/PhotoEditTab/components/ImageUpload/ImageUpload.tsx (1)
58-59: 미사용 주석 코드 제거 제안:UploadAddIconimport 제거 후 관련된 주석<img>태그가 남아있습니다. 불필요한 주석 코드는 제거하여 코드베이스를 정리하는 것을 권장합니다.frontend/src/components/common/InputField/InputField.styles.ts (1)
94-104: HelperText 컴포넌트의 위치 지정 방식 검토 필요HelperText가 absolute 포지셔닝을 사용하고 있는데, 이는 부모 컨테이너의 높이에 영향을 주지 않아 다른 요소와 겹칠 가능성이 있습니다. 특히 폼 요소가 여러 개 있는 경우 레이아웃 문제가 발생할 수 있습니다.
다음과 같은 방식으로 수정하는 것을 고려해보세요:
export const HelperText = styled.div` - position: absolute; - left: 0; - top: 100%; + position: relative; font-size: 0.75rem; color: red; - margin-top: 4px; + margin-top: 8px; pointer-events: none; white-space: nowrap; z-index: 1; `;frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (2)
197-201: 입력 필드의 변경 및 초기화 처리가 UX 관점에서 잘 설계되었습니다.사용자가 입력을 변경하거나 지울 때 적절한 처리가 이루어집니다. 특히 입력을 지울 때 에러 상태도 함께 초기화하는 점이 좋습니다.
다만, 다음 방식으로 코드를 더 간결하게 만들 수 있습니다:
- onClear={() => { - setSocialLinks((prev) => ({ ...prev, [key]: '' })); - setSnsErrors((prev) => ({ ...prev, [key]: '' })); - }} + onClear={() => { + handleSocialLinkChange(key, ''); + }}
1-214: 코드 스타일 및 구조에 대한 종합 의견전반적으로 코드 구조와 상태 관리가 잘 설계되어 있습니다. SNS_CONFIG를 기반으로 한 동적 UI 생성과 타입 안전성은 매우 좋은 접근 방식입니다.
몇 가지 개선할 수 있는 점은:
- 초기 상태 값을 중복해서 선언하는 부분을 함수나 상수로 분리하여 재사용할 수 있습니다.
- SNS 링크 검증 로직이 프론트엔드에만 있는데, 백엔드에서도 동일한 검증을 수행하는지 확인해 보세요.
- 로딩 상태나 제출 중 상태에 대한 UI 피드백이 추가되면 더 좋을 것 같습니다.
그 외에는 코드가 잘 구조화되어 있고, 새로운 SNS 플랫폼 추가도 쉽게 할 수 있는 확장성 있는 설계가 인상적입니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
frontend/src/components/common/InputField/InputField.styles.ts(2 hunks)frontend/src/components/common/InputField/InputField.tsx(4 hunks)frontend/src/constants/snsConfig.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.styles.ts(1 hunks)frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx(6 hunks)frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx(1 hunks)frontend/src/pages/AdminPage/tabs/PhotoEditTab/PhotoEditTab.tsx(1 hunks)frontend/src/pages/AdminPage/tabs/PhotoEditTab/components/ImageUpload/ImageUpload.tsx(1 hunks)frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx(1 hunks)frontend/src/types/club.ts(3 hunks)frontend/src/utils/validateSocialLink.test.ts(1 hunks)frontend/src/utils/validateSocialLink.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
frontend/src/types/club.ts (1)
frontend/src/constants/snsConfig.ts (1)
SNS_CONFIG(1-17)
frontend/src/utils/validateSocialLink.test.ts (3)
frontend/src/types/club.ts (1)
SNSPlatform(14-14)frontend/src/constants/snsConfig.ts (1)
SNS_CONFIG(1-17)frontend/src/utils/validateSocialLink.ts (1)
validateSocialLink(4-10)
frontend/src/utils/validateSocialLink.ts (2)
frontend/src/types/club.ts (1)
SNSPlatform(14-14)frontend/src/constants/snsConfig.ts (1)
SNS_CONFIG(1-17)
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (3)
frontend/src/types/club.ts (1)
SNSPlatform(14-14)frontend/src/utils/validateSocialLink.ts (1)
validateSocialLink(4-10)frontend/src/constants/snsConfig.ts (1)
SNS_CONFIG(1-17)
🔇 Additional comments (33)
frontend/src/pages/AdminPage/tabs/PhotoEditTab/components/ImageUpload/ImageUpload.tsx (1)
54-55: JSX 중괄호 닫힘 위치 변경 확인: onClick 핸들러의 닫는 괄호를 새 줄로 분리하여 가독성을 높인 변경으로, 기능에는 영향이 없습니다.frontend/src/pages/AdminPage/tabs/PhotoEditTab/PhotoEditTab.tsx (1)
4-5: 컴포넌트 경로 로컬라이제이션 적용 확인:ImageUpload및ImagePreview컴포넌트의 import 경로를 탭별 폴더 구조로 이동하여 모듈화 및 가독성을 개선한 변경입니다. 기능에는 영향이 없으며, 구조 개선에 긍정적입니다.frontend/src/pages/AdminPage/tabs/RecruitEditTab/RecruitEditTab.tsx (2)
4-4: 컴포넌트 경로 로컬라이제이션 적용 확인:Calendar컴포넌트 import 경로가 탭 폴더 내로 이동되었습니다. 구조 일관성이 향상되었습니다.
11-11: 컴포넌트 경로 로컬라이제이션 적용 확인:MarkdownEditor컴포넌트 import 경로가 탭 폴더 내로 이동되었습니다. 구조 일관성이 향상되었습니다.frontend/src/components/common/InputField/InputField.styles.ts (2)
22-38: 입력 필드의 오류 상태 스타일링이 잘 구현되었습니다.error 상태에 따라 border-color와 box-shadow 색상이 조건부로 변경되는 부분이 잘 구현되었습니다. 사용자에게 시각적 피드백을 제공하는 중요한 UI/UX 요소입니다.
45-47: placeholder 스타일 개선이 좋습니다.placeholder 텍스트 색상을 명시적으로 지정하여 사용자 입력 텍스트와의 구분을 명확히 한 것이 좋습니다.
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/components/SelectTags/SelectTags.tsx (1)
20-21: 코드 포맷팅 개선이 적절합니다.닫는 꺾쇠 괄호를 새 줄로 이동하여 JSX 코드의 가독성이 향상되었습니다. 이는 좋은 코딩 스타일 관행입니다.
frontend/src/types/club.ts (2)
14-14: SNSPlatform 타입 정의 방식이 매우 적절합니다.SNS_CONFIG의 키를 타입으로 사용함으로써, 설정 객체와 타입이 항상 동기화되는 장점이 있습니다. 새로운 SNS 플랫폼을 추가할 때도 SNS_CONFIG만 수정하면 타입도 자동으로 확장되어 유지보수성이 높아집니다.
25-25: Record 타입을 활용한 socialLinks 필드 추가가 잘 구현되었습니다.Record<SNSPlatform, string> 타입을 사용하여 각 SNS 플랫폼별로 링크를 저장하는 방식이 효율적입니다. 이 접근 방식은 타입 안전성을 보장하면서도 확장성이 뛰어납니다. SNS_CONFIG에 새 플랫폼을 추가하면 자동으로 ClubDetail 인터페이스도 해당 플랫폼을 지원하게 됩니다.
frontend/src/constants/snsConfig.ts (1)
1-17: 구조화 된 SNS 설정이 잘 구성되어 있습니다.SNS 플랫폼별 설정이 명확하게 정의되어 있고, 정규식 패턴도 적절하게 구현되어 있습니다.
as const를 사용하여 타입 안전성을 보장한 것도 좋은 접근입니다.몇 가지 고려할 만한 점:
- 새로운 SNS 플랫폼을 추가할 때 확장이 용이한 구조입니다.
- 정규식은 잘 작성되었지만, 플랫폼 URL 형식이 변경될 경우 대응이 필요합니다.
frontend/src/components/common/InputField/InputField.tsx (4)
17-18: 오류 상태 관리를 위한 속성 추가가 적절합니다.
isError와helperText속성 추가로 인해 InputField 컴포넌트의 재사용성이 향상되었습니다. 특히 폼 유효성 검사와 관련된 작업에서 사용자 경험을 개선할 수 있습니다.
33-34: 함수 매개변수에 오류 관련 속성 반영이 잘 되었습니다.InputField 함수 매개변수에
isError와helperText를 추가하여 인터페이스와 일관성을 유지했습니다.
71-71: Input 컴포넌트에 오류 상태 속성 적용이 적절합니다.Styled.Input 컴포넌트에
hasError속성을 전달하여 오류 상태를 시각적으로 표현할 수 있도록 했습니다. 이는 사용자 경험 측면에서 중요한 개선입니다.
89-91: 오류 메시지 표시 로직이 효율적으로 구현되었습니다.조건부 렌더링을 사용하여
isError와helperText가 모두 존재할 때만 오류 메시지를 표시하는 방식은 적절합니다. 이는 불필요한 UI 요소를 방지합니다.frontend/src/utils/validateSocialLink.test.ts (7)
5-6: 타입 정의가 명확하게 구성되었습니다.
LinkSet타입을Record<SNSPlatform, string>으로 정의하여 SNS 플랫폼과 URL 간의 매핑을 명확하게 표현했습니다. 이는 코드의 가독성과 유지보수성을 향상시킵니다.
7-23: 테스트 데이터가 다양한 케이스를 포함하고 있습니다.유효한 링크, 유효하지 않은 링크, 피싱 링크 등 다양한 테스트 케이스를 포함하고 있어 함수의 견고성을 검증하는데 적합합니다. 특히 보안 관련 테스트 케이스(피싱 링크)를 포함한 것은 매우 중요합니다.
25-25: SNS_CONFIG의 키를 동적으로 활용한 접근 방식이 효율적입니다.
Object.keys(SNS_CONFIG) as SNSPlatform[]을 사용하여 플랫폼 목록을 생성하는 방식은SNS_CONFIG가 변경되더라도 테스트 코드를 수정할 필요가 없게 해줍니다. 이는 유지보수성을 크게 향상시킵니다.
28-36: 헬퍼 함수 사용으로 테스트 코드가 간결해졌습니다.
expectNoError와expectError헬퍼 함수를 사용하여 반복적인 검증 로직을 추상화한 접근 방식이 훌륭합니다. 이로 인해 테스트 코드의 가독성이 향상되고 유지보수가 용이해졌습니다.
38-59: 기본적인 유효성 검사 시나리오가 잘 테스트되었습니다.유효한 링크, 유효하지 않은 링크, 빈 문자열, 피싱 링크에 대한 테스트가 모두 구현되어 있습니다. 특히
forEach를 사용하여 모든 플랫폼에 대해 일관되게 테스트하는 방식이 효율적입니다.
60-68: 보안 관련 에지 케이스 테스트가 추가되어 있습니다.HTTP 프로토콜과 유니코드 기반 도메인 위장에 대한 테스트가 포함되어 있어 보안 측면에서 중요한 케이스를 검증하고 있습니다. 특히 유니코드 도메인 위장은 흔히 간과되는 부분이라 이를 테스트한 것은 매우 가치 있습니다.
70-74: 리디렉션을 통한 공격 패턴 테스트가 구현되어 있습니다.리디렉션 파라미터를 사용한 악의적인 URL에 대한 테스트는 XSS 같은 보안 취약점을 방지하는데 중요합니다. 이런 세부적인 보안 테스트 케이스를 포함한 것은 매우 좋은 접근입니다.
frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.styles.ts (4)
34-35: TagEditGroup의 마진 조정으로 레이아웃이 개선되었습니다.새로운 SNS 입력 영역을 위해 기존 TagEditGroup의 margin-bottom을 조정했습니다. 이는 UI 요소 간의 적절한 간격을 보장하여 가독성을 향상시킵니다.
37-42: SNSInputGroup 스타일 컴포넌트가 잘 구성되어 있습니다.SNS 입력 필드 그룹을 위한 Flexbox 레이아웃이 적절하게 구성되어 있고, 간격과 여백도 UI/UX 관점에서 잘 설정되어 있습니다.
44-50: SNSRow 스타일 컴포넌트의 구조가 적절합니다.개별 SNS 입력 행을 위한 컴포넌트가 Flexbox 컬럼 레이아웃으로 구성되어 있고, 요소 간 간격과 정렬이 적절하게 설정되어 있습니다.
position: relative를 추가하여 절대 위치 요소를 포함할 수 있도록 준비한 점도 좋습니다.
52-57: SNSCheckboxLabel 스타일 컴포넌트가 접근성을 고려하였습니다.체크박스와 라벨 간의 간격과 정렬이 적절하게 설정되어 있고,
font-weight: 600을 적용하여 시각적 중요도를 강조했습니다. Flexbox를 사용한 정렬 방식도 적절합니다.frontend/src/pages/AdminPage/tabs/ClubInfoEditTab/ClubInfoEditTab.tsx (8)
3-8: Import 구조가 적절히 확장되었습니다.필요한 의존성들이 잘 추가되었습니다. SNS 기능 구현을 위한 유틸리티 함수(validateSocialLink), 상수(SNS_CONFIG), 타입(SNSPlatform)이 적절히 임포트되었습니다.
26-30: 소셜 링크 상태 관리가 타입 안전하게 구현되었습니다.
Record<SNSPlatform, string>타입을 사용하여 타입 안전성이 보장됩니다. SNS_CONFIG의 키와 일치하는 구조로 초기화하여 일관성을 유지하고 있습니다.
32-36: 에러 상태 관리가 적절히 구현되었습니다.각 SNS 플랫폼별 에러 메시지를 관리할 수 있는 구조가 잘 설계되었습니다. socialLinks와 동일한 구조로 일관성 있게 관리됩니다.
56-62: 기존 데이터 로딩 시 소셜 링크 초기화 로직이 안전하게 구현되었습니다.clubDetail에 socialLinks가 있는지 확인 후 초기화하는 방어적 코딩이 잘 적용되었습니다. 각 필드에 빈 문자열로 기본값을 설정하여 undefined 발생 가능성을 방지합니다.
65-69: 소셜 링크 변경 핸들러가 효율적으로 구현되었습니다.입력값 변경 시 즉시 유효성 검사를 수행하고 에러와 값을 동시에 업데이트하는 구조가 좋습니다. 하나의 함수로 여러 SNS 플랫폼을 처리할 수 있어 코드 중복을 방지합니다.
81-85: 폼 제출 전 유효성 검사 로직이 적절히 구현되었습니다.사용자가 폼을 제출하기 전에 SNS 링크 오류를 확인하는 방어 코드가 잘 작성되었습니다. 오류가 있을 경우 사용자에게 알림을 표시하여 UX가 향상되었습니다.
96-96: 업데이트 데이터에 소셜 링크가 포함되었습니다.API 요청에 socialLinks를 포함시켜 백엔드로 전송하는 구현이 적절합니다.
186-208: SNS 링크 입력 UI가 동적이고 재사용 가능하게 구현되었습니다.SNS_CONFIG 객체를 기반으로 입력 필드를 동적으로 생성하는 방식이 매우 효율적입니다. 새로운 SNS 플랫폼을 추가할 때 SNS_CONFIG만 수정하면 되어 확장성이 뛰어납니다.
각 입력 필드에 오류 표시 기능과 초기화 기능이 잘 구현되어 있습니다. 사용자가 입력을 지울 때 오류 상태도 함께 초기화하는 부분이 세심한 UX 고려를 보여줍니다.
seongwon030
left a comment
There was a problem hiding this comment.
정규표현식을 통해서 검증까지 정말 고생하셨습니다 !!

#️⃣연관된 이슈
📝작업 내용
default.mp4
1. 컴포넌트 폴더 구조 리팩토링
AdminPage/components폴더 내에 공통 및 탭별 컴포넌트가 혼재되어 있었습니다.AdminPage/tabs/{탭이름}/components로 이동.2. SNS 링크 입력 필드 추가
label,placeholder값을 적용하여 입력 가이드 제공3. SNS 설정 상수화 및 정규식 기반 검증 구조화
3-1. SNS 설정 상수 (
SNS_CONFIG)3-2. 플랫폼 키 타입 추론 (
SNSPlatform)SNS_CONFIG의 key를 기반으로SNSPlatform을 추론하여 상수-타입 간 일관성 확보3-3. 동아리 상세 타입 내 사용 (
ClubDetail)SNS_CONFIG만 수정하면, 타입 추론부터 UI 렌더링, 유효성 검증까지 가능하도록 설계했습니다!4. SNS 유효성 검사 및 테스트 코드 작성
validateSocialLink(platform, url)함수 구현 및 유닛 테스트 작성에러 발생 시 수정 요청은 막고 있지만, 패킷으로 우회할 수 있으니 백엔드 검증이나 프론트 렌더링 시 추가 검증이 필요합니다.

5. InputField 에러 메시지 기능 추가 및 UI 개선
중점적으로 리뷰받고 싶은 부분
SNS_CONFIG구조와 이를 기반으로 추론한SNSPlatform타입 설계가 괜찮은지InputField컴포넌트에error,helperTextprops를 추가한 방식이 괜찮은지🫡 참고사항
SNS_CONFIG에 같이 넣으면 될 것 같습니다Summary by CodeRabbit