본문으로 건너뛰기

결정 기록

✍️ 중요한 결정 기록 (아키텍처 결정 기록) 마지막 업데이트: 2025년 6월 29일

이 문서는 SurfAI 프로젝트를 만들면서 내린 중요한 기술 결정들이 왜 나왔는지, 어떤 다른 생각들이 있었는지, 그리고 왜 최종 결정을 했는지 기록한 것입니다.


1. 로그인 방식: JWT + HttpOnly 쿠키 사용하기로 결정

  • 날짜: 2025-06-21
  • 이야기 나눈 것:
    • 처음에는 옛날 방식인 세션-쿠키를 생각했어요.
    • 나중에는 더 많은 사람들이 쓰고(확장성) 휴대폰 같은 다른 기기에서도 잘 되도록 JWT 토큰을 LocalStorage에 저장하는 방법을 이야기했어요.
    • 마지막으로, 보안도 좋고 쓰기도 편하게 JWTHttpOnly 쿠키에 넣어서 보내는 방법으로 정했어요.
  • 결정: JWT (로그인 토큰/새로고침 토큰)를 만들고, 이걸 HttpOnly Secure 쿠키에 담아 사용자에게 보냅니다.
  • 이유:
    • 보안 더 강하게 (XSS 막기): HttpOnly 덕분에 웹사이트의 프로그램(JavaScript)이 토큰에 직접 접근할 수 없어서, 나쁜 공격(XSS)으로 토큰을 뺏길 위험이 크게 줄어들어요.
    • 서버가 기억할 필요 없게: JWT를 쓰면 서버가 사용자의 로그인 상태를 따로 기억할 필요가 없어서, 나중에 서버를 더 많이 늘려도(확장) 아주 좋아요.
    • 자동 로그인: 웹사이트 프로그램은 apiClient에서 credentials: 'include'만 설정하면, 웹 브라우저가 모든 요청에 자동으로 로그인 쿠키를 붙여줘서 프로그램을 관리하기 쉬워요.

2. 배포 방식: Docker + Google Cloud Run 사용하기로 결정

  • 날짜: 2025-06-22
  • 이야기 나눈 것:
    • 웹사이트(프론트엔드)를 배포할 때는 쉬운 Cloudflare Pages/Vercel을 생각했어요.
    • 서버(백엔드)를 배포할 때는 GCP의 App Engine(쉬운 서버 관리)과 Compute Engine(직접 서버 관리)을 살펴봤어요.
    • 마지막으로, 웹사이트와 서버 모두 Docker라는 상자에 넣어서 Google Cloud Run에 배포하기로 정했어요.
  • 결정: 웹사이트(Next.js)와 서버(NestJS)를 각각 Docker 상자로 만들고, Google Cloud Run에 배포합니다.
  • 이유:
    • 환경 똑같이: Docker를 쓰면 내 컴퓨터에서 개발하는 환경과 실제 서비스 환경을 100% 똑같이 만들 수 있어요. "내 컴퓨터에서는 됐는데..." 같은 문제가 아예 없어져요.
    • 배포 편하게: Docker 상자는 "웹 배포의 표준"과 같아요. 나중에 AWS, Azure 같은 다른 클라우드 서비스나 우리 서버로 옮겨야 할 때도, 조금만 고치면 바로 옮길 수 있어서 특정 서비스에 묶이지 않아요.
    • 자동 배포 쉽게: 두 프로젝트 모두 "Docker 상자 만들기 -> Cloud Run에 배포"라는 똑같은 자동 배포 과정을 GitHub Actions에서 만들 수 있어서 관리하기 편해요.

3. 주소 나누기: 서브도메인으로 나누기로 결정

  • 날짜: 2025-06-20
  • 이야기 나눈 것:
    • 경로로 나누기 (surfai.org/surfai.org/api/): 하나의 주소를 써서 CORS나 쿠키 문제를 없앨 수 있는 장점이 있었어요. 하지만 앞에 트래픽을 나눠줄 로드밸런서라는 것을 추가로 설정해야 했어요.
    • 서브도메인으로 나누기 (app.surfai.orgapi.surfai.org): 각 서비스의 역할을 분명히 나누고, 따로 관리하기 쉬운 일반적인 방법이에요.
  • 결정: 웹사이트는 surfai.org, 서버는 api.surfai.org처럼 서브도메인으로 나누어 운영합니다.
  • 이유:
    • 처음 설정하는 것이 로드밸런서보다 더 쉽고 간단해요 (Cloud Run의 주소 연결 기능을 사용).
    • 웹사이트와 서버의 역할이 주소에서부터 분명하게 나뉘어서, 각 서비스에 맞는 보안 규칙(방화벽, 캐싱 등)을 적용하기 쉬워요.
    • 복잡했던 다른 주소 간 쿠키 문제는, 서버에서 sameSite: 'none', domain: 'surfai.org'처럼 올바른 쿠키 설정을 해서 해결했어요.

4. 데이터 보관 규칙: 파일은 자동 삭제, 정보는 계속 보관

  • 날짜: 2025-06-23
  • 이야기 나눈 것:
    • 저장 공간 비용을 아끼기 위해 2일이 지난 모든 데이터(파일+데이터베이스 기록)를 지우는 방법을 생각했어요.
    • 하지만 이렇게 하면 사용자가 예전에 작업했던 기록(어떤 글을 썼는지, 어떤 설정을 했는지 등)을 영원히 잃어버려서 사용자가 불편할 수 있다고 걱정했어요.
  • 결정: 실제 이미지/동영상 파일은 2일 뒤 Cloudflare R2에서 자동으로 지우지만, 생성 기록 정보(데이터베이스 기록)는 사용자가 직접 지우기 전까지 계속 보관합니다.
  • 이유:
    • 가장 많은 공간을 차지하는 파일만 지워서 저장 공간 비용을 효과적으로 아낄 수 있어요.
    • 사용자는 자신의 "기록" 페이지에서 예전 작업의 자세한 정보(어떤 글을 썼는지 등)를 계속 볼 수 있어서 사용하기 편해요.
    • 웹사이트에서는 기간이 지난 파일에 대해 "기간 만료"라고 보여줘서 사용자에게 분명하게 알려줘요.

5. 문서 시스템: Docusaurus 사용하기로 결정

  • 날짜: 2025-07-07
  • 이야기 나눈 것:
    • 처음에는 GitHub Wiki나 간단한 README.md 파일로 문서를 관리하는 것을 생각했어요.
    • 더 체계적으로 관리하기 위해 GitBook 같은 외부 서비스도 알아봤어요.
    • 마지막으로, 프로그램 코드와 문서를 같은 곳에서 관리하고, React로 쉽게 고칠 수 있는 Docusaurus를 쓰기로 정했어요.
  • 결정: 프로젝트의 공식 문서 도구로 Docusaurus를 사용하고, surfai-docs라는 이름으로 따로 관리합니다.
  • 이유:
    • 살아있는 문서: 모든 문서가 Markdown(.md, .mdx) 파일로 되어 있어서, 프로그램 코드와 함께 Git으로 관리할 수 있어요. 이렇게 하면 코드와 문서가 항상 최신 상태로 유지되어 좋아요.
    • 개발자에게 편하게: 개발자들은 익숙한 Markdown으로 문서를 쓰고, 필요하면 React 프로그램을 문서 안에 바로 넣어서(MDX) 더 재미있는 문서를 만들 수 있어요.
    • 누구나 쉽게 볼 수 있게: 만들어진 문서는 일반 웹사이트라서, 개발자가 아닌 사람들도 특별한 프로그램 없이 웹 브라우저로 항상 최신 문서를 쉽게 보고 찾을 수 있어요.
    • 기능 확장하기 쉬움: 여러 나라 언어 지원, 문서 버전 관리, 검색 기능(Algolia) 같은 복잡한 기능들도 플러그인이나 설정을 통해 쉽게 추가할 수 있어요.