[FE] 위키 도메인 테크스펙 - 100-hours-a-week/20-real-wiki GitHub Wiki

배경

프로젝트 목표

카카오테크 부트캠프에 등장하는 다양한 인물과 사건들을 정리하고, 사용자가 쉽고 빠르게 정보를 탐색할 수 있도록 위키 시스템을 구현한다.

설계 및 기술 자료

주요 페이지 / 컴포넌트 구조

1. 페이지

  • /wiki/main: 위키 메인 페이지

    • 주요 기능: 위키 검색, 최근 수정된 위키 조회

    • 사용 컴포넌트

      • Input (커스텀한 input 컴포넌트)
      • RecentWikiItem (최근 수정된 위키 아이템)
    • 데이터 로딩 시점

      • 페이지 진입 시 GET /wikis/recentchange API 호출
    • 라우팅

      • /wiki → 사용자가 검색/랜덤 검색 시 → /wiki/search/{searchTerm}
      • /wiki → 사용자가 최근 수정 위키 아이템 클릭 시 → /wiki/{wiki-title}
    • 컴포넌트 배치

  • /wiki/search/{searchTerm}: 위키 검색 리스트 페이지

    • 주요 기능: 검색한 위키 결과 조회

    • 사용컴포넌트

      • Input (커스텀한 input 컴포넌트)
      • WikiSearchDirectLink (검색 문서로 바로 이동)
      • WikiSearchListItem (검색 위키 아이템)
      • LoadingIndicator (무한 스크롤)
    • 데이터 로딩 시점

      • 페이지 진입 시 GET /wikis/list API 호출
      • 검색 결과 페이지네이션. GET /wiki/list API 호출
    • 라우팅

      • /wiki/search/{searchTerm} → 사용자가 각 검색 결과/바로 문서로 가기 버튼 클릭 시 → /wiki/{wiki-title}
    • 컴포넌트 배치

  • /wiki/{wiki-title}: 위키 문서 페이지

    • 주요 기능: 위키에 대한 문서 조회

    • 사용 컴포넌트

      • Input (커스텀한 input 컴포넌트)
      • WikiHeader (위키의 제목, 마지막 편집일 수정 버튼)
      • WikiIndex (위키 목차)
      • MarkdownViewer (위키 마크다운 뷰어)
    • 데이터 로딩 시점

      • 페이지 진입 시 GET /wikis API 호출
    • 라우팅

      • 만약 해당 문서가 없는 경우 → /wiki/{wiki-title} → 새로운 문서 만들기 클릭 시 → /wiki/{wiki-title}/edit
      • 해당 문서가 있는 경우 → /wiki/{wiki-title} → 수정 클릭 시 → /wiki/{wiki-title}/edit
    • 컴포넌트 배치

  • /wiki/{wiki-title}/edit: 위키 생성/수정 페이지

    • 주요 기능
      • 위키 문서 생성/수정
    • 사용 컴포넌트
      • WikiEditor(위키 마크다운 생성/수정)
      • MarkdownViewer (위키 마크다운 뷰어)
    • 라우팅
      • /wiki/{wiki-title}/edit -> 저장 클릭 시 → /wiki/{wiki-title}

2. 주요 컴포넌트

  • WikiEditor
    • 역할: 위키 생성/수정 시 편집기

    • Props & Interface

      interface WikiEditorProps {
      	value: string;
      	onValueChange: (value: string) => void;
      }
      
      • value (required): 마크다운 텍스트
      • onValueChange (required): 값 변경 시 부모에게 알리는 콜백
    • 내부 상태 & 이벤트

      • 텍스트 수정 시 onValueChange(value) 호출
      • 편집 바에 각 버튼 클릭 시 value에 반영
      • 편집 바에서 이미지 삽입 클릭 시 이미지 업로드 팝업(각 OS별 native)
    • 사용 예시

      <WikiEditor
      	value={text}
      	onValueChange={handleTextChange}
      />
      
    • 에러 처리 / 엣지 케이스

      • 최대 10만자 이상 작성 시 입력 제한 및 스낵바 띄움
    • Storybook

      • Default: 일반적인 케이스
  • WikiDocument
    • 역할: 위키 마크다운 문서 렌더링

    • 렌더링 전략

      • 위키 수정/생성 시 미리보기에선 CSR로
      • 위키 문서에선 SSR로 렌더링
    • Props & interface

      interface WikiDocument {
      	content: stirng;
      }
      
      • content (required): 위키 마크다운 텍스트
    • 사용 예시

      <WikiDocument
        content={text}
      />
      
    • Storybook

      • Default: 일반적인 케이스

상태 관리 전략

  • Local State

    • 컴포넌트 내부 상태

      // 위키 생성/편집 텍스트
      const [content, setContent] = useState('');
      
  • Server Cache State

    • 위키 상세 내용 조회 GET /wikis?title={wikiTitle}
      • staleTime: 1분
      • gcTime: 5분
      • 위키 문서 편집 시 캐싱 invalidate
    • 위키 검색 결과 조회 GET /wikis/list
      • staleTime: 1분
      • gcTime: 5분

API 연동

  • 호출할 백엔드 API 목록: (백엔드 테크 스펙 참조)
    • GET /wikis?title={wikiTitle}: 위키 내용 상세 조회
    • GET /wikis/list: 위키 검색 결과 조회
    • POST /wikis : 위키 생성
    • PATCH /wikis/{wikiId}: 위키 수정
  • API 호출 처리
    • fetch API 사용
    • 인터셉터 등의 기능을 사용하기 위해 fetch의 래퍼 함수인 fetcher 사용
    • API 요청/응답 상태에 따른 로딩 인디케이터(Spinner, Skeleton UI) 표시
    • Tanstack Query를 활용하여 중복 호출 방지, 캐시 관리, 자동 재요청 등 처리

라우팅

  • Next.js의 App Router 사용
  • 인가 필요한 페이지 접근 제어(404)

폼 처리 및 유효성 검증

  • 위키 작성 시 10만 자 이상 입력 시 입력 제한

    const MAX_COMMENT_LENGTH = 100000;
    
    const [content, setContent] = useState('');
    
    const handleChange = (e) => {
      const value = e.target.value;
      if (value.length <= MAX_COMMENT_LENGTH) {
        setContent(value);
      }
    };