-
Notifications
You must be signed in to change notification settings - Fork 2
✨Feat: 공통 사용자 프로필 구현 #33
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
Conversation
Walkthrough이번 변경에서는 글로벌 CSS와 Tailwind 기반 유틸리티 클래스, 웹 폰트, TypeScript 설정 파일, 클래스 병합 유틸리티 함수, 그리고 사용자 프로필 컴포넌트가 새롭게 추가되었습니다. Header 컴포넌트는 상태 관리 로직이 제거되고, 새로운 프로필 컴포넌트와 커스텀 스타일 클래스를 사용하도록 리팩터링되었습니다. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Header
participant Profile
User->>Header: 페이지 접근
Header->>Profile: nickname 등 props 전달
Profile-->>Header: 프로필 UI 반환
Header-->>User: 헤더(프로필 포함) 렌더링
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
npm error Exit handler never called! ✨ Finishing Touches
🪧 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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Caution
Inline review comments failed to post. This is likely due to GitHub's limits when posting large numbers of comments. If you are seeing this consistently it is likely a permissions issue. Please check "Moderation" -> "Code review limits" under your organization settings.
Actionable comments posted: 17
🧹 Nitpick comments (11)
src/app/shared/types/user.type.ts (1)
7-8: 타임스탬프 타입 검토 제안
createdAt/updatedAt를 ISO 문자열 대신Date타입으로 관리하는 방안을 고려해 보세요.src/app/loading.tsx (1)
2-2: 접근성 개선 제안
<div role="status" aria-live="polite">또는 스피너 아이콘 추가로 로딩 상태를 명확히 표시하는 것을 고려해 보세요.src/app/not-found.tsx (1)
1-3: 제안: 404 페이지 내 홈 링크 및 스타일 추가현재 단순 텍스트만 출력되므로, 사용자가 홈으로 돌아갈 수 있는 링크(
<Link href="/">홈으로</Link>)와 Tailwind 스타일을 추가해 사용자 경험을 개선하는 것을 권장합니다.src/app/page.tsx (1)
1-7: 접근성 강화:<main>시맨틱 태그 추가 제안랜딩 페이지에
<main>태그를 감싸서 시맨틱 마크업 및 접근성(ARIA) 지원을 강화하고, 페이지 구조를 명확히 하는 것이 좋습니다.postcss.config.mjs (1)
5-5: 주석 오타 수정 제안
// CSS애 접두사(Vendor Prefix, 예: -webkit-, -moz-) 붙여줌→// CSS에 접두사(Vendor Prefix, 예: -webkit-, -moz-) 붙여줌- autoprefixer: {}, // CSS애 접두사(Vendor Prefix, 예: -webkit-, -moz-) 붙여줌 + autoprefixer: {}, // CSS에 접두사(Vendor Prefix, 예: -webkit-, -moz-) 붙여줌src/app/shared/components/common/header/Header.tsx (1)
69-74: UI/UX 개선 제안마이페이지와 로그아웃 버튼이 단순한 텍스트 버튼으로 되어 있어 사용자 경험이 좋지 않을 수 있습니다. 드롭다운 메뉴나 더 명확한 버튼 스타일을 적용하는 것을 고려해보세요.
- <button onClick={goToMypage} className="text-xs"> - 마이페이지 - </button> - <button onClick={logout} className="text-xs"> - 로그아웃 - </button> + <div className="flex gap-2"> + <button onClick={goToMypage} className="Border-btn rounded-md px-3 py-1 text-xs hover:bg-gray-50"> + 마이페이지 + </button> + <button onClick={logout} className="Border-btn rounded-md px-3 py-1 text-xs hover:bg-gray-50"> + 로그아웃 + </button> + </div>.github/workflows/deploy.yml (1)
48-56: 헬스 체크 로직 개선 제안현재 헬스 체크는 단순히 컨테이너 실행 여부만 확인합니다. 실제 애플리케이션이 정상적으로 응답하는지 확인하는 것이 더 안전합니다.
if docker ps | grep -q coplan-app; then + # 애플리케이션 헬스 체크 추가 + if curl -f http://localhost:3000/api/health > /dev/null 2>&1; then + echo "✅ Application health check passed!" + else + echo "⚠️ Container running but application not responding" + fi echo "✅ Deployment completed successfully!" docker logs --tail 10 coplan-app - echo "🌐 Service available at: http://15.164.127.149" + echo "🌐 Service available at: ${{ secrets.SERVICE_URL }}" else echo "❌ Deployment failed!" docker logs coplan-app exit 1 fisrc/app/shared/components/common/Profile.tsx (3)
63-63: 한글 접두사 '사' 제거 제안사용자 이름 앞에 '사'를 붙이는 것이 의도적인 것인지 확인이 필요합니다. 일반적이지 않은 패턴이므로 제거하거나 설명이 필요합니다.
- <span className="text-sm font-semibold">사{user?.name}</span> + <span className="text-sm font-semibold">{user?.name}</span>
25-37: getInitial 함수 로직 개선현재 함수는 영어와 한글만 처리하고 있습니다. 다른 언어나 특수문자에 대한 처리를 개선할 수 있습니다.
function getInitial(nickname: string): string { - const firstChar = nickname.trim().charAt(0) + const trimmedNickname = nickname.trim() + if (!trimmedNickname) return '?' + + const firstChar = trimmedNickname.charAt(0) if (/[a-zA-Z]/.test(firstChar)) { return firstChar.toUpperCase() // 영어: 대문자 } if (/[가-힣]/.test(firstChar)) { return firstChar // 한글은 그대로 반환 } - return '?' // 기타문자: 물음표 + // 숫자나 기타 문자의 경우 첫 번째 문자 반환 + return firstChar.toUpperCase() }
67-79: 스타일링 일관성 개선imageUrl이 있을 때와 없을 때의 레이아웃이 다릅니다. 일관된 사용자 경험을 위해 레이아웃을 통일하는 것을 고려해보세요.
) : ( - <> + <div className="flex items-center gap-4"> <div - className="ml-8 flex items-center justify-center rounded-full font-semibold text-white" + className="flex items-center justify-center rounded-full font-semibold text-white" style={{ width: size, height: size, fontSize: size * 0.4, // 글자 크기 조정 backgroundColor: bgColor, }} > {initial} </div> - <div className="text-base font-medium">{nickname}</div> - </> + <span className="text-sm font-semibold">{nickname}</span> + </div> ).eslintrc.js (1)
39-42: 함수 스타일 규칙을 재검토해보세요.현재 설정은 함수 선언식을 권장하면서 화살표 함수도 허용하고 있습니다. 하지만 React 컴포넌트나 훅에서는 함수 표현식이 일반적으로 사용됩니다. 팀의 코딩 스타일에 따라 이 규칙을 완전히 비활성화(
'off')하는 것을 고려해보세요.- 'func-style': ['warn', 'declaration', { allowArrowFunctions: true }], + 'func-style': 'off', // React 컴포넌트에서의 유연성을 위해
🛑 Comments failed to post (17)
src/app/dashboard/[id]/edit/page.tsx (1)
1-3: 🛠️ Refactor suggestion
컴포넌트 명명 컨벤션 수정 필요
React 컴포넌트는 PascalCase(
DashboardEditPage)로 명명하는 것이 권장됩니다. 파일명에 맞춰 함수명도 일관성 있게 변경해주세요.🤖 Prompt for AI Agents
In src/app/dashboard/[id]/edit/page.tsx at lines 1 to 3, the React component function name dashBoardEditPage does not follow the PascalCase naming convention. Rename the function to DashboardEditPage to match the recommended React component naming style and ensure consistency with the file name.src/app/dashboard/[id]/edit/layout.tsx (1)
1-7:
⚠️ Potential issueReactNode 타입 import 누락 (빌드 에러 발생 가능)
children에React.ReactNode를 사용하려면react에서 해당 타입을 import해야 합니다. 아래와 같이 수정해주세요.@@ -1,2 +1,3 @@ import Header from '@components/common/header/Header' +import type { ReactNode } from 'react' -export default function AboutLayout({ - children, -}: { - children: React.ReactNode -}) { +export default function AboutLayout({ + children, +}: { + children: ReactNode +}) { return ( <div> <Header /> <div>{children}</div> {/* 여기에 page.tsx 내용이 들어옴 */} </div> ) }Also applies to: 9-14
🤖 Prompt for AI Agents
In src/app/dashboard/[id]/edit/layout.tsx around lines 1 to 14, the ReactNode type is used for the children prop but ReactNode is not imported from 'react', which can cause build errors. Fix this by adding an import statement for ReactNode from 'react' at the top of the file, ensuring the type is properly recognized.README.md (1)
1-8: 🛠️ Refactor suggestion
프로젝트 시작 가이드 구체화 제안
현재 브랜치 전략, 폴더 구조 등이 설명되어 있으나,npm install,npm run dev,npm run build등 개발자가 즉시 실행할 수 있는 명령 예시가 누락되어 있습니다.## 설치 및 실행 ```bash npm install npm run dev # 개발 서버 시작 npm run build # 프로덕션 빌드 npm start # 빌드된 앱 실행<details> <summary>🤖 Prompt for AI Agents</summary>In README.md lines 1 to 8, the project start guide lacks concrete instructions
for installing dependencies and running the project. Add a new section titled
"설치 및 실행" that includes example commands such asnpm install,npm run dev,
npm run build, andnpm startwith brief comments explaining each command to
help developers quickly set up and run the project.</details> </blockquote></details> <details> <summary>tsconfig.json (1)</summary><blockquote> 22-30: _💡 Verification agent_ <details> <summary>🧩 Analysis chain</summary> **경로 별칭 설정이 잘 구성되어 있습니다.** 별칭 설정이 프로젝트 구조와 일치하며, 일관된 import 패턴을 지원합니다. 한국어 주석도 개발팀에게 도움이 됩니다. 프로젝트 전체에서 별칭이 일관되게 사용되는지 확인해보겠습니다: --- 🏁 Script executed: ```shell #!/bin/bash # 프로젝트에서 정의된 별칭들이 실제로 사용되고 있는지 확인 echo "=== @/* 별칭 사용 확인 ===" rg -g "*.{ts,tsx}" "from ['\"]@/" --count echo "=== @components/* 별칭 사용 확인 ===" rg -g "*.{ts,tsx}" "from ['\"]@components/" --count echo "=== @store/* 별칭 사용 확인 ===" rg -g "*.{ts,tsx}" "from ['\"]@store/" --count echo "=== @lib/* 별칭 사용 확인 ===" rg -g "*.{ts,tsx}" "from ['\"]@lib/" --countLength of output: 758
프로젝트 전체에서 ‘@hooks/*’ 별칭 사용 여부를 추가로 확인하겠습니다:
🏁 Script executed:
#!/bin/bash echo "=== @hooks/* 별칭 사용 확인 ===" rg -g "*.{ts,tsx}" "from ['\"]@hooks/" --countLength of output: 111
@hooks/ 및 @/ 별칭이 사용되지 않음 확인**
프로젝트 내 ts/tsx 파일에서 다음 별칭만 실제로 import 구문에 사용되고 있었습니다:
- @components/*
- @store/*
- @lib/*
반면에
@hooks/*와 최상위@/*별칭은 어떤 import에서도 발견되지 않았습니다.
필요 없는 별칭이라면 tsconfig.json에서 제거하시거나, 앞으로 사용할 계획이 있다면 해당 경로로 import 구문이 제대로 반영되었는지 검토해주세요.• 대상 파일: tsconfig.json (Lines 22–30)
• 미사용 별칭:
- "@/": ["./src/"]
- "@hooks/": ["./src/app/shared/hooks/"]
🤖 Prompt for AI Agents
In tsconfig.json around lines 22 to 30, the path aliases "@/*" and "@hooks/*" are defined but not used anywhere in the project imports. To fix this, either remove these unused aliases from the paths configuration to keep the config clean, or if you plan to use them later, ensure that import statements correctly reference these aliases in the codebase.
src/app/shared/components/ThemeToggle.tsx (1)
17-24: 🛠️ Refactor suggestion
접근성을 위한 aria-label 추가를 권장합니다.
버튼에 시각적 텍스트가 없으므로 스크린 리더 사용자를 위한 접근성 라벨이 필요합니다.
다음과 같이 개선하세요:
<button + aria-label={isDark ? '라이트 모드로 전환' : '다크 모드로 전환'} className="BG-ThemeToggle relative flex h-30 w-60 rounded-25 bg-[url('/images/darkmode.svg')] bg-center bg-no-repeat" onClick={() => setTheme(isDark ? 'light' : 'dark')} >📝 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.<button aria-label={isDark ? '라이트 모드로 전환' : '다크 모드로 전환'} className="BG-ThemeToggle relative flex h-30 w-60 rounded-25 bg-[url('/images/darkmode.svg')] bg-center bg-no-repeat" onClick={() => setTheme(isDark ? 'light' : 'dark')} > <div className={`BG-ThemeToggleButton absolute bottom-5 left-6 size-20 rounded-full transition-transform duration-[0.4s] ease-in-out ${isDark ? 'translate-x-28' : 'translate-x-0'}`} ></div> </button>🤖 Prompt for AI Agents
In src/app/shared/components/ThemeToggle.tsx around lines 17 to 24, the button lacks an aria-label, which is necessary for screen reader users since there is no visible text. Add an appropriate aria-label attribute to the button element that clearly describes its function, such as "Toggle dark mode" or "Switch theme," to improve accessibility.
src/app/tester/page.tsx (1)
43-43:
⚠️ Potential issueCSS 클래스에 오타가 있습니다.
marker:flex는 유효하지 않은 클래스입니다.flex로 수정해야 합니다.다음과 같이 수정하세요:
- <div className="gap-16 bg-gray-100 p-4 marker:flex"> + <div className="flex gap-16 bg-gray-100 p-4">📝 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.<div className="flex gap-16 bg-gray-100 p-4">🤖 Prompt for AI Agents
In src/app/tester/page.tsx at line 43, the className contains a typo: 'marker:flex' is not a valid CSS class. Replace 'marker:flex' with 'flex' to correct the className.
src/app/shared/store/useUserStore.ts (1)
14-26: 💡 Verification agent
🧩 Analysis chain
Zustand 스토어 구성이 올바릅니다.
persist 미들웨어 사용과 메서드 구현이 적절합니다.
하지만 브라우저 로컬 스토리지에 액세스 토큰을 저장하는 것은 보안상 위험할 수 있습니다. 다음을 확인해주세요:
🌐 Web query:
localStorage에 JWT 토큰을 저장하는 것의 보안 위험성과 대안 방법💡 Result:
localStorage에 JWT 토큰을 저장하는 것의 보안 위험성과 대안 방법에 대해 설명해 드리겠습니다.
보안 위험성
XSS(교차 사이트 스크립팅) 공격에 취약함
localStorage는 자바스크립트 코드에서 접근할 수 있기 때문에, 만약 사이트에 XSS 취약점이 존재하면 공격자가 악성 스크립트를 삽입하여 localStorage에 저장된 JWT 토큰을 탈취할 수 있습니다.CSRF 공격에는 어느 정도 안전하지만 비정상적인 행위에 노출될 수 있음
localStorage에 저장된 토큰은 자동으로 요청 헤더에 붙지 않으며, 자바스크립트 코드에서 직접 첨부해야 하므로 CSRF 공격은 상대적으로 적지만, XSS에 의해 조작될 수 있는 위험이 더 큽니다.브라우저 정책에 따른 데이터 접근
사용자 또는 다른 스크립트가 브라우저 콘솔을 통해 쉽게 localStorage에 접근할 수 있습니다. 즉, 보호가 어려움.대안 방법
HttpOnly 쿠키 사용
JWT를 HttpOnly 속성이 설정된 쿠키에 저장하면 자바스크립트에서 접근할 수 없으므로 XSS로부터 안전합니다.
다만, CSRF 공격 위험이 있으므로 CSRF 토큰을 함께 사용하거나 SameSite 속성을 사용해 CSRF를 방어합니다.메모리 저장소 사용
JWT를 localStorage나 세션스토리지 대신 메모리에만 저장해서 페이지를 벗어나거나 새로고침 시 토큰이 사라지도록 하는 방법입니다. 이 방법은 XSS 위험을 줄이지만, 페이지 리로드 시 인증 상태가 사라집니다.Content Security Policy(CSP) 적용
스크립트 삽입을 방지하는 CSP를 적용해 XSS 공격 자체를 줄이는 보조적인 방법입니다.Access Token과 Refresh Token 분리 저장
Access Token은 메모리나 HttpOnly 쿠키에 저장하고, Refresh Token은 HttpOnly, Secure 쿠키에 저장해 보안을 강화할 수 있습니다.토큰 암호화 및 짧은 만료 시간 설정
토큰 자체를 암호화하거나 만료 시간을 짧게 설정해 탈취 시 피해를 최소화하는 방법도 중요합니다.요약하면, localStorage에 JWT를 저장하는 방식은 간편하지만 XSS 공격에 매우 취약하므로, 보안이 중요한 서비스라면 HttpOnly 쿠키에 저장하고 CSRF 방어 대책을 함께 사용하는 것이 권장됩니다.
보안 경고: accessToken 저장소 재검토 필요
브라우저 localStorage에 JWT 토큰을 저장할 경우 XSS 공격 시 토큰 탈취 위험이 크므로, 보다 안전한 저장 방식을 적용해야 합니다.
해당 코드 위치
- 파일: src/app/shared/store/useUserStore.ts
- Lines: 14–26
제안 사항
- localStorage 대신 HttpOnly, Secure 쿠키에 accessToken 저장
• SameSite 속성 및 CSRF 토큰 검증 병행- 민감한 토큰은 메모리 저장 후 페이지 언로드 시 소멸하도록 고려
- CSP 적용으로 스크립트 삽입(XSS) 리스크 추가 완화
- Access/Refresh Token 분리: Access는 메모리 또는 쿠키, Refresh는 HttpOnly 쿠키에 보관
위 대안을 검토 후 코드를 수정해주세요.
🤖 Prompt for AI Agents
In src/app/shared/store/useUserStore.ts around lines 14 to 26, the current implementation persists the accessToken in localStorage via Zustand's persist middleware, which poses a security risk due to XSS vulnerabilities. To fix this, remove the persistence of accessToken from localStorage and instead manage the accessToken using HttpOnly, Secure cookies set by the server with appropriate SameSite attributes and CSRF protections. Alternatively, keep the accessToken only in memory within the store without persisting it, so it clears on page unload. Adjust the store code to no longer persist accessToken and ensure token handling aligns with secure cookie usage and CSRF defenses as per best practices.
src/app/shared/components/common/header/Header.tsx (4)
19-19:
⚠️ Potential issue커스텀 CSS 클래스명 일관성 문제
클래스명이 일관되지 않습니다.
BG-White는 대문자 W를 사용하고 있으나, 다른 곳에서는 소문자를 사용하고 있습니다. globals.css의 정의와 일치하도록 수정이 필요합니다.- <header className="BG-White Border-section Text-black flex items-center justify-between border-b px-36 py-16"> + <header className="BG-white Border-section Text-black flex items-center justify-between border-b px-36 py-16">📝 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.<header className="BG-white Border-section Text-black flex items-center justify-between border-b px-36 py-16">🤖 Prompt for AI Agents
In src/app/shared/components/common/header/Header.tsx at line 19, the CSS class name "BG-White" uses an uppercase "W" which is inconsistent with other usages and does not match the definition in globals.css. Change "BG-White" to "bg-white" to ensure consistent lowercase naming and alignment with the global CSS definitions.
66-66: 🛠️ Refactor suggestion
불필요한 구분자 제거
|문자가 JSX 내에서 텍스트로 렌더링되어 UI에 표시됩니다. 이것이 의도된 것인지 확인하고, 시각적 구분자가 필요하다면 적절한 CSS 스타일링을 사용하는 것이 좋습니다.- |{/* 내 프로필 이미지 */} + {/* 내 프로필 이미지 */}📝 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.{/* 내 프로필 이미지 */}🤖 Prompt for AI Agents
In src/app/shared/components/common/header/Header.tsx at line 66, remove the '|' character from the JSX as it is rendering as visible text in the UI. If a visual separator is needed, replace this character with appropriate CSS styling instead of a text symbol.
67-67: 🛠️ Refactor suggestion
하드코딩된 닉네임 개선 필요
닉네임이 하드코딩되어 있습니다. useUserStore에서 실제 사용자 데이터를 가져와 사용하는 것이 좋겠습니다.
- <Profile nickname="전유진" /> + <Profile nickname={user?.name || "사용자"} />📝 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.<Profile nickname={user?.name || "사용자"} />🤖 Prompt for AI Agents
In src/app/shared/components/common/header/Header.tsx at line 67, the nickname "전유진" is hardcoded in the Profile component. Replace this hardcoded value by importing and using the actual user data from useUserStore, passing the user's nickname dynamically to the Profile component instead.
47-47:
⚠️ Potential issue클래스명 오타 수정 필요
rounded-6이rounded-md이어야 할 것 같습니다. Tailwind CSS의 표준 클래스명을 사용해야 합니다.- className={cn( - 'Border-btn mr-16 flex items-center gap-6 rounded-6 border-solid px-12 py-6', - pathname === '/modal' && 'font-semibold', - )} + className={cn( + 'Border-btn mr-16 flex items-center gap-6 rounded-md border-solid px-12 py-6', + pathname === '/modal' && 'font-semibold', + )}📝 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.className={cn( 'Border-btn mr-16 flex items-center gap-6 rounded-md border-solid px-12 py-6', pathname === '/modal' && 'font-semibold', )}🤖 Prompt for AI Agents
In src/app/shared/components/common/header/Header.tsx at line 47, the class name 'rounded-6' is incorrect and should be replaced with the standard Tailwind CSS class 'rounded-md'. Update the class string to use 'rounded-md' instead of 'rounded-6' to ensure proper styling.
src/app/globals.css (1)
4-5:
⚠️ Potential issue@import 규칙 위치 수정 필요
정적 분석 도구에서 지적한 대로,
@import규칙은 다른 모든 CSS 규칙보다 앞에 위치해야 합니다. 현재 위치가 올바르지 않습니다.@tailwind base; @tailwind components; @tailwind utilities; -@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap'); -@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css'); :root { --font-sans: 'Pretendard', 'Noto Sans KR', sans-serif; } + +@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap'); +@import url('https://cdn.jsdelivr.net/gh/orioncactus/pretendard/dist/web/static/pretendard.css');또는 Next.js의
next/font를 사용하여 폰트를 최적화하는 것을 고려해보세요.Committable suggestion skipped: line range outside the PR's diff.
🧰 Tools
🪛 Biome (1.9.4)
[error] 4-4: This @import is in the wrong position.
Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid.
Consider moving import position.(lint/correctness/noInvalidPositionAtImportRule)
[error] 5-5: This @import is in the wrong position.
Any @import rules must precede all other valid at-rules and style rules in a stylesheet (ignoring @charset and @layer), or else the @import rule is invalid.
Consider moving import position.(lint/correctness/noInvalidPositionAtImportRule)
🤖 Prompt for AI Agents
In src/app/globals.css around lines 4 to 5, the @import rules are not placed at the very top of the CSS file as required. Move all @import statements to the very beginning of the file before any other CSS rules to comply with CSS standards and avoid static analysis warnings. Alternatively, consider using Next.js's next/font for optimized font loading.
.github/workflows/deploy.yml (2)
16-16:
⚠️ Potential issueGitHub Actions checkout 버전 업데이트 필요
정적 분석 도구에서 지적한 대로,
actions/checkout@v3는 너무 오래된 버전입니다. 최신 버전으로 업데이트해야 합니다.- uses: actions/checkout@v3 + uses: actions/checkout@v4📝 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.uses: actions/checkout@v4🧰 Tools
🪛 actionlint (1.7.7)
16-16: the runner of "actions/checkout@v3" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🤖 Prompt for AI Agents
In .github/workflows/deploy.yml at line 16, the GitHub Actions checkout step uses an outdated version 'actions/checkout@v3'. Update this to the latest available version, such as 'actions/checkout@v4', to ensure compatibility and benefit from recent improvements and fixes.
51-51:
⚠️ Potential issue하드코딩된 IP 주소 보안 이슈
서비스 URL에 하드코딩된 IP 주소가 노출되어 있습니다. 이는 보안상 위험할 수 있습니다. GitHub Secrets이나 환경 변수를 사용하는 것이 좋습니다.
- echo "🌐 Service available at: http://15.164.127.149" + echo "🌐 Service available at: ${{ secrets.SERVICE_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.echo "🌐 Service available at: ${{ secrets.SERVICE_URL }}"🤖 Prompt for AI Agents
In .github/workflows/deploy.yml at line 51, the service URL contains a hardcoded IP address, which poses a security risk. Replace the hardcoded IP with a reference to a GitHub Secret or environment variable that stores the IP address securely. Update the echo command to use this variable instead of the fixed IP.
src/app/shared/components/common/Profile.tsx (1)
53-64:
⚠️ Potential issueimageUrl props와 구현 불일치
imageUrlprops를 받지만 실제로는 하드코딩된 이미지 경로(/images/profile.gif)를 사용하고 있습니다. 이는 props의 목적과 맞지 않습니다.return imageUrl ? ( <div className="flex items-center gap-4"> <div className="relative size-48 overflow-hidden rounded-full"> <Image - src="/images/profile.gif" + src={imageUrl} fill alt="프로필 이미지" className="size-full object-cover" /> </div> <span className="text-sm font-semibold">사{user?.name}</span> </div> ) : (📝 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.return imageUrl ? ( <div className="flex items-center gap-4"> <div className="relative size-48 overflow-hidden rounded-full"> <Image src={imageUrl} fill alt="프로필 이미지" className="size-full object-cover" /> </div> <span className="text-sm font-semibold">사{user?.name}</span> </div>🤖 Prompt for AI Agents
In src/app/shared/components/common/Profile.tsx around lines 53 to 64, the component receives an imageUrl prop but uses a hardcoded image path instead. Update the Image component's src attribute to use the imageUrl prop value rather than the fixed "/images/profile.gif" path to align with the intended use of the prop.
package.json (1)
11-25: 🛠️ Refactor suggestion
의존성 버전 관리 정책을 일관되게 적용하세요.
React와 React DOM은 정확한 버전(18.2.0)으로 고정되어 있는 반면, 다른 라이브러리들은 캐럿(^) 범위를 사용하고 있습니다. 프로젝트의 안정성을 위해 일관된 버전 관리 정책을 적용하는 것을 권장합니다.
- "react": "18.2.0", - "react-dom": "18.2.0", + "react": "^18.2.0", + "react-dom": "^18.2.0",또는 더 엄격한 관리를 원한다면 모든 의존성을 정확한 버전으로 고정하는 것도 고려해보세요.
📝 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."dependencies": { "@dnd-kit/core": "^6.3.1", "@tanstack/react-query": "^5.80.2", "axios": "^1.9.0", "clsx": "^2.1.1", "next": "14.2.25", "next-themes": "^0.4.6", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hook-form": "^7.57.0", "sonner": "^2.0.5", "tailwind-merge": "^3.3.0", "tailwindcss-preset-px-to-rem": "^1.2.1", "zustand": "^5.0.5" },🤖 Prompt for AI Agents
In package.json lines 11 to 25, the dependency versions are inconsistently managed: React and React DOM use exact versions while others use caret ranges. To fix this, update all dependencies to either use exact version numbers or consistently use caret ranges, depending on your project's version management policy. This ensures uniformity and improves project stability.
.eslintrc.js (1)
76-78: 💡 Verification agent
🧩 Analysis chain
Tailwind CSS 설정 파일 경로를 확인하세요.
설정에서
./tailwind.config.js를 참조하고 있지만, 일반적으로 TypeScript 프로젝트에서는tailwind.config.ts를 사용합니다. 실제 프로젝트의 Tailwind 설정 파일 이름과 일치하는지 확인해주세요.
🏁 Script executed:
#!/bin/bash # Tailwind 설정 파일 존재 여부 확인 fd -t f "tailwind.config" --max-depth 1Length of output: 58
.eslintrc.js에서 Tailwind 설정 파일 경로를 수정하세요
프로젝트 루트에
tailwind.config.ts가 존재하므로,.eslintrc.js의 Tailwind 설정 경로를.js에서.ts로 변경해야 합니다.
- 파일:
.eslintrc.js- 위치: 약 76–78행
수정 전/후 예시:
tailwindcss: { - config: './tailwind.config.js', // Tailwind CSS 설정 파일 경로 + config: './tailwind.config.ts', // Tailwind CSS 설정 파일 경로 whitelist: ['html', 'js', 'jsx', 'ts', 'tsx'],📝 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.tailwindcss: { config: './tailwind.config.ts', // Tailwind CSS 설정 파일 경로 (커스터마이징 필요 시) whitelist: ['html', 'js', 'jsx', 'ts', 'tsx'], // Tailwind 클래스 검색할 확장자 지정. 정확한 분석을 위함🤖 Prompt for AI Agents
In .eslintrc.js around lines 76 to 78, update the Tailwind CSS config file path from './tailwind.config.js' to './tailwind.config.ts' to match the actual TypeScript configuration file used in the project.
Insung-Jo
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
수고 많으셨습니다! 리뷰 하면서 처음 보는 함수나 새로운 정규 표현식에 대해 알 수 있어서 좋았습니다! 👍 👍
dkslel1225
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로필 구현 수고하셨습니다!⭐️⭐️
LeeCh0129
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
프로필 컴포넌트를 잘구현해주셨네요, 수고많으셨습니다~👍
…o feature/Profile
…o feature/Profile
There was a problem hiding this 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
♻️ Duplicate comments (1)
src/app/shared/components/common/Profile.tsx (1)
5-9:size프롭 사용 일관성 부족
size값은 무이미지 분기에서만 활용되고 이미지 분기에서는 고정size-48로 하드코딩되어 있습니다. 프롭을 유지하려면 두 분기 모두 동일하게 적용하거나, 필요 없다면 아예 제거해 주세요.
🧹 Nitpick comments (2)
src/app/shared/components/common/Profile.tsx (2)
1-1: Server Component로 내려도 무방해 보입니다 –use client제거 고려클라이언트 훅이나 이벤트 핸들러가 없으므로 굳이
use client지시어를 둘 필요가 없습니다. 서버 컴포넌트로 두면 번들 크기를 줄이고 렌더 성능을 개선할 수 있습니다.
65-77: 하드코딩된ml-8여백은 재사용성을 떨어뜨립니다컴포넌트 내부에서 margin을 강제하면 호출 위치에 따라 불필요한 간격이 생길 수 있습니다. 부모 컨테이너에서 간격을 제어하도록 margin 클래스를 제거하고, 필요하다면 외부에서 Tailwind
gap-*또는ml-*를 전달하는 편이 유연합니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/app/shared/components/common/Profile.tsx(1 hunks)src/app/shared/components/common/header/Header.tsx(5 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/app/shared/components/common/header/Header.tsx
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: eslint-check
| return imageUrl ? ( | ||
| // 프로필 이미지가 있을 때 | ||
| <div className="flex items-center gap-4"> | ||
| <div className="relative size-48 overflow-hidden rounded-full"> | ||
| <Image | ||
| src="/images/profile.gif" | ||
| fill | ||
| alt="프로필 이미지" | ||
| className="size-full object-cover" | ||
| /> | ||
| </div> | ||
| <span className="text-sm font-semibold">사용자</span> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
imageUrl 프롭이 무시되고 있습니다
imageUrl이 truthy여도 실제로는 하드코딩된 /images/profile.gif를 렌더링하고 nickname 대신 "사용자" 텍스트를 표기하고 있습니다. 이는 명백한 기능 오류입니다.
- <Image
- src="/images/profile.gif"
- fill
- alt="프로필 이미지"
- className="size-full object-cover"
- />
+ <Image
+ src={imageUrl}
+ fill
+ alt={`${nickname} 프로필 이미지`}
+ className="size-full object-cover"
+ />
...
- <span className="text-sm font-semibold">사용자</span>
+ <span className="text-sm font-semibold">{nickname}</span>또한 컨테이너에 style={{ width: size, height: size }} 를 동일하게 적용하여 size 프롭을 일관되게 반영해 주세요.
📝 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.
| return imageUrl ? ( | |
| // 프로필 이미지가 있을 때 | |
| <div className="flex items-center gap-4"> | |
| <div className="relative size-48 overflow-hidden rounded-full"> | |
| <Image | |
| src="/images/profile.gif" | |
| fill | |
| alt="프로필 이미지" | |
| className="size-full object-cover" | |
| /> | |
| </div> | |
| <span className="text-sm font-semibold">사용자</span> | |
| </div> | |
| return imageUrl ? ( | |
| // 프로필 이미지가 있을 때 | |
| <div className="flex items-center gap-4"> | |
| <div className="relative size-48 overflow-hidden rounded-full"> | |
| <Image | |
| src={imageUrl} | |
| fill | |
| alt={`${nickname} 프로필 이미지`} | |
| className="size-full object-cover" | |
| /> | |
| </div> | |
| <span className="text-sm font-semibold">{nickname}</span> | |
| </div> |
🤖 Prompt for AI Agents
In src/app/shared/components/common/Profile.tsx around lines 50 to 62, the
imageUrl prop is ignored because the Image component always uses the hardcoded
"/images/profile.gif" source and the nickname is replaced with the fixed text
"사용자". To fix this, update the Image src to use the imageUrl prop and replace
the fixed nickname text with the nickname prop. Also, apply the style attribute
with width and height set to the size prop on the container div to ensure
consistent sizing.
📌 변경 사항 개요
✨ 요약
공통 사용자 프로필 구현 및 추가 사항 반영
📝 상세 내용
🐛Fix: 파일명 변경 사항 미반영 에러 수정
🔧Chore: lib 사용을 위한 alias 설정 추가
🎨Style:
✨Feat:
🔗 관련 이슈
🖼️ 스크린샷
✅ 체크리스트
💡 참고 사항
src/app/shared/lib/cn.ts파일의 clsx + twMerge 방식 반영하여 사용하시면 될 것 같습니다!!Summary by CodeRabbit
신규 기능
리팩터링
환경 설정