Skip to content

✨Feat : MyPage 작업#67

Merged
KongMezu merged 20 commits intodevelopfrom
feat/#44/mypage
Oct 29, 2025
Merged

✨Feat : MyPage 작업#67
KongMezu merged 20 commits intodevelopfrom
feat/#44/mypage

Conversation

@KongMezu
Copy link
Copy Markdown
Contributor

@KongMezu KongMezu commented Oct 27, 2025

🔥 작업 내용

  • 엽서 저장 컨테이너 컴포넌트
  • 프로필 이미지 컴포넌트
  • 마이페이지 레이아웃

🤔 추후 작업 사항

  • 이벤트 페이지
  • 이벤트 클릭 페이지

🔗 이슈

PR Point (To Reviewer)

mypage 하위 폴더 파일들 + global.css 만 보시면 될 거 같습니다

MyPage 레이아웃 작업

페이지 레이아웃 작업해놨습니다.
엽서 저장 컨테이너는 8개 이상이 될 조건부로 가로 스크롤로 가능하도록 해놨습니다.
2행 고정 + 가로 확장형 그리드: grid-rows-2 + grid-flow-col + auto-cols-[70px]

Barrel 파일 & global.css 스크롤 숨김 추가

공동컴포넌트들을 Barrel 파일로 불러왔습니다. 또 스크롤바가 나오면 디자인이 틀어져, global.css 에 스크롤바를 숨기도록 아래처럼 추가해뒀습니다.

.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

📸 피그마 스크린샷 or 기능 GIF

스크린샷 2025-10-28 001250 스크린샷 2025-10-28 001412 스크린샷 2025-10-28 002854
KakaoTalk_20251028_011213062.mp4

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • 사용자 마이페이지 추가: 프로필 영역, 저장된 이벤트(예시 카드), 저장된 포스트카드 그리드, 하단 내비게이션, 로그아웃 확인 팝업 포함
    • 저장된 포스트카드 썸네일 그리드(스크롤 및 선택 가능) 추가
    • 프로필 사진 표시 컴포넌트 추가
  • 스타일

    • 메인 페이지 상단 헤더를 아이콘으로 대체
    • 스크롤바 숨김 스타일 추가
  • 변경

    • 주소 복사 동작이 간단한 플레이스홀더 텍스트로 변경

@vercel
Copy link
Copy Markdown

vercel bot commented Oct 27, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Comments Updated (UTC)
af-fe Ready Ready Preview Comment Oct 29, 2025 2:48pm

@github-actions github-actions bot added the style 코드 스타일 변경(기능 변경 없음) label Oct 27, 2025
@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Oct 27, 2025

Important

Review skipped

Review was skipped due to path filters

⛔ Files ignored due to path filters (17)
  • src/shared/icons/source/CalendarBlank.svg is excluded by !**/*.svg
  • src/shared/icons/source/Caret.svg is excluded by !**/*.svg
  • src/shared/icons/source/ChatCircle.svg is excluded by !**/*.svg
  • src/shared/icons/source/Check.svg is excluded by !**/*.svg
  • src/shared/icons/source/CopySimple.svg is excluded by !**/*.svg
  • src/shared/icons/source/Export.svg is excluded by !**/*.svg
  • src/shared/icons/source/FadersHorizontal.svg is excluded by !**/*.svg
  • src/shared/icons/source/GoogleIcon.svg is excluded by !**/*.svg
  • src/shared/icons/source/HeartStraight.svg is excluded by !**/*.svg
  • src/shared/icons/source/HouseSimple.svg is excluded by !**/*.svg
  • src/shared/icons/source/KakaoIcon.svg is excluded by !**/*.svg
  • src/shared/icons/source/MapPin.svg is excluded by !**/*.svg
  • src/shared/icons/source/MapPin_.svg is excluded by !**/*.svg
  • src/shared/icons/source/Save.svg is excluded by !**/*.svg
  • src/shared/icons/source/User.svg is excluded by !**/*.svg
  • src/shared/icons/source/backto.svg is excluded by !**/*.svg
  • src/shared/icons/source/x.svg is excluded by !**/*.svg

CodeRabbit blocks several paths by default. You can override this behavior by explicitly including those paths in the path filters. For example, including **/dist/** will override the default block on the dist directory, by removing the pattern from both the lists.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

메인 페이지 헤더를 텍스트에서 세 개의 아이콘으로 교체하고, 마이페이지용 프로필·저장된 이벤트·엽서 컨테이너 및 로그아웃 팝업을 새로 추가했습니다. 공유 컴포넌트 재내보내기가 확장되고 전역 스타일에 스크롤바 숨김 클래스가 추가되었습니다.

Changes

Cohort / File(s) 요약
메인 페이지 수정
src/pages/index.tsx
기존 상단 헤더 텍스트와 설명 문단을 제거하고 CopySimple, HeartStraight, Stamp 아이콘 컴포넌트를 렌더링하도록 변경
마이페이지 페이지
src/pages/mypage/index.tsx
마이페이지 신규 클라이언트 페이지 추가 — 프로필 영역, 저장된 이벤트 섹션, 저장된 엽서 섹션, 로그아웃 팝업 상태 로직 및 BottomNav 포함
마이페이지 컴포넌트
src/pages/mypage/components/PostcardContainer.tsx, src/pages/mypage/components/ProfilePhoto.tsx
엽서 그리드 렌더링용 PostcardContainer와 프로필 사진 표시용 ProfilePhoto 클라이언트 컴포넌트 추가
공유 컴포넌트 인덱스
src/shared/components/index.ts
LocationBubbleSet, PopupSet, LocationCard, EventCard, AddressCopy, CommonButton(default 재내보내기), BottomNav(이름 재내보내기) 추가
전역 스타일
src/styles/globals.css
.no-scrollbar 클래스 추가로 WebKit 및 크로스브라우저 스크롤바 숨김 스타일 도입
Node 컴포넌트 수정
src/pages/main/Node.tsx
AddressCopy 사용부의 복사 대상 값을 구체 주소에서 일반 플레이스홀더 '주소'로 변경 (label 사용 라인 제거/수정)

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant MyPage as MyPage 컴포넌트
    participant ProfilePhoto as ProfilePhoto
    participant PostcardContainer as PostcardContainer
    participant PopupSet as PopupSet

    User->>MyPage: 마이페이지 접속
    MyPage->>ProfilePhoto: 프로필 렌더 요청
    ProfilePhoto-->>MyPage: 이미지/플레이스홀더 반환
    MyPage->>PostcardContainer: 엽서 목록 전달
    PostcardContainer-->>MyPage: 슬롯/썸네일 렌더
    User->>MyPage: 로그아웃 버튼 클릭
    MyPage->>PopupSet: 팝업 표시 상태 변경
    PopupSet-->>MyPage: 확인/취소 결과 반환
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • 주의할 파일/영역:
    • PostcardContainer의 슬롯 채우기(filledSlots) 로직 및 스크롤/인터랙티브 클래스 처리
    • PopupSet 재내보내기와 mypage/index.tsx에서의 팝업 상태/핸들링 일관성
    • AddressCopy에 대한 Node.tsx 변경이 다른 사용처에 미치는 영향
    • src/shared/components/index.ts에 추가된 재내보내기들이 올바른 경로/이름으로 연결되었는지

Possibly related PRs

Suggested labels

feat

Suggested reviewers

  • skyblue1232
  • jjangminii

Poem

🐰 새로 온 페이지에 아이콘 반짝,
엽서 모아 담고 사진도 빛나네.
팝업 툭 열리고 스크롤은 숨겨,
깔끔히 정리된 우리 마이페이지—
당근 하나로 축하할래요 🥕🎉

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed PR 제목 "✨Feat : MyPage 작업"은 변경 사항의 주요 목표를 명확하게 반영하고 있습니다. 실제 변경 사항의 핵심은 MyPage 페이지 컴포넌트 및 관련 UI 컴포넌트(PostcardContainer, ProfilePhoto)의 추가 구현이며, 제목에서 "MyPage 작업"이라고 정확하게 명시하고 있습니다. 이모지(✨Feat)를 통해 기능 추가 특성을 표현하고 있으며, 간결하면서도 구체적입니다.
Description Check ✅ Passed PR 설명이 제공된 템플릿의 모든 필수 섹션을 포함하고 있습니다. "🔥 작업 내용"에서 세 가지 주요 구현사항을 명시하고, "🤔 추후 작업 사항"에 체크박스를 포함한 향후 계획을 기술했으며, "🔗 이슈"에서 관련 이슈를 링크했습니다. "PR Point (To Reviewer)" 섹션에서 검토자를 위한 상세한 가이드(마이페이지 폴더 및 global.css 확인 권장, 그리드 구조 설명, 스크롤바 숨김 구현 설명)를 제공하고 있으며, 마지막으로 "📸 피그마 스크린샷 or 기능 GIF"에 3개의 이미지와 1개의 비디오 등 시각적 증거를 모두 포함하고 있습니다.

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

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@github-actions github-actions bot added the comment 필요한 주석 추가 및 변경 label Oct 27, 2025
@github-actions
Copy link
Copy Markdown

🏷️ Labeler has automatically applied labels based on your PR title, branch name, or commit message.
Please verify that they are correct before merging.

@KongMezu KongMezu changed the title ✨Feat : MyPage 레이아웃 작업 ✨Feat : MyPage 작업 Oct 27, 2025
Copy link
Copy Markdown
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: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/shared/components/button/AddressCopy.tsx (1)

50-60: 키보드 접근성 부족: 클릭 가능한 div에 role/tabIndex/키 핸들러 필요

현재 마우스만 동작합니다. Space/Enter로도 복사가 가능하도록 보완해 주세요. 시멘틱 변경(버튼 태그) 대신 비침투적 수정안 제안합니다.

   return (
-    <div
-      onClick={handleCopy}
+    <div
+      role="button"
+      tabIndex={0}
+      onClick={handleCopy}
+      onKeyDown={(e) => {
+        if (e.key === 'Enter' || e.key === ' ') {
+          e.preventDefault();
+          handleCopy();
+        }
+      }}
       className={cn(
         addressCopyStyle({ variant }),
         'w-full h-[4rem] px-[1.3rem] py-[1rem] gap-[0.4rem]',
         'cursor-pointer select-none',
         className,
       )}
       {...props}
     >
🧹 Nitpick comments (5)
src/pages/mypage/index.tsx (1)

49-49: 엽서 데이터 패칭 로직을 추가하세요.

현재 빈 배열이 전달되고 있습니다. 실제 사용자가 저장한 엽서 데이터를 가져오는 로직이 필요합니다.

다음과 같은 구현이 필요합니다:

const [savedPostcards, setSavedPostcards] = useState<string[]>([]);

useEffect(() => {
  // TODO: 저장한 엽서 목록 API 호출
}, []);

// JSX에서
<PostcardContainer postcards={savedPostcards} />

이 기능 구현을 위한 이슈를 생성해드릴까요?

src/pages/mypage/components/PostcardContainer.tsx (3)

24-31: bordered=false 처리 시 border-none 대신 border-0 권장

베이스 클래스에 border border-pink-200가 있어 border-none만으로는 width가 남을 수 있습니다. border-0가 보다 명시적입니다.

-      bordered: {
-        false: 'border-none',
-      },
+      bordered: {
+        false: 'border-0',
+      },

86-95: 폼 내부 포함 시 의도치 않은 submit 방지

button 기본 type은 submit입니다. 안전하게 type="button"을 지정해 주세요.

-        <button
+        <button
+          type="button"
           key={idx}
           onClick={() => src && onClickCard?.(idx)}

7-12: postcards를 선택 프로퍼티로 전환하면 사용성이 좋아집니다

런타임 기본값을 이미 []로 처리하고 있어 타입도 선택으로 맞추는 편이 자연스럽습니다.

-interface PostcardContainerProps {
-  postcards: string[];
+interface PostcardContainerProps {
+  postcards?: string[];
src/shared/components/button/AddressCopy.tsx (1)

61-79: 복사 상태를 스크린리더에 알려주세요

copied 변화가 시각적으로만 표시됩니다. aria-live로 비가시 메시지를 추가하면 접근성이 좋아집니다.

       <div className='flex-shrink-0'>
         <Icon
           name={copied ? 'Check' : 'CopySimple'}
           size={18}
           color={variant === 'mint' ? 'mint-400' : 'gray-400'}
         />
       </div>
+      {/* SR 전용 상태 알림 */}
+      <span className="sr-only" aria-live="polite" aria-atomic="true">
+        {copied ? '복사됨' : ''}
+      </span>
       <span
         className={cn(
           'text-label-lg flex-1 min-w-0',
           variant === 'mint' ? 'text-mint-400' : 'text-gray-400',
           truncate &&
             'truncate whitespace-nowrap overflow-hidden text-ellipsis',
         )}
         title={value}
       >
         {value}
       </span>
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 07d6602 and daba470.

⛔ Files ignored due to path filters (17)
  • src/shared/icons/source/CalendarBlank.svg is excluded by !**/*.svg
  • src/shared/icons/source/Caret.svg is excluded by !**/*.svg
  • src/shared/icons/source/ChatCircle.svg is excluded by !**/*.svg
  • src/shared/icons/source/Check.svg is excluded by !**/*.svg
  • src/shared/icons/source/CopySimple.svg is excluded by !**/*.svg
  • src/shared/icons/source/Export.svg is excluded by !**/*.svg
  • src/shared/icons/source/FadersHorizontal.svg is excluded by !**/*.svg
  • src/shared/icons/source/GoogleIcon.svg is excluded by !**/*.svg
  • src/shared/icons/source/HeartStraight.svg is excluded by !**/*.svg
  • src/shared/icons/source/HouseSimple.svg is excluded by !**/*.svg
  • src/shared/icons/source/KakaoIcon.svg is excluded by !**/*.svg
  • src/shared/icons/source/MapPin.svg is excluded by !**/*.svg
  • src/shared/icons/source/MapPin_.svg is excluded by !**/*.svg
  • src/shared/icons/source/Save.svg is excluded by !**/*.svg
  • src/shared/icons/source/User.svg is excluded by !**/*.svg
  • src/shared/icons/source/backto.svg is excluded by !**/*.svg
  • src/shared/icons/source/x.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • src/pages/auth/index.tsx (4 hunks)
  • src/pages/index.tsx (1 hunks)
  • src/pages/mypage/components/PostcardContainer.tsx (1 hunks)
  • src/pages/mypage/components/ProfilePhoto.tsx (1 hunks)
  • src/pages/mypage/index.tsx (1 hunks)
  • src/shared/components/button/AddressCopy.tsx (3 hunks)
  • src/shared/components/container/Card.tsx (1 hunks)
  • src/shared/components/index.ts (1 hunks)
  • src/shared/icons/components/icon.tsx (3 hunks)
  • src/styles/globals.css (1 hunks)
  • svgo.config.mjs (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (6)
src/shared/components/button/AddressCopy.tsx (1)
src/shared/lib/utils.ts (1)
  • cn (71-73)
src/pages/mypage/index.tsx (4)
src/pages/mypage/components/ProfilePhoto.tsx (1)
  • ProfilePhoto (11-35)
src/pages/mypage/components/PostcardContainer.tsx (1)
  • PostcardContainer (59-111)
src/shared/components/tab/BottomNav.tsx (1)
  • BottomNav (21-54)
src/shared/components/set/PopupSet.tsx (1)
  • PopupSet (11-35)
src/pages/index.tsx (1)
src/shared/icons/components/icon.tsx (1)
  • Icon (55-110)
src/pages/auth/index.tsx (1)
src/pages/auth/components/LoginButton.tsx (1)
  • LoginButton (33-67)
src/pages/mypage/components/ProfilePhoto.tsx (1)
src/shared/lib/utils.ts (1)
  • cn (71-73)
src/pages/mypage/components/PostcardContainer.tsx (1)
src/shared/lib/utils.ts (1)
  • cn (71-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (11)
src/styles/globals.css (1)

222-223: LGTM!

스크롤바 숨김 유틸리티 클래스가 잘 구현되었습니다. 크로스 브라우저 지원도 적절합니다.

svgo.config.mjs (1)

1-7: LGTM!

SVG 속성 자동 조작 플러그인 제거로 Icon 컴포넌트에서 fillColor prop을 통한 명시적 제어가 가능해졌습니다. 이는 더 예측 가능한 동작을 제공합니다.

src/pages/auth/index.tsx (1)

72-104: LGTM!

최근 사용한 로그인 플랫폼을 추적하고 시각적으로 표시하는 기능이 잘 구현되었습니다. 각 버튼마다 독립적으로 RecentLoginBubble을 조건부 렌더링하는 구조가 깔끔합니다.

src/shared/icons/components/icon.tsx (3)

48-48: LGTM!

fillColor prop 추가로 아이콘의 채우기 색상을 독립적으로 제어할 수 있게 되었습니다. 기존 color prop(stroke용)과 함께 사용하여 더 세밀한 스타일링이 가능합니다.


89-94: LGTM!

CSS 변수를 활용한 스타일링 접근 방식이 우수합니다. colorfillColor를 CSS 변수로 변환하여 SVG 내부에서 참조할 수 있도록 했으며, 기존 style prop과도 잘 병합됩니다.


97-98: LGTM!

조건부 fill/stroke 속성 처리가 적절합니다:

  • fillColor가 제공되면 CSS 변수 참조, 아니면 'none'
  • color가 제공되면 'currentColor', 아니면 'none'

이를 통해 명시적이고 예측 가능한 동작이 보장됩니다.

src/pages/mypage/index.tsx (1)

8-12: 로그아웃 로직을 구현하세요.

현재 팝업만 표시되고 실제 로그아웃 처리가 없습니다. 팝업의 확인 버튼 클릭 시 다음 작업이 필요합니다:

  • 인증 토큰 제거
  • 사용자 상태 초기화
  • 로그인 페이지로 리다이렉트
const handleConfirmLogout = async () => {
  // TODO: 로그아웃 API 호출
  // TODO: 로컬 스토리지/쿠키에서 토큰 제거
  // TODO: /auth로 리다이렉트
  router.push('/auth');
};
src/shared/components/container/Card.tsx (1)

14-16: 검증 불완전 - 코드베이스에서 제한된 정보만 확인됨

현재 Card.tsx의 코드는 이미 w-full이 적용된 상태입니다. 다만 다음 이유로 영향 검증이 불충분합니다:

  • 사용처 제한: EventCard는 mypage에서만 발견되었고, LocationCard는 실제 사용 사례를 찾을 수 없습니다.
  • 단일 컨텍스트: 발견된 EventCard 사용처가 하나뿐이므로, 다양한 레이아웃 시나리오에서의 동작을 확인할 수 없습니다.
  • 기존 상태 미확인: 고정 너비(w-[17rem], w-[35.4rem])로부터의 변경 전 상태를 현재 코드에서 확인할 수 없습니다.

개발자의 수동 검증이 필요합니다. 변경사항이 다양한 화면 크기와 부모 컨테이너에서 의도대로 동작하는지 확인하고, 모바일/태블릿/데스크톱 환경에서 카드 레이아웃이 정상인지 테스트해주세요.

src/shared/components/index.ts (2)

11-11: 검증 완료: 현재 코드가 정상입니다

BottomNav는 named export(export const BottomNav = () => { ... })로 정의되어 있으므로, 현재의 재‑export 방식이 올바릅니다.

export { BottomNav } from './tab/BottomNav';

제안된 수정(export { default as BottomNav })은 불필요하며, 현재 코드는 변경할 사항이 없습니다.


5-10: 순환 의존성 검증 완료 - 문제 없음

검증 결과, 내보낸 컴포넌트들이 @/shared/components 바렐(index.ts)을 다시 import하지 않습니다. 모든 내부 import는 다음과 같이 특정 서브모듈을 지정합니다:

  • PopupSet.tsx: @/shared/components/container/Popup
  • LocationBubbleSet.tsx: @/shared/components/container/LocationBubble
  • LocationCard.tsx, EventCard.tsx: @/shared/components/container/Card

순환 의존성이 없으므로 바렐 export 추가는 안전합니다.

src/shared/components/button/AddressCopy.tsx (1)

23-28: 검증 완료: 리뷰 의견이 코드베이스와 일치하지 않음

검증 결과, 다음을 확인했습니다:

  • AddressCopy 컴포넌트는 코드베이스 전체에서 사용되지 않음 (호출 사이트 0개)
  • 현재 인터페이스에 label prop이 존재하지 않음 (이미 제거되었거나 처음부터 없었음)
  • 마이그레이션이 필요한 기존 호출부 없음

리뷰 의견의 우려사항(기존 호출부 파괴 가능성)은 적용되지 않습니다.

Likely an incorrect or invalid review comment.

Comment on lines +11 to +15
const handleLoginClick = (platform: string) => {
alert(`${platform} 로그인 준비중`);
console.log(`${platform} 로그인 버튼 클릭`);
setRecentPlatform(platform);
};
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

프로덕션 코드에서 alertconsole.log를 제거하세요.

개발/테스트용 코드가 포함되어 있습니다:

  • Line 12: alert()는 사용자 경험을 해치며 프로덕션에 적합하지 않습니다.
  • Line 13: console.log()는 배포 전에 제거되어야 합니다.

다음과 같이 수정하세요:

  const handleLoginClick = (platform: string) => {
-   alert(`${platform} 로그인 준비중`);
-   console.log(`${platform} 로그인 버튼 클릭`);
+   // TODO: 실제 로그인 로직 구현
    setRecentPlatform(platform);
  };
📝 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
const handleLoginClick = (platform: string) => {
alert(`${platform} 로그인 준비중`);
console.log(`${platform} 로그인 버튼 클릭`);
setRecentPlatform(platform);
};
const handleLoginClick = (platform: string) => {
// TODO: 실제 로그인 로직 구현
setRecentPlatform(platform);
};
🤖 Prompt for AI Agents
In src/pages/auth/index.tsx around lines 11 to 15, remove the development-only
alert() and console.log() calls from handleLoginClick; preserve the
setRecentPlatform(platform) call and, if user feedback is required in
production, replace alert() with a proper non-blocking UI notification/toast and
send console logs to a telemetry/logger utility instead of using console.log().

Comment on lines +8 to +25
<Icon
name='CopySimple'
size={24}
color='mint-500'
fillColor='mint-200'
/>
<Icon
name='HeartStraight'
size={24}
color='red-300'
fillColor='red-400'
/>

<Icon
name='Stamp'
size={24}
color='pink-100'
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

프로덕션 코드가 아닌 테스트 코드가 포함되어 있습니다.

홈페이지의 실제 콘텐츠가 Icon 컴포넌트 테스트용 코드로 교체되었습니다. 이는 새로운 fillColor 기능을 테스트하기 위한 임시 코드로 보이며, 실제 배포 전에 원래 콘텐츠로 복원되어야 합니다.

다음과 같이 수정하세요:

  • 원래 홈페이지 콘텐츠로 복원
  • 또는 Icon 컴포넌트 테스트가 목적이라면 별도의 테스트 페이지나 Storybook으로 이동
🤖 Prompt for AI Agents
In src/pages/index.tsx around lines 8 to 25, the homepage content has been
replaced with Icon component test snippets; restore the original production
homepage markup (or remove these test Icons) so end users don't see test code,
or if testing the new fillColor behavior is required move these Icon examples to
a dedicated test page or Storybook story and remove them from this file before
merging.

Comment on lines +96 to +104
{src && (
<Image
src={src}
alt={`엽서 ${idx + 1}`}
width={200}
height={200}
className="w-full h-full object-cover"
/>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

원격 이미지 도메인 허용 여부 확인

Next/Image 사용 시 next.config.(js|ts)images.domains 또는 remotePatterns에 엽서 이미지 도메인이 등록되어 있어야 합니다. 누락 시 빌드/런타임 에러가 납니다.


🏁 Script executed:

#!/bin/bash
# next.config 파일에서 이미지 설정 확인
fd -a 'next.config.*' | xargs -I{} sh -c "echo '--- {} ---'; cat {}"
rg -nP "images\s*:\s*\{|\bdomains\b|\bremotePatterns\b" -n --glob 'next.config.*'

Length of output: 856


next.config.ts에 원격 이미지 도메인 설정 필요

현재 next.config.tsimages.domains 또는 remotePatterns 설정이 없습니다. PostcardContainer.tsx의 Next/Image 컴포넌트가 원격 이미지를 로드할 때 에러가 발생합니다. 사용 중인 이미지 도메인을 next.config.tsimages 설정에 추가하세요.

const nextConfig: NextConfig = {
  images: {
    domains: ['your-image-domain.com'], // 또는 remotePatterns 사용
  },
  // ... 기타 설정
};
🤖 Prompt for AI Agents
In src/pages/mypage/components/PostcardContainer.tsx around lines 96 to 104 the
Next/Image component may load remote images and currently Next.js config lacks
allowed remote image domains, causing runtime errors; open your project's
next.config.ts and add the image host(s) you use under the images key (either as
domains array or remotePatterns) so Next/Image can fetch them, then restart the
dev server to apply the changes.

return (
<div className={cn(baseStyle, className)}>
{src ? (
<img src={src} className='w-full h-full object-cover' />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Next.js Image 컴포넌트를 사용하고 접근성을 개선하세요.

현재 구현의 문제점:

  1. 네이티브 <img> 태그 사용으로 Next.js의 이미지 최적화 혜택(자동 리사이징, 포맷 변환, 지연 로딩 등)을 받지 못합니다.
  2. alt 속성이 누락되어 접근성 기준(WCAG)을 충족하지 못합니다.

다음과 같이 수정하세요:

+'use client';
+
+import Image from 'next/image';
 import { Icon } from '@/shared/icons';
 import { cn } from '@/shared/lib';
 
 // ... interface ...

 export default function ProfilePhoto({
   src,
   className,
 }: ProfilePhotoProps) {
   // ... baseStyle ...

   return (
     <div className={cn(baseStyle, className)}>
       {src ? (
-        <img src={src} className='w-full h-full object-cover' />
+        <Image 
+          src={src} 
+          alt="프로필 사진"
+          width={146}
+          height={146}
+          className='w-full h-full object-cover'
+          priority
+        />
       ) : (
         <div className='p-[6.1rem] flex items-center justify-center'>
           <Icon name='User' size={24} color='gray-500' />
         </div>
       )}
     </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.

Suggested change
<img src={src} className='w-full h-full object-cover' />
'use client';
import Image from 'next/image';
import { Icon } from '@/shared/icons';
import { cn } from '@/shared/lib';
// ... interface ...
export default function ProfilePhoto({
src,
className,
}: ProfilePhotoProps) {
// ... baseStyle ...
return (
<div className={cn(baseStyle, className)}>
{src ? (
<Image
src={src}
alt="프로필 사진"
width={146}
height={146}
className='w-full h-full object-cover'
priority
/>
) : (
<div className='p-[6.1rem] flex items-center justify-center'>
<Icon name='User' size={24} color='gray-500' />
</div>
)}
</div>
);
}
🤖 Prompt for AI Agents
In src/pages/mypage/components/ProfilePhoto.tsx around line 27, replace the
native <img> with Next.js' Image component and add an appropriate alt attribute
to satisfy accessibility: import Image from 'next/image' at the top, swap the
<img src={src} className='w-full h-full object-cover' /> for <Image> using
either width/height or layout='fill' (with parent position:relative) to preserve
sizing and object-fit behavior, pass alt (use a descriptive string or alt="" if
purely decorative), keep any needed className or style for object-cover, and
ensure loading behavior (lazy/priority) is set according to importance.

Comment on lines +14 to +72
return (
<main className='w-full min-h-screen bg-white flex flex-col items-center'>
<div className='w-full flex flex-col items-center px-[2.3rem] pb-[2rem]'>
{/* 프로필 */}
<section className='w-full flex flex-col items-center mt-[2.4rem] gap-[1.0rem]'>
<ProfilePhoto/>
<p className='text-title-md'>이름</p>
</section>

{/* 저장한 행사 */}
<section className='w-full mt-[1.6rem]'>
<p className='text-label-lg mb-[1rem] pl-[1rem]'>저장한 행사</p>
<div className='max-h-[18rem] overflow-y-auto no-scrollbar space-y-[1rem]'>
<EventCard
name='골반 통신 이상 감지'
address='우리집'
description='내 골반이 멈추지 않아서 일까?'
variant='gray'
size='large'
imageSrc=''
/>
<EventCard
name='이혼 숙려 캠프'
address='우리집'
description='앙 이라는 감정'
variant='gray'
size='large'
imageSrc=''
/>
</div>
</section>

{/* 저장한 엽서 */}
<section className='w-full mt-[1.8rem]'>
<p className='text-label-lg mb-[0.6rem] pl-[1rem]'>저장한 엽서</p>
<PostcardContainer postcards={[]} />
</section>

{/* 로그아웃 */}
<button
type='button'
onClick={handleLogout}
className='mt-[2.1em] text-label-md text-gray-400 cursor-pointer underline underline-offset-[0.25rem]'
>
로그아웃
</button>
</div>
<BottomNav />

{showLogoutPopup && (
<PopupSet
text="로그아웃 하시겠습니까?"
onClose={() => {
setShowLogoutPopup(false);
}}
/>
)}
</main>
);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

로딩 및 에러 상태 처리를 추가하세요.

현재 구현에는 다음이 누락되어 있습니다:

  • 데이터 로딩 중 표시할 스켈레톤 UI
  • API 에러 발생 시 에러 메시지 표시
  • 네트워크 실패 시 재시도 로직

기본적인 로딩 상태 처리 예시:

if (isLoading) {
  return <LoadingSkeleton />;
}

if (error) {
  return <ErrorMessage message={error.message} onRetry={refetch} />;
}

Comment on lines +27 to +42
<EventCard
name='골반 통신 이상 감지'
address='우리집'
description='내 골반이 멈추지 않아서 일까?'
variant='gray'
size='large'
imageSrc=''
/>
<EventCard
name='이혼 숙려 캠프'
address='우리집'
description='앙 이라는 감정'
variant='gray'
size='large'
imageSrc=''
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

테스트 데이터를 실제 데이터 패칭으로 교체하세요.

하드코딩된 테스트 데이터("골반 통신 이상 감지", "이혼 숙려 캠프")가 포함되어 있습니다. 실제 배포 전에 API 연동 및 데이터 패칭 로직으로 교체되어야 합니다.

실제 이벤트 데이터 패칭 구현 예시:

const [savedEvents, setSavedEvents] = useState<Event[]>([]);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  // TODO: API 호출로 저장한 이벤트 목록 가져오기
  fetchSavedEvents()
    .then(setSavedEvents)
    .finally(() => setIsLoading(false));
}, []);

🏁 Script executed:

#!/bin/bash
# Examine the target file and lines
if [ -f "src/pages/mypage/index.tsx" ]; then
  echo "=== File found: src/pages/mypage/index.tsx ==="
  echo "=== Lines 1-50 (including target lines 27-42) ==="
  head -n 50 "src/pages/mypage/index.tsx"
else
  echo "File not found at src/pages/mypage/index.tsx"
  find . -name "index.tsx" -path "*/mypage/*" 2>/dev/null | head -20
fi

Length of output: 1822


🏁 Script executed:

#!/bin/bash
# Check for common API/data fetching patterns
if [ -d "src" ]; then
  echo "=== Searching for API integration patterns ==="
  rg -n "fetch|axios|useEffect|API|api" src/pages/mypage/ 2>/dev/null || echo "No results found"
else
  echo "src directory not found"
fi

Length of output: 63


🏁 Script executed:

#!/bin/bash
# Search for EventCard component definition and usage
echo "=== Searching for EventCard component ==="
rg -n "EventCard" -A 5 -B 2 --type tsx 2>/dev/null | head -50

Length of output: 41


🏁 Script executed:

#!/bin/bash
# Check file structure around the target area
if [ -f "src/pages/mypage/index.tsx" ]; then
  echo "=== Context around lines 20-50 ==="
  sed -n '20,50p' "src/pages/mypage/index.tsx"
fi

Length of output: 1017


저장한 행사 데이터를 API 연동으로 교체하세요.

파일 src/pages/mypage/index.tsx 27-42줄에 하드코딩된 테스트 데이터가 포함되어 있습니다. 현재 상태로는 배포 불가능하며, 실제 저장된 행사 데이터를 서버에서 가져오는 로직으로 반드시 교체되어야 합니다. 추가로 PostcardContainer도 빈 배열을 받고 있으므로 함께 수정이 필요합니다.

Copy link
Copy Markdown
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: 3

♻️ Duplicate comments (2)
src/pages/mypage/index.tsx (2)

27-42: 저장한 행사 데이터를 API 연동으로 교체하세요.

이전 리뷰에서 지적된 것과 동일하게, 하드코딩된 테스트 데이터("골반 통신 이상 감지", "이혼 숙려 캠프")가 그대로 남아있습니다. 배포 전 반드시 실제 API에서 저장된 행사 목록을 가져오는 로직으로 교체되어야 합니다.


14-72: 로딩 및 에러 상태 처리를 추가하세요.

이전 리뷰에서 지적된 것과 동일하게, 데이터 로딩 중 스켈레톤 UI, API 에러 발생 시 에러 메시지 표시, 네트워크 실패 시 재시도 로직이 여전히 누락되어 있습니다. 프로덕션 배포를 위해서는 이러한 상태 처리가 필수적입니다.

기본 구현 예시:

if (isLoading) {
  return <LoadingSkeleton />;
}

if (error) {
  return <ErrorMessage message={error.message} onRetry={refetch} />;
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between daba470 and 305da77.

📒 Files selected for processing (1)
  • src/pages/mypage/index.tsx (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/mypage/index.tsx (4)
src/pages/mypage/components/ProfilePhoto.tsx (1)
  • ProfilePhoto (11-35)
src/pages/mypage/components/PostcardContainer.tsx (1)
  • PostcardContainer (59-111)
src/shared/components/tab/BottomNav.tsx (1)
  • BottomNav (21-54)
src/shared/components/set/PopupSet.tsx (1)
  • PopupSet (11-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build-and-deploy
🔇 Additional comments (2)
src/pages/mypage/index.tsx (2)

1-6: 'use client' 지시어와 임포트가 올바르게 설정되었습니다.

클라이언트 상태 관리(useState)를 사용하므로 'use client' 지시어가 적절하며, 모든 필요한 컴포넌트가 정확하게 임포트되었습니다.


8-12: 상태 관리가 깔끔하고 적절합니다.

로그아웃 팝업 표시를 위한 상태 관리가 명확하고 간결하게 구현되었습니다.

Comment on lines +18 to +21
<section className='w-full flex flex-col items-center mt-[2.4rem] gap-[1.0rem]'>
<ProfilePhoto/>
<p className='text-title-md'>이름</p>
</section>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

사용자 프로필 데이터를 API 연동으로 교체하세요.

현재 사용자 이름이 "이름"으로 하드코딩되어 있고, ProfilePhoto에 실제 이미지 경로가 전달되지 않습니다. 사용자 정보를 가져오는 API 연동이 필요합니다.

구현 예시:

const [userData, setUserData] = useState({ name: '', profileImage: '' });
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  fetchUserProfile()
    .then(setUserData)
    .finally(() => setIsLoading(false));
}, []);

// 렌더링:
<ProfilePhoto src={userData.profileImage} />
<p className='text-title-md'>{userData.name}</p>
🤖 Prompt for AI Agents
In src/pages/mypage/index.tsx around lines 18 to 21, the user name is hardcoded
as "이름" and ProfilePhoto is not receiving an image path; replace this with
API-backed user data by adding useState for userData ({ name: '', profileImage:
''}) and loading state, call your fetchUserProfile (or equivalent) inside
useEffect to populate userData (handle errors and set loading false), then
render <ProfilePhoto src={userData.profileImage} /> and <p
className='text-title-md'>{userData.name}</p>, showing a loader or placeholder
while loading or when image/name are absent.

Comment on lines +47 to +50
<section className='w-full mt-[1.8rem]'>
<p className='text-label-lg mb-[0.6rem] pl-[1rem]'>저장한 엽서</p>
<PostcardContainer postcards={[]} />
</section>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

저장한 엽서 데이터를 API 연동으로 교체하세요.

PostcardContainer에 빈 배열이 전달되고 있습니다. 사용자가 저장한 엽서 목록을 API에서 가져오는 로직을 구현해야 합니다.

구현 예시:

const [postcards, setPostcards] = useState<string[]>([]);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
  fetchSavedPostcards()
    .then(setPostcards)
    .finally(() => setIsLoading(false));
}, []);

// 렌더링:
<PostcardContainer postcards={postcards} />

Comment on lines +63 to +70
{showLogoutPopup && (
<PopupSet
text="로그아웃 하시겠습니까?"
onClose={() => {
setShowLogoutPopup(false);
}}
/>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

로그아웃 확인 후 실제 로그아웃 로직을 추가하세요.

현재 로그아웃 팝업이 표시되지만, 사용자가 확인을 클릭해도 실제 로그아웃 처리(토큰 제거, 세션 종료, 리다이렉트 등)가 수행되지 않습니다. PopupSet 컴포넌트에 확인 액션 핸들러를 추가하거나, 별도의 로그아웃 로직을 구현해야 합니다.

구현 예시:

const handleConfirmLogout = async () => {
  try {
    await logout(); // API 호출
    // 토큰 제거, 상태 초기화 등
    router.push('/login');
  } catch (error) {
    console.error('로그아웃 실패:', error);
  }
  setShowLogoutPopup(false);
};

// PopupSet에 onConfirm prop이 있다면:
<PopupSet
  text="로그아웃 하시겠습니까?"
  onConfirm={handleConfirmLogout}
  onClose={() => setShowLogoutPopup(false)}
/>
🤖 Prompt for AI Agents
In src/pages/mypage/index.tsx around lines 63 to 70, the logout confirmation
popup is shown but no actual logout logic runs when the user confirms; add an
onConfirm handler to PopupSet that calls the logout flow (await logout API call
if applicable), clears auth tokens/storage, resets any user state,
navigates/redirects to the login (or home) page via the router, handles errors
(log or show a message), and finally closes the popup by setting
setShowLogoutPopup(false); wire the onConfirm prop into the existing PopupSet
invocation and keep the current onClose to just dismiss the dialog.

@KongMezu KongMezu linked an issue Oct 27, 2025 that may be closed by this pull request
1 task
jjangminii
jjangminii previously approved these changes Oct 28, 2025
Copy link
Copy Markdown
Contributor

@jjangminii jjangminii left a comment

Choose a reason for hiding this comment

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

수고하셨습니다-! 따로 좋은 수정 방안 있을거같아 하나 남겨놨어요 확인해주세요-!

Comment on lines +79 to +86
{recentPlatform === '카카오' && (
<div
className='absolute -top-[3.8rem] left-1/2 -translate-x-1/2
w-auto min-w-max h-auto flex-shrink-0 pointer-events-none'
>
<RecentLoginBubble />
</div>
)}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이 부분이 반복되고 있는거 같아요 혹시 따로 컴포넌트로 분리하거나, 플랫폼 리스트를 배열로 선언 후 map으로 돌리는 방법은 어떤가요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

미처 생각 못했네요.. 너무 좋은 방법인 거 같습니다! 이 부분은 로그인 페이지 브랜치에서 수정해보도록 하겠습니다!

Comment on lines +27 to +42
<EventCard
name='골반 통신 이상 감지'
address='우리집'
description='내 골반이 멈추지 않아서 일까?'
variant='gray'
size='large'
imageSrc=''
/>
<EventCard
name='이혼 숙려 캠프'
address='우리집'
description='앙 이라는 감정'
variant='gray'
size='large'
imageSrc=''
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

이거 뭐에요 ㅋㅎㅋㅎㅋㅎㅋㅋ

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

웃고 가세요 :)

Comment on lines +5 to +11
export { default as LocationBubbleSet } from './set/LocationBubbleSet';
export { default as PopupSet } from './set/PopupSet';
export { default as LocationCard } from './container/LocationCard';
export { default as EventCard } from './container/EventCard';
export { default as AddressCopy } from './button/AddressCopy';
export { default as CommonButton } from './button/CommonButton';
export { BottomNav } from './tab/BottomNav';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

viewBox="0 0 24 24"
className={combined}
style={{ ...(color && { color: `var(--color-${color})` }), ...style }}
style={iconStyle}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

여기 코드 svg pr에 올라온 부분이랑 중복된거같아요

Comment on lines +222 to +223
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; } No newline at end of file
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

저희 스크롤바는 따로 안보이게 하는건가요?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

피그마 디자인 상에 기능적으로 스크롤이 들어가야하는 부분은 있지만, 따로 스크롤바는 보이지 않아
일단은 보이지 않도로고 해놓긴 했습니다!

@KongMezu KongMezu dismissed jjangminii’s stale review October 28, 2025 16:52

The merge-base changed after approval.

Copy link
Copy Markdown
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: 0

🧹 Nitpick comments (1)
src/shared/components/button/AddressCopy.tsx (1)

68-78: 텍스트 렌더링이 잘 구현되었으나 클래스 중복이 있습니다.

flex-1 min-w-0title 속성을 통한 접근성 향상은 잘 되어 있습니다. 다만 Lines 72-73의 조건부 클래스에서 Tailwind의 truncate 유틸리티가 이미 overflow-hidden, text-overflow: ellipsis, white-space: nowrap를 포함하고 있어 중복입니다.

다음과 같이 단순화할 수 있습니다:

         className={cn(
           'text-label-lg flex-1 min-w-0',
           variant === 'mint' ? 'text-mint-400' : 'text-gray-400',
-          truncate &&
-            'truncate whitespace-nowrap overflow-hidden text-ellipsis',
+          truncate && 'truncate',
         )}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 593e0e5 and 7d5c023.

📒 Files selected for processing (1)
  • src/shared/components/button/AddressCopy.tsx (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/shared/components/button/AddressCopy.tsx (2)
src/shared/utils/copy.ts (1)
  • Copy (1-12)
src/shared/lib/utils.ts (1)
  • cn (71-73)
🔇 Additional comments (4)
src/shared/components/button/AddressCopy.tsx (4)

8-21: 베이스 스타일 정의가 잘 되어 있습니다.

overflow-hidden 추가로 컨테이너 내에서 콘텐츠가 넘치는 것을 방지하고, rounded-full과 함께 깔끔한 UI를 유지합니다.


23-28: 인터페이스 변경이 적절합니다.

truncate prop 추가로 텍스트 말줄임 표시를 선택적으로 제어할 수 있어 컴포넌트 유연성이 향상되었습니다.


30-48: Props 및 핸들러 로직이 올바릅니다.

label을 복사 값으로 사용하고, truncate 기본값이 true로 설정되어 일관성 있는 동작을 제공합니다. 복사 성공 시 1.5초 동안 피드백을 표시하는 것도 좋은 UX입니다.


61-67: 아이콘 렌더링이 적절합니다.

복사 상태에 따라 아이콘이 전환되어(CheckCopySimple) 사용자에게 명확한 피드백을 제공합니다. flex-shrink-0 래퍼로 아이콘 크기가 보존됩니다.

Copy link
Copy Markdown
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: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/pages/main/Node.tsx (1)

2-2: 배럴 파일에서 import하도록 변경하세요.

AddressCopy를 직접 경로에서 import하고 있지만, PR에서 공유 컴포넌트용 배럴 파일을 추가했으므로 일관성을 위해 다른 컴포넌트(Header)처럼 배럴 파일에서 import해야 합니다.

다음 diff를 적용하세요:

 import { Header } from '@/shared/components';
-import AddressCopy from '@/shared/components/button/AddressCopy';
+import { AddressCopy } from '@/shared/components';
 import LocationCard from '@/shared/components/container/LocationCard';
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7d5c023 and 03a6115.

📒 Files selected for processing (1)
  • src/pages/main/Node.tsx (1 hunks)
🧰 Additional context used
🪛 GitHub Actions: Next.js CI/CD with Vercel
src/pages/main/Node.tsx

[error] 64-64: Type '{ variant: "mint"; value: string; label: string; }' is not assignable to type 'IntrinsicAttributes & AddressCopyProps'. Property 'label' does not exist on type 'IntrinsicAttributes & AddressCopyProps'.

Comment on lines 61 to 64
<AddressCopy
variant='mint'
value='인천광역시 계양구 오조산로 31길(복사되어야할 주소)'
label={label ? String(label) : '노드'}
value='(복사되어야할 주소)'
/>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

하드코딩된 플레이스홀더를 실제 주소 데이터로 교체하세요.

value prop에 플레이스홀더 문자열 "(복사되어야할 주소)"가 하드코딩되어 있습니다. 사용자가 이 버튼을 클릭하면 의미 없는 플레이스홀더 텍스트가 클립보드에 복사되어 잘못된 사용자 경험을 제공합니다.

Line 55의 LocationCard와 마찬가지로 실제 주소 데이터(API 응답, 라우터 쿼리 등)를 사용하도록 구현하거나, 데이터가 준비될 때까지 이 컴포넌트를 조건부로 렌더링하세요.

예시:

 <AddressCopy
   variant='mint'
-  value='(복사되어야할 주소)'
+  value={actualAddress || '주소 정보를 불러올 수 없습니다'}
 />

Committable suggestion skipped: line range outside the PR's diff.

🧰 Tools
🪛 GitHub Actions: Next.js CI/CD with Vercel

[error] 64-64: Type '{ variant: "mint"; value: string; label: string; }' is not assignable to type 'IntrinsicAttributes & AddressCopyProps'. Property 'label' does not exist on type 'IntrinsicAttributes & AddressCopyProps'.

🤖 Prompt for AI Agents
In src/pages/main/Node.tsx around lines 61 to 64, the AddressCopy component is
using a hardcoded placeholder "(복사되어야할 주소)"; replace that hardcoded string with
the actual address variable (e.g., from props, component state populated by the
API response, or router query) and ensure the component only renders or is
enabled once the address is available—either conditionally render AddressCopy
(matching the approach used for LocationCard at line 55) or pass a safe
fallback/disabled state until the real address is loaded.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comment 필요한 주석 추가 및 변경 style 코드 스타일 변경(기능 변경 없음)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] 마이페이지 제작

2 participants