[FEAT] 파비콘·SEO 메타데이터 설정 및 아키텍처 문서 동기화 - #216
Conversation
- public/favicon.png를 next.js metadata.icons에 연결해 브라우저 탭 파비콘을 표시했습니다. - 정적 title/description을 generateMetadata로 전환해 로케일(en/ko)별 텍스트가 반영되도록 했습니다. - metadataBase, Open Graph, Twitter Card, hreflang(alternates), robots, formatDetection 등 SEO 메타데이터를 추가했습니다. - messages/en.json, messages/ko.json에 Metadata 네임스페이스를 추가했습니다.
- API 클라이언트가 실제로는 swagger-typescript-api가 아닌 Orval 기반임을 반영해 stack.md를 수정했습니다. - Git Hooks를 Husky 단독이 아닌 Husky + lint-staged 조합으로 정정했습니다. - SVG 아이콘 생성 방식을 SVG sprite에서 실제 사용 중인 SVGR로 수정했습니다. - structure.md의 모노레포 트리에서 존재하지 않는 lib/를 제거하고 api/, containers/ 등 실제 디렉터리를 반영했습니다. - components.md의 예시 도메인을 존재하지 않는 auth에서 실제 존재하는 focus 도메인으로 교체했습니다. - commit.md의 config 스코프에 누락된 tailwind-config 패키지를 추가했습니다. - tokens.md에 실제 CSS에는 있지만 문서화되지 않았던 Radius, Shadow, Z-Index, overlay 색상 토큰을 추가했습니다.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Timo Performance ReportBundle Size — timo-web
Lighthouse — timo-web
Image Optimization — timo-web
측정 커밋: |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@apps/timo-web/app/`[locale]/layout.tsx:
- Around line 61-79: Remove the path-dependent canonical, languages, and
openGraph.url fields from the root layout’s metadata configuration. Keep
locale-independent Open Graph fields and move these route-specific SEO values to
each top-level or individual page metadata definition, where the current
pathname is available, so child routes do not inherit the homepage URL.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: fe8d26cc-f259-4658-82c9-5e9140bbb5c0
⛔ Files ignored due to path filters (1)
apps/timo-web/public/favicon.pngis excluded by!**/*.png
📒 Files selected for processing (8)
apps/timo-web/app/[locale]/layout.tsxapps/timo-web/messages/en.jsonapps/timo-web/messages/ko.jsondocs/architecture/components.mddocs/architecture/stack.mddocs/architecture/structure.mddocs/conventions/commit.mddocs/design/tokens.md
- app/[locale]/layout.tsx는 locale 세그먼트까지의 params만 받아 하위 경로를 알 수 없는데도, alternates.canonical/languages와 openGraph.url을 항상 locale 루트 경로로 고정해 모든 하위 라우트가 홈 URL을 상속했습니다. - 경로 종속 필드를 제거하고, locale에만 의존하는 openGraph 필드(type, siteName, title, description, locale, alternateLocale)는 유지했습니다.
- (main) 라우트 그룹은 AuthGuardProvider로 로그인이 필요한 개인화 화면이라 robots.index/follow를 false로 설정해 검색 엔진 노출에서 제외했습니다.
- 로그인 페이지에 generateMetadata를 추가해 로케일별 title/description과 경로 고유 canonical(/{locale}/login)을 설정했습니다. messages의 Login 네임스페이스에 title 키를 새로 추가했습니다.
- 약관 페이지에 generateMetadata를 추가해 type 쿼리 파라미터(SERVICE/PRIVACY)에 따라 기존 Settings.nav.policy/privacy 문자열을 재사용한 제목과 경로 고유 canonical(/{locale}/policy)을 설정했습니다.
ISSUE 🔗
close #215
What is this PR? 🔍
파비콘과 로케일별 SEO 메타데이터를 설정하고, 실제 구현과 어긋나 있던 아키텍처·컨벤션·디자인 토큰 문서를 최신 상태로 동기화했습니다.
배경
metadata객체(title/description)만 export했고, 파비콘·Open Graph·hreflang 등 SEO 관련 메타데이터는 설정돼 있지 않았습니다.docs/아키텍처 문서 일부가 실제 코드와 어긋나 있어(API 클라이언트 표기, 존재하지 않는 디렉터리 등) 온보딩 시 혼란을 줄 수 있었습니다.metadata를 next-intl 기반generateMetadata로 전환해 로케일별 텍스트·hreflang·OG locale을 반영하고, 문서는 실제 소스 파일(orval.config.ts,theme.css등)을 대조해 정정했습니다.파비콘·SEO 메타데이터 (apps/timo-web)
public/favicon.png를 파비콘으로 연결하고, 루트 레이아웃의 메타데이터를 로케일 인식generateMetadata로 전환해 SEO 필드를 추가했습니다.messages/{en,ko}.json에Metadata네임스페이스(title,description)를 추가하고,layout.tsx의generateMetadata({ params })에서hasLocale로 유효성 검증 후getTranslations({ locale, namespace: "Metadata" })로 텍스트를 가져옵니다.metadataBase를https://timo.kr로 고정하고,title.template(%s | timo),openGraph(locale을en_US/ko_KR로 매핑,alternateLocale),twitter(summary카드),robots(index/follow 명시),formatDetection.telephone: false를 설정했습니다. OG 이미지 에셋이 아직 없어summary_large_image대신summary카드를 사용했습니다.og-image.png)는 이번 범위에 포함하지 않았습니다. 추후 디자인 에셋이 준비되면openGraph.images/twitter.images를 추가하는 후속 작업이 필요합니다.문서 동기화 (docs/)
docs/architecture/*,docs/conventions/commit.md,docs/design/tokens.md를 실제 구현 기준으로 정정했습니다.orval.config.ts)이었고, 모노레포 트리에 존재하지 않는lib/가 남아 있었으며, 컴포넌트 계층 예시가 실존하지 않는auth도메인을 참조하는 등 여러 항목이 실제 코드와 어긋나 있었습니다.packages/tailwind-config/theme.css에는 Shadow·Z-Index 토큰이,tokens/radius.css에는 Radius 토큰이 정의돼 있었지만tokens.md에는 반영되지 않았습니다.orval.config.ts,.husky/pre-commit,lint-staged.config.js,generate-icons.mjs, 실제apps/timo-web디렉터리 구조,packages/tailwind-config/theme.css·tokens/radius.css)와 대조해 표·트리·예시를 갱신했습니다.components.md의 예시 도메인은_components/_containers/_hooks/_queries/_types/_utils가 모두 존재하는focus도메인으로 교체했습니다.코드 리뷰 반영 — 경로 종속 메타데이터 분리 (apps/timo-web)
alternates.canonical/languages,openGraph.url)를 제거하고, 인증이 필요한(main)라우트 그룹은robotsnoindex로 비공개 처리했으며, 공개 페이지인 로그인·약관에는 페이지별 메타데이터를 추가했습니다.app/[locale]/layout.tsx는[locale]세그먼트까지의params만 받아 하위 경로를 알 수 없는데도,alternates.canonical/languages와openGraph.url을 항상 locale 루트 경로로 고정해/en/today,/en/focus,/en/settings/account등 모든 하위 라우트가 홈 URL을 canonical/OG URL로 상속한다는 점이 지적됐습니다.openGraph필드(type,siteName,title,description,locale,alternateLocale)만 유지했습니다.(main)라우트 그룹(home/today/focus/settings/statistics)은 모두AuthGuardProvider로 감싸진 로그인 필수·개인화 화면이라, 그룹 레이아웃 한 곳에 정적metadata: { robots: { index: false, follow: false } }를 추가해 그룹 전체를 검색 노출에서 제외했습니다. 반대로login,policy는 비로그인 상태에서도 접근 가능한 공개 페이지이므로 각각generateMetadata를 추가해 로케일별 title/description과 페이지 고유alternates.canonical(/{locale}/login,/{locale}/policy)을 설정했습니다.policy는type쿼리 파라미터(SERVICE/PRIVACY)에 따라 기존Settings.nav.policy/privacy문자열을 재사용해 제목을 다르게 표시하도록 했습니다(새 번역 키를 만들지 않음).onboarding,oauth/callback도 인증이 필요하거나 콘텐츠가 없는 페이지지만, 이번에 합의한 범위(공개 페이지 일부 + 인증 그룹 전체 noindex)에는 포함하지 않았습니다. 필요 시 후속 작업으로 처리합니다.To Reviewers
hasLocale+notFound()가드가 이제 루트 레이아웃(컴포넌트/generateMetadata 각각), 로그인·약관 페이지의generateMetadata까지 총 4곳에 반복됩니다. Next.js가generateMetadata와 컴포넌트를 별도 시점에 호출하고, 각 페이지의generateMetadata가 부모 레이아웃의setRequestLocale실행 여부를 보장받지 못해 각자 명시적으로{ locale, namespace }를 넘기도록 했는데, 반복이 늘어난 만큼 공용 헬퍼로 추출할지 판단 부탁드립니다.SEO 메타데이터의 도메인은
https://timo.kr로 지정했습니다. 실제 배포 도메인이 다르면 알려주세요.문서 커밋은 코드 변경과 무관한 정정이라 별도 커밋으로 분리했습니다.
Screenshot 📷
Test Checklist ✔
pnpm check-types:web통과pnpm lint:web통과/en/today,/en/settings등 하위 라우트에서 canonical 태그가 더 이상 홈 URL을 가리키지 않는지 확인 — 후속 작업