# 260212-18.20-kakao-sharing-specs

> **일시**: 2026-02-12 18:20
> **주제**: 카카오톡 공유 미리보기(OG Tag) 및 보안 접근 제어 설계

---

## 1. 개요 (Overview)
*   **목표**: 'Public' 위키 문서를 카카오톡 등으로 공유했을 때, **제목과 요약(Description)이 포함된 Rich Preview**를 제공한다.
*   **제약 사항**:
    *   사용자는 반드시 **로그인**을 해야만 문서의 **본문**을 볼 수 있다. (기존 보안 정책 유지)
    *   크롤러(카카오톡, 슬랙 등)는 자바스크립트를 실행하지 않거나 로그인할 수 없으므로, **Server-Side Rendering (SSR)** 단계에서 메타데이터를 제공해야 한다.

## 2. 아키텍처 설계 (Architecture)

### 2.1. SSR 메타데이터 생성 (`generateMetadata`)
Nest.js (App Router)의 `generateMetadata` 함수는 서버에서 실행되므로, 여기서 문서를 Fetch하여 `<meta>` 태그를 완성한다.

*   **도구**: `firebase-admin` (Server SDK)
    *   Client SDK는 브라우저 중심이라 SSR에서 인증/초기화 이슈가 있을 수 있음.
    *   Admin SDK는 서비스 계정(Service Account)을 사용하여 권한 제약 없이 Firestore에 접근 가능.
*   **로직**:
    1.  URL의 `docId` 파싱.
    2.  Firestore에서 해당 문서 조회.
    3.  **보안 체크**:
        *   `visibility == 'public'`: 제목과 내용(앞부분 100자)을 OG 태그로 설정.
        *   `visibility == 'private'`: "비공개 문서입니다" 또는 "InsuWiki" 기본 타이틀만 노출. (제목 유출 방지)
    4.  메타데이터 반환.

### 2.2. 클라이언트 보안 (Client Security)
*   `page.tsx` 컴포넌트 내부의 **본문 렌더링 로직**은 변경하지 않는다.
*   `useAuth()` 훅을 통한 클라이언트 사이드 인증 체크(`useEffect`)는 그대로 유지된다.
*   **흐름**:
    1.  **크롤러 접속**: 서버에서 HTML(메타태그 포함) 수신 → 미리보기 생성 → 종료. (JS 실행 X)
    2.  **사용자 접속**: 서버에서 HTML 수신 → 브라우저가 JS 실행 → `useAuth` 체크 → (비로그인 시) `/login` 리다이렉트.

## 3. 구현 상세 (Implementation Details)

### 3.1. Firebase Admin 설정
*   `src/lib/firebase-admin.ts` 생성
*   환경 변수: `FIREBASE_SERVICE_ACCOUNT_KEY` (JSON string or base64)
*   (로컬 개발 시에는 Mocking하거나 로컬 에뮬레이터 연결 고려, 배포 시 Vercel Env 설정 필수)

### 3.2. 메타데이터 로직 (Pseudo Code)

```typescript
// src/app/docs/[id]/page.tsx

export async function generateMetadata({ params }: Props): Promise<Metadata> {
  const doc = await getDocumentFromAdminSDK(params.id);

  if (!doc || doc.visibility === 'private') {
    return {
      title: 'InsuWiki - 비공개 문서',
      description: '접근 권한이 필요한 문서입니다.'
    };
  }

  return {
    title: `${doc.title} - InsuWiki`,
    description: doc.content.slice(0, 100),
    openGraph: {
      title: doc.title,
      description: doc.content.slice(0, 100),
      // images: [...] (Optional)
    }
  };
}
```

## 4. 보안 검토 (Security Review)
*   **Q**: 제목이 유출될 위험은 없는가?
    *   **A**: `visibility == 'private'`인 경우, 메타데이터에서도 제목을 숨기도록 로직을 작성하므로 안전하다.
*   **Q**: 본문이 유출될 위험은 없는가?
    *   **A**: `generateMetadata`는 `<head>` 태그만 관여하며, `<body>`의 본문 렌더링은 클라이언트 컴포넌트(`DocumentPage`)에서 `useAuth`로 보호되므로 안전하다. 단, SSR로 본문을 렌더링해서 내려보낸다면 위험하지만, 현재 `DocumentPage`는 `'use client'` 지시어가 있어 클라이언트 렌더링 위주로 동작한다. (추가 확인 필요: `page.tsx`가 Server Component인지 Client Component인지. 현재 `use client`가 최상단에 있다면 Metadata만 서버에서 돌고, 본문은 클라이언트에서 렌더링되므로 안전.)

## 5. 결론
*   이 방식은 보안 요구사항(로그인 필수)을 충족하면서 마케팅 요구사항(카톡 공유 미리보기)을 해결하는 최적의 방안임.
