결정 기록
✍️ 중요한 결정 기록 (아키텍처 결정 기록) 마지막 업데이트: 2025년 6월 29일
이 문서는 SurfAI 프로젝트를 만들면서 내린 중요한 기술 결정들이 왜 나왔는지, 어떤 다른 생각들이 있었는지, 그리고 왜 최종 결정을 했는지 기록한 것입니다.
1. 로그인 방식: JWT
+ HttpOnly
쿠키 사용하기로 결정
- 날짜: 2025-06-21
- 이야기 나눈 것:
- 처음에는 옛날 방식인 세션-쿠키를 생각했어요.
- 나중에는 더 많은 사람들이 쓰고(확장성) 휴대폰 같은 다른 기기에서도 잘 되도록
JWT
토큰을LocalStorage
에 저장하는 방법을 이야기했어요. - 마지막으로, 보안도 좋고 쓰기도 편하게
JWT
를HttpOnly
쿠키에 넣어서 보내는 방법으로 정했어요.
- 결정:
JWT
(로그인 토큰/새로고침 토큰)를 만들고, 이걸HttpOnly
Secure
쿠키에 담아 사용자에게 보냅니다. - 이유:
- 보안 더 강하게 (XSS 막기):
HttpOnly
덕분에 웹사이트의 프로그램(JavaScript)이 토큰에 직접 접근할 수 없어서, 나쁜 공격(XSS)으로 토큰을 뺏길 위험이 크게 줄어들어요. - 서버가 기억할 필요 없게:
JWT
를 쓰면 서버가 사용자의 로그인 상태를 따로 기억할 필요가 없어서, 나중에 서버를 더 많이 늘려도(확장) 아주 좋아요. - 자동 로그인: 웹사이트 프로그램은
apiClient
에서credentials: 'include'
만 설정하면, 웹 브라우저가 모든 요청에 자동으로 로그인 쿠키를 붙여줘서 프로그램을 관리하기 쉬워요.
- 보안 더 강하게 (XSS 막기):
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.org
와api.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) 같은 복잡한 기능들도 플러그인이나 설정을 통해 쉽게 추가할 수 있어요.
- 살아있는 문서: 모든 문서가 Markdown(