Skip to content

Feat(client, landing): 이용약관, 개인정보 처리방침 뷰 구현 및 footer 링크 반영#233

Merged
constantly-dev merged 12 commits intodevelopfrom
feat/#230/information-policy-view
Jan 7, 2026
Merged

Feat(client, landing): 이용약관, 개인정보 처리방침 뷰 구현 및 footer 링크 반영#233
constantly-dev merged 12 commits intodevelopfrom
feat/#230/information-policy-view

Conversation

@constantly-dev
Copy link
Member

@constantly-dev constantly-dev commented Jan 6, 2026

📌 Related Issues

관련된 Issue를 태그해주세요. (e.g. - close #25)

📄 Tasks

  • 이용약관, 개인정보 처리방침 뷰 구현
  • footer 링크 반영

⭐ PR Point (To Reviewer)

이용약관이랑 개인정보 처리방침 뷰 구현했습니다. 그리고 기존 노션으로 되어있던 footer link를 해당 뷰로 router 처리하도록 수정하였습니다.

📷 Screenshot

Summary by CodeRabbit

  • 새로운 기능

    • 개인정보처리방침 및 이용약관 페이지 추가
    • 북마크 및 리마인드 페이지에 푸터 컴포넌트 추가
  • 개선 사항

    • 사이드바가 온보딩·로그인뿐 아니라 정책 페이지에서도 자동으로 숨김
    • 법적 링크를 외부 탭에서 앱 내 네비게이션으로 전환
    • 랜딩 푸터의 법적 링크 대상 도메인 일괄 업데이트
    • 로그인·소셜 로그인 화면의 법적 링크 경로 통일

✏️ Tip: You can customize this high-level summary in your review settings.

@vercel
Copy link

vercel bot commented Jan 6, 2026

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

Project Deployment Review Updated (UTC)
pinback-client-client Ready Ready Preview, Comment Jan 7, 2026 0:30am
pinback-client-landing Ready Ready Preview, Comment Jan 7, 2026 0:30am

@github-actions github-actions bot added the feat 기능 개발하라 개발 달려라 달려 label Jan 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2026

Warning

Rate limit exceeded

@constantly-dev has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 0 minutes and 3 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between f1ecd8a and 9008384.

📒 Files selected for processing (2)
  • apps/client/src/layout/Layout.tsx
  • apps/client/src/pages/policy/TermsOfService.tsx

Walkthrough

이 PR은 이용약관·개인정보처리방침 정적 페이지를 추가하고 여러 클라이언트 페이지에 Footer를 통합하며, ROUTES_CONFIG·라우터를 업데이트하고 Layout의 사이드바 숨김 로직을 isSidebarHidden로 중앙화해 정책·로그인·온보딩 페이지에서 사이드바를 숨기도록 변경합니다.

Changes

Cohort / File(s) 변경 요약
레이아웃 및 사이드바 가시성
apps/client/src/layout/Layout.tsx
사이드바 표시 로직을 isSidebarHidden 플래그로 통합; ROUTES_CONFIG 기반 정책 페이지 판별 추가(온보딩/로그인/정책에서 사이드바 숨김).
정책 페이지 추가
apps/client/src/pages/policy/PrivacyPolicy.tsx, apps/client/src/pages/policy/TermsOfService.tsx
개인정보처리방침 및 이용약관 정적 JSX 뷰 추가(헤더·섹션·목록 포함, 기본 export).
라우팅 및 설정
apps/client/src/routes/routesConfig.ts, apps/client/src/routes/router.tsx
ROUTES_CONFIG에 privacyPolicy(/policytermsOfService(/terms) 추가 및 라우터에 해당 컴포넌트 등록.
MyBookmark / Remind에 Footer 통합
apps/client/src/pages/myBookmark/MyBookmark.tsx, apps/client/src/pages/myBookmark/components/footer/Footer.tsx, apps/client/src/pages/remind/Remind.tsx, apps/client/src/pages/remind/components/footer/Footer.tsx
두 페이지에 Footer 컴포넌트 추가(약관·개인정보 링크, 연락처, 연도, 소셜 아이콘 포함). 레이아웃 패딩 조정(상단 패딩으로 변경).
OnBoarding Footer 링크 변경
apps/client/src/pages/onBoarding/components/footer/Footer.tsx
외부 앵커를 내부 Link로 교체하여 ROUTES_CONFIG 기반의 내부 라우팅 사용.
Login 및 소셜 로그인 링크 업데이트
apps/client/src/pages/login/Login.tsx, apps/client/src/pages/onBoarding/components/funnel/step/SocialLoginStep.tsx
하드코딩된 약관·개인정보 경로를 ROUTES_CONFIG.termsOfService.path / ROUTES_CONFIG.privacyPolicy.path로 변경.
Landing Footer URL 상수화
apps/landing/src/components/Footer.tsx
SERVICE_URL 상수 추가 및 Notion 하드코딩 URL을 ${SERVICE_URL}/terms, ${SERVICE_URL}/policy로 대체.

Sequence Diagram(s)

sequenceDiagram
    participant User as 사용자
    participant Router as Router
    participant Layout as Layout
    participant Sidebar as Sidebar
    participant Page as Page

    Note over User,Router: 사용자가 경로로 접근 (/policy, /terms 또는 기타)
    User->>Router: 요청 경로 전달
    Router->>Layout: 페이지 렌더링 요청
    Layout->>Layout: isSidebarHidden 계산 (onboarding || login || policy)
    alt 사이드바 숨김
        Layout-->>Sidebar: 숨김 처리
    else 사이드바 노출
        Layout-->>Sidebar: 노출 처리
    end
    Layout->>Page: 해당 페이지(정책 또는 콘텐츠+Footer) 렌더링
    Page-->>User: 콘텐츠 및 Footer 전달
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

🛠️ Feature

Suggested reviewers

  • jllee000
  • jjangminii

Poem

🐰 폴짝폴짝 약관 길 걷네,
푸터에 해와 연도 반짝이네,
라우터가 길 정해 사이드 숨기면,
작은 링크로 모두 한자리에,
도묵이랑 축하해요 🎉

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning PR은 #230(이용약관 및 개인정보 처리방침 뷰 추가) 요구사항을 충족하였습니다. 다만 #25(Progress 컴포넌트)는 관련 이슈가 아니며, 실제 변경사항 목록에도 포함되지 않습니다. PR 설명의 Related Issues에서 #25를 제거하거나, #25가 실제로 관련이 있다면 명확히 설명하세요. 현재 PR은 #230 요구사항만 충족합니다.
Out of Scope Changes check ⚠️ Warning 대부분의 변경사항이 #230(이용약관/개인정보처리방침 뷰 및 footer 링크)과 관련이 있습니다. 다만 Layout.tsx의 isSidebarHidden 로직 변경은 명확하게 정의된 요구사항에 포함되지 않습니다. Layout.tsx의 sidebar 숨김 조건 변경(isSidebarHidden 로직 추가)이 #230과의 연관성을 설명하거나, 별도 이슈로 분리하세요.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 변경사항의 핵심을 명확하게 반영하고 있습니다. 이용약관/개인정보처리방침 뷰 구현과 footer 링크 반영이라는 주요 변경사항을 잘 요약했습니다.
Description check ✅ Passed PR 설명이 템플릿 구조를 따르고 있으며, Related Issues(#230), Tasks, PR Point를 포함하고 있습니다. 다만 Screenshot 섹션이 비어있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

github-actions bot commented Jan 6, 2026

✅ Storybook chromatic 배포 확인:
🐿️ storybook

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI Agents
In @apps/client/src/layout/Layout.tsx:
- Around line 12-15: The sidebar-hide check in Layout.tsx is failing due to
inconsistent casing between the hardcoded startsWith('/onboarding') and
routesConfig's onBoarding.path ('/onBoarding') while onBoardingCallback.path
uses '/onboarding'; fix by referencing the canonical route value (e.g., use
routesConfig.onBoarding.path and routesConfig.onBoardingCallback.path) or
normalize casing before comparing (e.g., compare
location.pathname.toLowerCase().startsWith(routesConfig.onBoarding.path.toLowerCase())),
ensuring isSidebarHidden uses the route constants rather than hardcoded strings
so the onboarding path is detected correctly.

In @apps/client/src/pages/myBookmark/components/footer/Footer.tsx:
- Around line 25-57: The row uses a single flex container with class "flex
items-center justify-between" wrapping three children (the address block, the
copyright p referencing currentYear, and the social icons div), which can leave
the middle item visually off-center; pick one fix: either change the container
to a three-column grid (e.g., replace the "flex ... justify-between" container
with a grid and use "grid-cols-3 items-center" and add "text-center" to the
middle copyright p), or keep flex and give the left and right children (the
address element and the social icons div) "flex-1" so the middle copyright p
stays centered, or use "justify-center" with a gap and ensure left/right blocks
are absolutely or relatively positioned; update Footer.tsx accordingly by
modifying the container class and/or adding flex-1/text-center to the specific
children (address, the copyright <p> using currentYear, and the social icons
<div>).
- Around line 26-31: The Footer component currently hardcodes the support email
in the JSX (see address block in Footer.tsx), which exposes it to crawlers;
remove the plain email string and instead render a link to a dedicated contact
page or a server-backed contact endpoint (e.g., replace the paragraph that
contains "이한비 · pinback0615@gmail.com" with an anchor to a Contact/Support route
or API), or if you must display an email obfuscate it at runtime (construct it
via JS parts or fetch from a backend endpoint) so the raw address is not present
in the source; update the Footer rendering logic and any imports/props
accordingly to use the contact route or runtime-obfuscated value.

In @apps/client/src/pages/policy/TermsOfService.tsx:
- Line 179: The last list item in the TermsOfService component
(TermsOfService.tsx) is truncated ("브라우저 또는 보안 정책을 우회하여 확장프로그") — update the
text in the corresponding <li> within the TermsOfService component so the
sentence is complete (e.g. "브라우저 또는 보안 정책을 우회하여 확장프로그램을 사용하는 행위" or the correct
finalized wording) to avoid the broken phrase.
🧹 Nitpick comments (5)
apps/client/src/pages/policy/PrivacyPolicy.tsx (1)

7-11: 로고 클릭 동작을 홈 페이지 이동으로 변경하는 것을 권장합니다.

현재 로고 클릭 시 window.location.reload()로 페이지를 새로고침하는데, 이는 일반적인 UX 패턴과 다릅니다. 일반적으로 로고는 홈 페이지(또는 메인 페이지)로 이동하는 역할을 합니다. 또한 cursor-pointer 클래스가 누락되어 클릭 가능한 요소임을 시각적으로 표시하지 못하고 있습니다.

🔎 제안하는 개선 방안
+import { useNavigate } from 'react-router-dom';
+
 const PrivacyPolicy = () => {
+  const navigate = useNavigate();
+
   return (
     <>
       <header className="z-5 bg-white-bg absolute top-0 flex w-full justify-items-start px-[8.2rem] py-[2.5rem]">
         <img
           src={HeaderLogo}
           alt="header logo"
-          onClick={() => window.location.reload()}
+          className="cursor-pointer"
+          onClick={() => navigate('/')}
         />
       </header>
apps/client/src/pages/policy/TermsOfService.tsx (2)

7-12: 로고 클릭 동작을 홈 페이지 이동으로 변경하는 것을 권장합니다.

PrivacyPolicy와 동일한 이슈입니다. window.location.reload() 대신 홈 페이지로 이동하도록 변경하는 것이 좋습니다.

🔎 제안하는 개선 방안
+import { useNavigate } from 'react-router-dom';
+
 const TermsOfService = () => {
+  const navigate = useNavigate();
+
   return (
     <>
       <header className="z-5 bg-white-bg absolute top-0 flex w-full justify-items-start px-[8.2rem] py-[2.5rem]">
         <img
           src={HeaderLogo}
           alt="header logo"
           className="cursor-pointer"
-          onClick={() => window.location.reload()}
+          onClick={() => navigate('/')}
         />
       </header>

6-13: 선택 사항: 공통 헤더 컴포넌트 추출을 고려해보세요.

PrivacyPolicyTermsOfService가 동일한 헤더 구조를 공유하고 있습니다. 향후 정책 페이지가 더 추가될 경우를 대비해 공통 PolicyPageHeader 컴포넌트로 추출하는 것을 고려해볼 수 있습니다.

apps/client/src/pages/remind/Remind.tsx (1)

26-26: 여러 페이지에서 중복된 Footer 컴포넌트를 공유 컴포넌트로 통합하는 것을 고려하세요.

AI 요약에 따르면 MyBookmark와 Remind 페이지에 각각 별도의 Footer 컴포넌트가 추가되었습니다. 이들 컴포넌트의 내용이 동일하거나 유사하다면, @shared/components 디렉터리에 공통 Footer 컴포넌트를 만들어 코드 중복을 줄이고 유지보수성을 개선할 수 있습니다.

🔎 제안하는 리팩토링 방향
-import Footer from './components/footer/Footer';
+import Footer from '@shared/components/footer/Footer';

그리고 apps/client/src/shared/components/footer/Footer.tsx에 공통 Footer 컴포넌트를 생성하세요.

Also applies to: 181-181

apps/landing/src/components/Footer.tsx (1)

5-5: 환경 변수를 사용하여 SERVICE_URL을 관리하는 것을 권장합니다.

SERVICE_URL이 하드코딩되어 있어 개발, 스테이징, 프로덕션 환경에서 유연하게 대응하기 어렵습니다. 환경 변수로 관리하면 배포 환경에 따라 적절한 URL을 사용할 수 있습니다.

🔎 제안하는 수정 사항
-  const SERVICE_URL = 'https://pinback.today';
+  const SERVICE_URL = import.meta.env.VITE_SERVICE_URL || 'https://pinback.today';

그리고 .env 파일에 환경별 URL을 설정하세요:

VITE_SERVICE_URL=https://pinback.today
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2478303 and 8935ed5.

📒 Files selected for processing (11)
  • apps/client/src/layout/Layout.tsx
  • apps/client/src/pages/myBookmark/MyBookmark.tsx
  • apps/client/src/pages/myBookmark/components/footer/Footer.tsx
  • apps/client/src/pages/onBoarding/components/footer/Footer.tsx
  • apps/client/src/pages/policy/PrivacyPolicy.tsx
  • apps/client/src/pages/policy/TermsOfService.tsx
  • apps/client/src/pages/remind/Remind.tsx
  • apps/client/src/pages/remind/components/footer/Footer.tsx
  • apps/client/src/routes/router.tsx
  • apps/client/src/routes/routesConfig.ts
  • apps/landing/src/components/Footer.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 5
File: apps/extension/src/index.css:1-1
Timestamp: 2025-08-19T17:18:57.678Z
Learning: constantly-dev는 디자인 시스템 설정 PR 머지 후 `import 'pinback/tailwind-config/shared-styles.css';`를 `app.css`나 `index.css`에서 사용하여 공유 스타일을 관리할 계획입니다.
📚 Learning: 2025-07-08T11:47:10.642Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 30
File: apps/extension/src/App.tsx:10-21
Timestamp: 2025-07-08T11:47:10.642Z
Learning: In apps/extension/src/App.tsx, the InfoBox component currently uses a hardcoded external URL for the icon prop as a temporary static placeholder. The plan is to replace this with dynamic favicon extraction from bookmarked websites in future iterations.

Applied to files:

  • apps/client/src/pages/myBookmark/MyBookmark.tsx
🧬 Code graph analysis (2)
apps/client/src/routes/router.tsx (1)
apps/client/src/routes/routesConfig.ts (1)
  • ROUTES_CONFIG (1-38)
apps/client/src/layout/Layout.tsx (1)
apps/client/src/routes/routesConfig.ts (1)
  • ROUTES_CONFIG (1-38)
⏰ 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: storybook
🔇 Additional comments (14)
apps/client/src/pages/onBoarding/components/footer/Footer.tsx (1)

10-22: 내부 라우팅 전환이 올바르게 구현되었습니다.

외부 링크에서 React Router의 Link 컴포넌트로 전환하여 페이지 새로고침 없이 내부 네비게이션을 지원합니다. 라우트 경로도 routesConfig와 일치합니다.

apps/client/src/pages/myBookmark/MyBookmark.tsx (1)

21-21: Footer 컴포넌트 통합이 올바르게 구현되었습니다.

Footer가 메인 컨텐츠와 모달 포털 사이에 적절하게 배치되어 있습니다.

Also applies to: 106-106

apps/client/src/routes/router.tsx (1)

7-8: 정책 페이지 라우트 설정이 올바르게 구현되었습니다.

새로운 개인정보 처리방침과 이용약관 페이지가 라우터에 적절히 통합되었으며, ROUTES_CONFIG를 통해 일관되게 관리되고 있습니다.

Also applies to: 47-54

apps/landing/src/components/Footer.tsx (1)

19-19: LGTM!

링크 구조가 올바르게 업데이트되었으며, target="_blank"와 함께 rel="noopener noreferrer" 보안 속성이 적절하게 적용되었습니다.

Also applies to: 28-28

apps/client/src/layout/Layout.tsx (2)

8-10: LGTM!

정책 페이지 확인 로직이 올바르게 구현되었으며, ROUTES_CONFIG를 활용하여 일관성을 유지하고 있습니다.


20-20: 조건부 렌더링 구현은 올바릅니다.

isSidebarHidden 플래그를 사용한 조건부 렌더링 로직은 적절합니다. 다만, 위에서 지적한 대소문자 불일치 문제가 해결되어야 의도한 대로 동작합니다.

apps/client/src/routes/routesConfig.ts (1)

30-37: LGTM!

새로운 정책 페이지 라우트가 명확하고 일관성 있게 추가되었습니다. 경로 네이밍(/policy, /terms)도 관례적이며 적절합니다.

apps/client/src/pages/remind/components/footer/Footer.tsx (3)

1-5: LGTM!

임포트와 초기 설정이 적절합니다. currentYear 계산도 표준적인 방식입니다.


10-22: LGTM!

내부 정책 페이지 링크가 Link 컴포넌트를 사용하여 SPA 네비게이션을 올바르게 구현하고 있으며, 스타일링도 적절합니다.


38-55: LGTM!

외부 소셜 링크가 보안 속성(rel="noopener noreferrer")과 접근성 속성(aria-label)을 적절하게 포함하고 있습니다.

apps/client/src/pages/myBookmark/components/footer/Footer.tsx (4)

1-2: LGTM! 적절한 import 사용

내부 네비게이션을 위해 Link 컴포넌트를 사용하고, 디자인 시스템의 Icon을 활용하는 것이 올바릅니다.


10-22: LGTM! 내부 라우팅 적절하게 구현됨

Link 컴포넌트를 사용하여 /terms/policy 페이지로의 내부 네비게이션이 올바르게 구현되었습니다. 호버 효과와 스타일링도 적절합니다.


8-8: 고정 padding-right 값 확인 필요

Footer에 고정된 pr-[3rem] 값이 사용되고 있습니다. 사이드바의 표시/숨김 상태에 따라 이 값이 적절한지 확인이 필요합니다.

다양한 뷰포트와 사이드바 상태에서 레이아웃이 올바르게 동작하는지 테스트해주세요.


38-56: LGTM! 접근성 모범 사례 준수

외부 링크에 적절한 보안 속성(rel="noopener noreferrer")과 접근성 레이블(aria-label)이 적용되어 있습니다. 호버 상태의 시각적 피드백도 잘 구현되었습니다.

Comment on lines 12 to 15
const isSidebarHidden =
location.pathname.startsWith('/onboarding') ||
location.pathname.startsWith('/login') ||
isPolicyPage;
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

CRITICAL: 경로 대소문자 불일치로 인한 사이드바 숨김 로직 오류

Line 13에서 startsWith('/onboarding')로 체크하고 있지만, routesConfig.tsonBoarding.path/onBoarding(대문자 B)으로 정의되어 있습니다. 이로 인해 온보딩 페이지에서 사이드바가 의도대로 숨겨지지 않습니다.

참고로 onBoardingCallback.path/onboarding/callback(소문자)로 정의되어 있어 라우트 정의 자체에도 일관성이 없습니다.

🔎 제안하는 수정 방안

옵션 1: Layout.tsx 수정 (권장)

   const isSidebarHidden =
-    location.pathname.startsWith('/onboarding') ||
+    location.pathname.startsWith(ROUTES_CONFIG.onBoarding.path) ||
     location.pathname.startsWith('/login') ||
     isPolicyPage;

옵션 2: routesConfig.ts의 경로 통일
onBoarding.path를 소문자 /onboarding으로 변경하여 onBoardingCallback과 일관성을 맞춥니다.

📝 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 isSidebarHidden =
location.pathname.startsWith('/onboarding') ||
location.pathname.startsWith('/login') ||
isPolicyPage;
const isSidebarHidden =
location.pathname.startsWith('/onBoarding') ||
location.pathname.startsWith('/login') ||
isPolicyPage;
🤖 Prompt for AI Agents
In @apps/client/src/layout/Layout.tsx around lines 12 - 15, The sidebar-hide
check in Layout.tsx is failing due to inconsistent casing between the hardcoded
startsWith('/onboarding') and routesConfig's onBoarding.path ('/onBoarding')
while onBoardingCallback.path uses '/onboarding'; fix by referencing the
canonical route value (e.g., use routesConfig.onBoarding.path and
routesConfig.onBoardingCallback.path) or normalize casing before comparing
(e.g., compare
location.pathname.toLowerCase().startsWith(routesConfig.onBoarding.path.toLowerCase())),
ensuring isSidebarHidden uses the route constants rather than hardcoded strings
so the onboarding path is detected correctly.

Comment on lines +25 to +57
<div className="flex items-center justify-between">
<address className="flex gap-[0.8rem] not-italic">
<p className="caption2-sb text-font-ltgray-4">운영팀 문의</p>
<p className="caption2-m text-font-ltgray-4">
이한비 · pinback0615@gmail.com
</p>
</address>
<p className="caption2-m text-font-ltgray-4">
©{currentYear} pinback All rights reserved.
</p>

<div className="flex items-end gap-[1.2rem]">
<p className="caption2-m text-gray400">TEAM. 도묵이</p>
<a
href="https://instagram.com/pinback.today/"
target="_blank"
rel="noopener noreferrer"
aria-label="Pinback 인스타그램"
className="transition-opacity hover:opacity-80"
>
<Icon name="instagram" width={28} height={28} />
</a>
<a
href="https://pinback.palms.blog/"
target="_blank"
rel="noopener noreferrer"
aria-label="Pinback 블로그"
className="transition-opacity hover:opacity-80"
>
<Icon name="palms" width={28} height={28} />
</a>
</div>
</div>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

레이아웃 구조 검토 필요

justify-between을 사용하여 3개의 요소(연락처, 저작권, 소셜 아이콘)를 배치하고 있습니다. 이 경우 가운데 요소(저작권 텍스트)가 시각적으로 중앙에 위치하지 않을 수 있습니다.

의도한 레이아웃이 맞는지 확인하고, 필요시 다음과 같은 대안을 고려해보세요:

  • justify-centergap 사용
  • Grid 레이아웃 사용하여 명시적인 열 배치
  • 각 섹션에 flex-1 적용
🔎 Grid 레이아웃 대안
-      <div className="flex items-center justify-between">
+      <div className="grid grid-cols-3 items-center">
-        <address className="flex gap-[0.8rem] not-italic">
+        <address className="flex gap-[0.8rem] not-italic justify-self-start">
           <p className="caption2-sb text-font-ltgray-4">운영팀 문의</p>
           <p className="caption2-m text-font-ltgray-4">
             이한비 · pinback0615@gmail.com
           </p>
         </address>
-        <p className="caption2-m text-font-ltgray-4">
+        <p className="caption2-m text-font-ltgray-4 justify-self-center">
           ©{currentYear} pinback All rights reserved.
         </p>
 
-        <div className="flex items-end gap-[1.2rem]">
+        <div className="flex items-end gap-[1.2rem] justify-self-end">
           <p className="caption2-m text-gray400">TEAM. 도묵이</p>
🤖 Prompt for AI Agents
In @apps/client/src/pages/myBookmark/components/footer/Footer.tsx around lines
25 - 57, The row uses a single flex container with class "flex items-center
justify-between" wrapping three children (the address block, the copyright p
referencing currentYear, and the social icons div), which can leave the middle
item visually off-center; pick one fix: either change the container to a
three-column grid (e.g., replace the "flex ... justify-between" container with a
grid and use "grid-cols-3 items-center" and add "text-center" to the middle
copyright p), or keep flex and give the left and right children (the address
element and the social icons div) "flex-1" so the middle copyright p stays
centered, or use "justify-center" with a gap and ensure left/right blocks are
absolutely or relatively positioned; update Footer.tsx accordingly by modifying
the container class and/or adding flex-1/text-center to the specific children
(address, the copyright <p> using currentYear, and the social icons <div>).

Comment on lines +26 to +31
<address className="flex gap-[0.8rem] not-italic">
<p className="caption2-sb text-font-ltgray-4">운영팀 문의</p>
<p className="caption2-m text-font-ltgray-4">
이한비 · pinback0615@gmail.com
</p>
</address>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

이메일 주소 노출로 인한 스팸 위험

운영팀 이메일 주소가 프론트엔드 코드에 평문으로 노출되어 있어 스팸봇의 타겟이 될 수 있습니다. 다음 방법을 고려해보세요:

  • 전용 문의 폼 구현
  • 이메일 주소 난독화
  • 별도의 고객지원 이메일 서비스 활용
🔎 이메일 난독화 예시
-          <p className="caption2-m text-font-ltgray-4">
-            이한비 · pinback0615@gmail.com
-          </p>
+          <p className="caption2-m text-font-ltgray-4">
+            이한비 · pinback0615{'@'}gmail{'.'}com
+          </p>

또는 문의 페이지 링크로 대체:

-          <p className="caption2-m text-font-ltgray-4">
-            이한비 · pinback0615@gmail.com
-          </p>
+          <Link to="/contact" className="caption2-m text-font-ltgray-4 hover:underline">
+            운영팀에 문의하기
+          </Link>
📝 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
<address className="flex gap-[0.8rem] not-italic">
<p className="caption2-sb text-font-ltgray-4">운영팀 문의</p>
<p className="caption2-m text-font-ltgray-4">
이한비 · pinback0615@gmail.com
</p>
</address>
<address className="flex gap-[0.8rem] not-italic">
<p className="caption2-sb text-font-ltgray-4">운영팀 문의</p>
<p className="caption2-m text-font-ltgray-4">
이한비 · pinback0615{'@'}gmail{'.'}com
</p>
</address>
🤖 Prompt for AI Agents
In @apps/client/src/pages/myBookmark/components/footer/Footer.tsx around lines
26 - 31, The Footer component currently hardcodes the support email in the JSX
(see address block in Footer.tsx), which exposes it to crawlers; remove the
plain email string and instead render a link to a dedicated contact page or a
server-backed contact endpoint (e.g., replace the paragraph that contains "이한비 ·
pinback0615@gmail.com" with an anchor to a Contact/Support route or API), or if
you must display an email obfuscate it at runtime (construct it via JS parts or
fetch from a backend endpoint) so the raw address is not present in the source;
update the Footer rendering logic and any imports/props accordingly to use the
contact route or runtime-obfuscated value.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/client/src/pages/myBookmark/components/footer/Footer.tsx (1)

10-24: 시맨틱 HTML 및 스타일 개선 제안

  1. <p> 태그는 단락을 나타내므로 구분자(|)에는 <span>이 더 적합합니다.
  2. Link 컴포넌트는 기본적으로 클릭 가능한 요소이므로 cursor-pointer 클래스가 불필요합니다.
♻️ 개선 제안
       <Link
         to={ROUTES_CONFIG.termsOfService.path}
-        className="caption1-sb text-font-gray-2 cursor-pointer hover:underline"
+        className="caption1-sb text-font-gray-2 hover:underline"
       >
         이용약관
       </Link>
-      <p className="caption1-sb text-font-gray-2">|</p>
+      <span className="caption1-sb text-font-gray-2" aria-hidden="true">|</span>
       <Link
         to={ROUTES_CONFIG.privacyPolicy.path}
-        className="caption1-sb text-font-gray-2 cursor-pointer hover:underline"
+        className="caption1-sb text-font-gray-2 hover:underline"
       >
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8a42b58 and 2314c21.

📒 Files selected for processing (5)
  • apps/client/src/pages/login/Login.tsx
  • apps/client/src/pages/myBookmark/components/footer/Footer.tsx
  • apps/client/src/pages/onBoarding/components/footer/Footer.tsx
  • apps/client/src/pages/onBoarding/components/funnel/step/SocialLoginStep.tsx
  • apps/client/src/pages/remind/components/footer/Footer.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
  • apps/client/src/pages/onBoarding/components/footer/Footer.tsx
  • apps/client/src/pages/remind/components/footer/Footer.tsx
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 5
File: apps/extension/src/index.css:1-1
Timestamp: 2025-08-19T17:18:57.678Z
Learning: constantly-dev는 디자인 시스템 설정 PR 머지 후 `import 'pinback/tailwind-config/shared-styles.css';`를 `app.css`나 `index.css`에서 사용하여 공유 스타일을 관리할 계획입니다.
📚 Learning: 2025-07-15T20:00:13.756Z
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 80
File: apps/client/src/shared/components/ui/modalPop/ModalPop.tsx:36-41
Timestamp: 2025-07-15T20:00:13.756Z
Learning: In apps/client/src/shared/components/ui/modalPop/ModalPop.tsx, the InfoBox component uses hardcoded values for title, location, and icon URL as temporary test data. These should be replaced with dynamic data from props when implementing actual functionality and should be marked with TODO comments for future changes.

Applied to files:

  • apps/client/src/pages/onBoarding/components/funnel/step/SocialLoginStep.tsx
🧬 Code graph analysis (2)
apps/client/src/pages/myBookmark/components/footer/Footer.tsx (1)
apps/client/src/routes/routesConfig.ts (1)
  • ROUTES_CONFIG (1-38)
apps/client/src/pages/login/Login.tsx (1)
apps/client/src/routes/routesConfig.ts (1)
  • ROUTES_CONFIG (1-38)
⏰ 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: storybook
🔇 Additional comments (6)
apps/client/src/pages/onBoarding/components/funnel/step/SocialLoginStep.tsx (1)

5-5: 라우트 중앙화 리팩토링이 올바르게 적용되었습니다.

하드코딩된 라우트 경로를 ROUTES_CONFIG로 교체하여 라우트 관리를 중앙화한 것은 좋은 개선입니다. 타입 안전성이 확보되고 향후 경로 변경 시 유지보수가 용이해집니다.

Also applies to: 38-38, 45-45

apps/client/src/pages/login/Login.tsx (1)

9-9: LGTM! 라우트 설정이 일관되게 적용되었습니다.

SocialLoginStep 컴포넌트와 동일한 패턴으로 ROUTES_CONFIG를 활용하여 라우트를 중앙화했습니다. 코드베이스 전반에 걸쳐 일관된 접근 방식이 적용되어 좋습니다.

Also applies to: 52-52, 59-59

apps/client/src/pages/myBookmark/components/footer/Footer.tsx (4)

1-3: LGTM!

임포트가 깔끔하고 모두 컴포넌트에서 사용되고 있습니다.


5-6: LGTM!

컴포넌트 선언과 연도 계산이 적절합니다.


39-56: LGTM!

외부 링크에 target="_blank", rel="noopener noreferrer", aria-label이 적절히 적용되어 보안 및 접근성 모범 사례를 잘 따르고 있습니다.


38-38: 이 색상 클래스는 프로젝트의 정의된 디자인 토큰 시스템의 일부입니다. text-gray400packages/design-system에 정의되어 있으며 프로젝트 전반에서 일관되게 사용되고 있습니다. 프로젝트는 text-gray900, bg-gray200, placeholder-font-gray-3 등 의도적으로 다양한 네이밍 패턴을 사용하는 커스텀 디자인 토큰 시스템을 운영하고 있으므로, 이를 변경할 필요가 없습니다.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
apps/client/src/pages/myBookmark/components/footer/Footer.tsx (1)

40-56: 소셜 미디어 URL을 상수로 추출하는 것을 고려해보세요.

Instagram과 블로그 URL이 컴포넌트 내에 하드코딩되어 있습니다. 향후 URL 변경 시 유지보수를 위해 별도 상수 파일이나 환경 변수로 관리하는 것을 권장합니다.

♻️ 제안하는 리팩토링

상수 파일 생성 (예: src/constants/social.ts):

export const SOCIAL_LINKS = {
  instagram: 'https://instagram.com/pinback.today/',
  blog: 'https://pinback.palms.blog/',
} as const;

Footer 컴포넌트에서 사용:

+import { SOCIAL_LINKS } from '@constants/social';
+
 const Footer = () => {
   // ...
   return (
     // ...
     <a
-      href="https://instagram.com/pinback.today/"
+      href={SOCIAL_LINKS.instagram}
       target="_blank"
       rel="noopener noreferrer"
       aria-label="Pinback 인스타그램"
       className="transition-opacity hover:opacity-80"
     >
       <Icon name="instagram" width={28} height={28} />
     </a>
     <a
-      href="https://pinback.palms.blog/"
+      href={SOCIAL_LINKS.blog}
       target="_blank"
       rel="noopener noreferrer"
       aria-label="Pinback 블로그"
       className="transition-opacity hover:opacity-80"
     >
       <Icon name="palms" width={28} height={28} />
     </a>
   );
 };
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2314c21 and f1ecd8a.

📒 Files selected for processing (4)
  • apps/client/src/pages/myBookmark/MyBookmark.tsx
  • apps/client/src/pages/myBookmark/components/footer/Footer.tsx
  • apps/client/src/pages/remind/Remind.tsx
  • apps/client/src/pages/remind/components/footer/Footer.tsx
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/client/src/pages/remind/components/footer/Footer.tsx
  • apps/client/src/pages/myBookmark/MyBookmark.tsx
  • apps/client/src/pages/remind/Remind.tsx
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 5
File: apps/extension/src/index.css:1-1
Timestamp: 2025-08-19T17:18:57.678Z
Learning: constantly-dev는 디자인 시스템 설정 PR 머지 후 `import 'pinback/tailwind-config/shared-styles.css';`를 `app.css`나 `index.css`에서 사용하여 공유 스타일을 관리할 계획입니다.
🧬 Code graph analysis (1)
apps/client/src/pages/myBookmark/components/footer/Footer.tsx (1)
apps/client/src/routes/routesConfig.ts (1)
  • ROUTES_CONFIG (1-38)
🔇 Additional comments (4)
apps/client/src/pages/myBookmark/components/footer/Footer.tsx (4)

1-7: 좋은 구조입니다!

중앙화된 라우팅 관리를 위해 ROUTES_CONFIG를 사용하고 있고, 동적으로 현재 연도를 계산하는 방식이 적절합니다.


11-23: 라우팅 구현이 올바릅니다.

ROUTES_CONFIG를 사용하여 일관된 라우팅을 유지하고 있으며, hover:underline 효과로 사용자 경험이 개선되었습니다.


24-26: 섹션 간 간격 확인이 필요합니다.

상단 링크 영역(이용약관, 개인정보처리방침)과 하단 정보 영역(연락처, 저작권) 사이에 명시적인 여백이 없습니다. 의도한 디자인인지 확인하고, 필요시 간격을 추가하는 것을 고려해보세요.

💡 간격 추가 예시
       </div>
 
-      <div className="flex items-center justify-between">
+      <div className="mt-[2.4rem] flex items-center justify-between">
         <address className="flex gap-[0.8rem] not-italic">

39-56: 접근성 구현이 우수합니다.

외부 링크에 적절한 rel="noopener noreferrer" 보안 속성과 aria-label이 적용되어 있습니다.

@constantly-dev constantly-dev merged commit 9629a80 into develop Jan 7, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat 기능 개발하라 개발 달려라 달려

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feat] 이용약관 및 개인정보 처리방침 뷰 추가

1 participant