Skip to content

CodeLog 마이크로 블로그 서비스 전환 #77

@parkblo

Description

@parkblo

Introduction

Status: Planned

이 문서는 CodeLog를 기존 코드 스니펫 SNS에서 TIL 특화 소셜 마이크로 블로그로 전환하기 위한 구현 계획이다. 범위는 공개 랜딩 페이지, 인증 게이트, TODAY 피드, 게시글 모델 변경, Logan 봇 자동 댓글, PostHog 실험 계측, SEO 정비를 포함한다.

1. Requirements & Constraints

  • REQ-001: app/page.tsx/home 리다이렉트를 제거하고 공개 랜딩 페이지를 렌더링해야 한다. 로그인된 사용자가 /에 접근하면 /home으로 즉시 리다이렉트해야 한다.
  • REQ-002: /home, /today, /explore, /profile/[username], /bookmarks, /search, /settings는 인증 필수 경로로 동작해야 한다. 비로그인 접근 시 /?auth=required&next=...로 리다이렉트해야 한다.
  • REQ-003: src/widgets/create-post/ui/create-post-form.tsx는 플레이스홀더를 오늘은 무엇을 배웠나요?로 변경하고, 오늘 이미 글을 작성한 경우 작성 진입을 잠그거나 오늘 글 편집 진입을 제공해야 한다.
  • REQ-004: src/pages/home/ui/home.tsx는 게시글 작성 유도 영역 바로 아래에 TODAY 구역을 배치해야 한다. TODAY 구역은 작성자에게만 실데이터를 노출하고, 미작성자에게는 blur 오버레이와 CTA를 노출해야 한다.
  • REQ-005: app/today/page.tsxsrc/pages/today/ui/today.tsx는 오늘 날짜 게시글 전용 페이지를 제공해야 한다. 오늘 글을 작성하지 않은 사용자는 /home으로 리다이렉트되고 토스트 메시지를 받아야 한다.
  • REQ-006: 게시글 카드와 상세 페이지는 content 대신 description을 핵심 요약 텍스트로 사용해야 한다. 상세 페이지는 description, content, code를 모두 렌더링해야 한다.
  • REQ-007: /post/[postId]는 공개 경로로 유지해야 한다. 좋아요, 댓글, 북마크 같은 인터랙션은 비로그인 시 인증 모달을 열어야 한다.
  • REQ-008: 모든 코드 스니펫은 is_review_enabled 여부와 무관하게 인라인 코멘트를 허용해야 한다. /code-review 라우트와 관련 네비게이션은 삭제해야 한다.
  • DAT-001: posts.description 컬럼은 TEXT NOT NULL이며 200자 이하 제약을 가져야 한다. 작성/수정 RPC와 프론트엔드 스키마는 동일 제약을 가져야 한다.
  • DAT-002: posts.authoring_mode 컬럼은 hand_written 또는 ai_assisted만 허용해야 한다. 모든 게시글 카드 헤더와 상세 페이지에서 배지를 항상 표시해야 한다.
  • DAT-003: 게시글 작성은 사용자당 로컬 날짜 기준 하루 1회만 허용해야 한다. 수정은 허용하고, soft delete 된 글은 제한 카운트에서 제외해야 한다.
  • REQ-009: Logan Bot은 게시글당 1개의 일반 댓글만 생성해야 한다. 생성 경로는 Supabase Database Webhook과 Edge Function이어야 하며 응답은 한국어 200자 이하여야 한다.
  • EXP-001: TODAY 실험은 PostHog user-level randomization을 전제로 하며 today_module_viewed를 exposure event로 사용해야 한다.
  • SEC-001: 인증 게이트는 src/shared/lib/supabase/middleware.ts와 서버 액션 양쪽에서 적용되어야 한다. 클라이언트 UI 숨김만으로 접근을 제어하면 안 된다.
  • CON-001: 기존 App Router 엔트리 파일 구조와 feature-sliced 구조를 유지해야 한다. app/*는 진입점만 담당하고 실제 페이지 로직은 src/pages/*로 위임해야 한다.
  • CON-002: 랜딩 페이지는 데스크톱에서 50:50 레이아웃, 모바일에서 우측 마키를 숨기거나 축소하는 반응형 동작을 가져야 한다.
  • GUD-001: 기존 AuthDialog, PostDialog, PostInfiniteList, updateSession, captureEvent 유틸리티를 재사용하고, 신규 로직은 동일 계층에 추가해야 한다.
  • PAT-001: 신규 서버 쿼리 함수는 src/entities/post/api/post.service.ts 또는 src/features/post-list/api/post-list.action.ts에 추가하고, 경로 보호 로직은 src/proxy.ts에서 한 번만 호출되는 updateSession() 내부에서 중앙 관리해야 한다.

2. Implementation Steps

Implementation Phase 1

  • GOAL-001: 공개 랜딩 페이지와 인증 게이트를 도입하고, v1의 코드 리뷰 전용 진입점을 제거한다.
Task Description Completed Date
TASK-001 app/page.tsx, app/layout.tsx를 수정하고 src/pages/landing/index.ts, src/pages/landing/ui/landing.tsx, src/pages/landing/ui/vertical-marquee.tsx, src/pages/landing/model/mock-posts.ts를 생성한다. /는 공개 랜딩을 렌더링하고, 로그인 사용자는 /home으로 리다이렉트하며, 모바일에서는 마키를 숨긴다.
TASK-002 src/shared/lib/auth.ts, src/features/auth/api/require-auth.ts, src/shared/lib/supabase/middleware.ts, src/proxy.ts를 수정해 보호 경로 목록과 공개 경로 목록을 명시적으로 분리한다. 비로그인 사용자는 /?auth=required&next=...로 이동시키고 /post/[postId]는 공개 상태를 유지한다.
TASK-003 app/code-review/page.tsx, src/pages/code-review/index.ts, src/pages/code-review/ui/code-review.tsx를 삭제하고 src/widgets/header/ui/header.tsx, src/widgets/header/ui/mobile-nav.tsx, app/sitemap.ts, src/pages/home/ui/home.tsx, src/widgets/sidebar/ui/welcome-card.tsx를 정리한다. 코드 리뷰 탭, 홈 로그인 배너, /code-review 사이트맵 엔트리를 제거한다.

Implementation Phase 2

  • GOAL-002: 홈 피드를 TODAY 중심 구조와 하루 1글 작성 흐름으로 전환한다.
Task Description Completed Date
TASK-004 app/today/page.tsx, src/pages/today/index.ts, src/pages/today/ui/today.tsx, src/pages/home/ui/today-section.tsx를 추가하고 src/pages/home/ui/home.tsx, src/pages/home/ui/home-feed-infinite-list.tsx를 수정한다. TODAY는 최대 10개를 노출하고, 미작성 사용자에게 blur 오버레이와 기록하러 가기 CTA를 보여주며, /today는 오늘 작성자에게만 허용한다.
TASK-005 src/features/post-list/api/post-list.action.tssrc/entities/post/api/post.service.tsgetTodayPostListAction, getNonTodayPostListPageAction, hasUserPostedTodayAction, getTodayPostByUserId를 추가한다. 오늘 범위 계산은 클라이언트가 보낸 로컬 날짜 범위를 기준으로 처리하고, 같은 날짜 안에서는 팔로잉 사용자를 우선 정렬한다.
TASK-006 src/widgets/create-post/ui/create-post-form.tsx, src/features/post-interaction/model/post.schema.ts, src/features/post-interaction/ui/post-dialog.tsx, src/entities/post/api/post.action.ts, src/pages/profile/ui/profile.tsx를 수정한다. description 입력을 추가하고, UI 작성은 기본적으로 authoring_mode = "hand_written"를 저장하며, 하루 1글 제한과 오늘 글 편집 진입을 공통 컴포넌트에서 처리한다.

Implementation Phase 3

  • GOAL-003: 게시글 모델, 댓글 경험, Logan 자동화를 v2 스펙에 맞게 교체한다.
Task Description Completed Date
TASK-007 supabase/migrations/20260325100000_codelog_v2_core.sql을 생성하고 src/shared/types/database.types.ts를 갱신한다. 이 마이그레이션은 posts.description, posts.authoring_mode, 체크 제약, Logan 시스템 유저, 웹훅 준비 로직을 추가하고 posts.is_review_enabled를 제거해야 한다.
TASK-008 src/shared/types/types.ts, src/entities/post/api/post.interface.ts, src/entities/post/api/post.service.ts, src/features/post-list/api/post-list.action.ts, src/features/post-view/api/post-view.action.ts, src/entities/comment/api/comment.service.ts를 수정한다. descriptionauthoring_mode를 읽고 쓰도록 바꾸고, soft delete 제외 일일 작성 제한을 서버에서 검증하며, is_review_enabled 기반 분기를 제거한다.
TASK-009 src/widgets/post-card/ui/post-card.tsx, src/widgets/post-card/ui/post-header.tsx, src/widgets/post-card/ui/post-actions.tsx, src/widgets/post-card/ui/post-code-section.tsx, src/pages/post-detail/ui/post-detail.tsx, app/post/[postId]/page.tsx, src/features/comment/ui/comment-item.tsx, src/features/comment/ui/review-comment.tsx를 수정한다. 카드 본문은 말풍선 형태의 description으로 바꾸고, AI Assisted 또는 Hand-Written 배지를 항상 표시하며, Logan 댓글에는 Bot 전용 스타일을 부여하고 모든 코드 스니펫에서 인라인 코멘트를 활성화한다.
TASK-010 supabase/functions/logan-comment/index.tssupabase/functions/logan-comment/prompt.ts를 생성한다. Edge Function은 게시글 description, content, code를 읽어 Gemini 3.1 Flash-Lite로 200자 이하 한국어 댓글을 생성하고, 동일 post_id에 Logan 댓글이 이미 존재하면 중복 삽입을 중단해야 한다.

Implementation Phase 4

  • GOAL-004: 실험 계측, SEO, 테스트를 완료해 v2 론치 가능한 상태로 만든다.
Task Description Completed Date
TASK-011 src/shared/lib/posthog/client.ts, src/features/post-interaction/ui/post-dialog.tsx, src/widgets/create-post/ui/create-post-form.tsx, src/pages/home/ui/today-section.tsx, src/pages/today/ui/today.tsx를 수정해 today_module_viewed, today_cta_clicked, post_dialog_opened, post_dialog_closed, post_create_submitted, post_created를 정의된 속성으로 캡처한다. authoring_mode, content_length, description_length, time_to_submit_ms, gate_state, source, experiment_key, variant를 누락 없이 전송한다.
TASK-012 app/layout.tsx, app/manifest.ts, app/sitemap.ts, app/robots.ts, app/post/[postId]/page.tsx를 수정해 랜딩 메타데이터를 v2 메시지로 교체하고, 상세 페이지는 description 기반 OG 및 JSON-LD Article을 검토한다. 더 이상 존재하지 않는 /code-review URL은 크롤링 대상에서 제거한다.
TASK-013 src/entities/post/api/post.service.test.ts, src/entities/post/api/post.action.test.ts, src/entities/comment/api/comment.service.test.ts, src/features/comment/ui/comment-item.test.tsx, src/shared/lib/date.test.ts를 보강하고 수동 검증 체크리스트를 문서화한다. 검증 범위는 로컬 날짜 기준 하루 1글 제한, 공개 상세 페이지, TODAY 잠금 해제, Logan 1회 생성, PostHog exposure 이벤트, 삭제 후 재작성 허용이다.

3. Alternatives

  • ALT-001: /home 피드를 계속 공개하고 상단 로그인 배너만 유지하는 안을 검토했으나, v2의 랜딩 중심 가입 전환 전략과 TODAY 잠금 구조를 만족하지 못해 선택하지 않았다.
  • ALT-002: Logan을 별도 애플리케이션 서버나 Cron Worker로 구현하는 안을 검토했으나, 현재 저장소는 Supabase 중심 구조이고 추가 인프라를 도입할 이유가 부족해 선택하지 않았다.
  • ALT-003: is_review_enabled를 유지한 채 인라인 코멘트를 확장하는 안을 검토했으나, v2 문서가 코드 리뷰 문맥 자체를 제거하고 모든 코드 스니펫을 동일하게 취급하므로 선택하지 않았다.
  • ALT-004: 하루 1글 제한을 서버 UTC 기준으로 구현하는 안을 검토했으나, 기획서가 클라이언트 로컬 타임존 기준을 요구하므로 선택하지 않았다.

4. Dependencies

  • DEP-001: Supabase SQL 마이그레이션 권한과 create_post_with_tags, update_post_with_tags RPC 정의 수정 권한이 필요하다.
  • DEP-002: Supabase Edge Function 런타임과 Database Webhook 구성이 필요하다.
  • DEP-003: Gemini 3.1 Flash-Lite 호출용 비밀키를 Supabase Edge Function secret으로 저장해야 한다.
  • DEP-004: PostHog 프로젝트에서 TODAY 실험용 experiment_key와 variant 구성이 준비되어야 한다.
  • DEP-005: Logan 시스템 유저에 사용할 고정 UUID 00000000-0000-0000-0000-000000000001이 운영 데이터와 충돌하지 않아야 한다.

5. Files

  • FILE-001: app/page.tsx, app/layout.tsx, src/pages/landing/index.ts, src/pages/landing/ui/landing.tsx, src/pages/landing/ui/vertical-marquee.tsx, src/pages/landing/model/mock-posts.ts
  • FILE-002: src/proxy.ts, src/shared/lib/supabase/middleware.ts, src/shared/lib/auth.ts, src/features/auth/api/require-auth.ts
  • FILE-003: app/today/page.tsx, src/pages/today/index.ts, src/pages/today/ui/today.tsx, src/pages/home/ui/today-section.tsx, src/pages/home/ui/home.tsx, src/pages/home/ui/home-feed-infinite-list.tsx
  • FILE-004: src/widgets/create-post/ui/create-post-form.tsx, src/features/post-interaction/model/post.schema.ts, src/features/post-interaction/ui/post-dialog.tsx, src/entities/post/api/post.action.ts, src/pages/profile/ui/profile.tsx
  • FILE-005: src/entities/post/api/post.interface.ts, src/entities/post/api/post.service.ts, src/features/post-list/api/post-list.action.ts, src/features/post-view/api/post-view.action.ts, src/shared/types/types.ts
  • FILE-006: src/widgets/post-card/ui/post-card.tsx, src/widgets/post-card/ui/post-header.tsx, src/widgets/post-card/ui/post-actions.tsx, src/widgets/post-card/ui/post-code-section.tsx
  • FILE-007: app/post/[postId]/page.tsx, src/pages/post-detail/ui/post-detail.tsx, src/pages/post-detail/ui/post-detail-comments-infinite-list.tsx
  • FILE-008: src/features/comment/ui/comment-item.tsx, src/features/comment/ui/review-comment.tsx, src/features/comment/ui/comment-form.tsx, src/entities/comment/api/comment.service.ts
  • FILE-009: src/widgets/header/ui/header.tsx, src/widgets/header/ui/mobile-nav.tsx, app/sitemap.ts, app/manifest.ts, app/robots.ts
  • FILE-010: src/shared/lib/posthog/client.ts, src/shared/lib/posthog/posthog-provider.tsx
  • FILE-011: supabase/migrations/20260325100000_codelog_v2_core.sql, supabase/functions/logan-comment/index.ts, supabase/functions/logan-comment/prompt.ts
  • FILE-012: src/entities/post/api/post.service.test.ts, src/entities/post/api/post.action.test.ts, src/entities/comment/api/comment.service.test.ts, src/features/comment/ui/comment-item.test.tsx, src/shared/lib/date.test.ts

6. Testing

  • TEST-001: 보호 경로 목록과 공개 경로 목록이 src/shared/lib/supabase/middleware.ts에서 올바르게 분기되는지 단위 테스트 또는 경로 매트릭스로 검증한다.
  • TEST-002: src/entities/post/api/post.service.test.ts에서 description, authoring_mode, TODAY 범위 쿼리, 팔로잉 우선 정렬, is_review_enabled 제거를 검증한다.
  • TEST-003: src/entities/post/api/post.action.test.ts에서 하루 1글 제한, soft delete 후 재작성 허용, 오늘 글 편집 허용을 검증한다.
  • TEST-004: src/features/comment/ui/comment-item.test.tsx에서 Logan Bot 배지와 일반 댓글 구분 스타일을 검증한다.
  • TEST-005: src/shared/lib/date.test.ts에서 로컬 날짜 범위 계산 유틸리티와 TODAY 게이트 계산을 검증한다.
  • TEST-006: 수동으로 /, /home, /today, /post/[postId] 접근 흐름을 확인해 리다이렉트, 토스트, blur 오버레이, 작성 CTA, 상세 공개 상태를 검증한다.
  • TEST-007: Supabase에서 게시글 INSERT 후 Logan Edge Function이 정확히 1회 실행되고, 중복 웹훅 재시도 시 추가 댓글이 생성되지 않는지 검증한다.
  • TEST-008: PostHog 대시보드에서 today_module_viewed가 실제 viewport 노출 시점에만 들어오고, 후속 post_create_submitted, post_created와 동일 experiment_keyvariant를 공유하는지 검증한다.

7. Risks & Assumptions

  • RISK-001: 클라이언트가 전송한 로컬 날짜 범위가 잘못되면 하루 1글 제한이 우회되거나 과잉 차단될 수 있다. 서버는 ISO 문자열 형식을 검증하고 허용 범위를 제한해야 한다.
  • RISK-002: 기존 게시글은 description이 비어 있을 수 있다. 마이그레이션 직후 상세 SEO와 카드 렌더링이 깨지지 않도록 백필 전략 또는 안전한 fallback이 필요하다.
  • RISK-003: Logan 웹훅이 재시도되면 중복 댓글이 생길 수 있다. post_id + bot_user_id 기준의 중복 차단 로직이 필수다.
  • RISK-004: TODAY 실험에서 exposure 시점을 잘못 잡으면 A/B 결과가 왜곡된다. 단순 렌더 시점이 아니라 viewport 진입 시점에만 today_module_viewed를 기록해야 한다.
  • ASSUMPTION-001: 신규 페이지 모듈 src/pages/landing/*src/pages/today/*를 추가해도 현재 빌드 구조와 alias 설정이 그대로 동작한다.
  • ASSUMPTION-002: Supabase Edge Function에서 Gemini 3.1 Flash-Lite를 호출할 수 있는 네트워크 및 시크릿 구성이 가능하다.
  • ASSUMPTION-003: Logan Bot 아바타 이미지 경로와 Bot badge 디자인 자산은 프런트엔드에서 신규 추가가 가능하다.
  • ASSUMPTION-004: PostHog 프로젝트가 이미 연결되어 있고, 신규 이벤트명과 실험 키를 추가해도 기존 대시보드와 충돌하지 않는다.

8. Related Specifications / Further Reading

  • Obsidian 원문 기획서: /Users/parkblo/Desktop/Bault/05 Atomic Notes/CodeLog v2 기획서.md
  • 현재 서비스 엔트리 파일: app/page.tsx, src/pages/home/ui/home.tsx, src/features/post-interaction/ui/post-dialog.tsx
  • 현재 인증 게이트 파일: src/proxy.ts, src/shared/lib/supabase/middleware.ts, src/features/auth/api/require-auth.ts
  • 현재 게시글/댓글 도메인 파일: src/entities/post/api/post.service.ts, src/entities/comment/api/comment.service.ts

Metadata

Metadata

Assignees

Labels

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions