성능: API P95 응답시간 0.5초 이내, 일일 배치 1시간 이내
사용자: 첫 주 100명, 한 달 내 2,000명 실사용자
사용성: 모바일 완벽 지원, 토큰 영구 접근성
프로젝트를 시작하기에 앞서 가장 중요하게 생각한 것은 우리 프로젝트 KR에 맞는 적절한 도구 선택이다.
기술 | 장점 | 단점 |
---|---|---|
✅ TypeScript | • 런타임 에러 사전 방지 • 강력한 타입 안정성 | • 컴파일 시간 필요 • 초기 설정 복잡 • 작은 변경에도 빌드 필요 |
JavaScript | • 브라우저 지원 • 빠른 개발 속도 • 유연한 타입 시스템 | • 런타임 에러 발생 위험 • 타입 관련 휴먼 에러 • 대규모 프로젝트시 유지보수 어려움 |
타입 시스템을 통해 응답 형태를 명확히 정의할 수 있어 TypeScript를 선택하였고, 덤으로 프론트 엔드 담당자 분도 TypeScript를 사용 예정이시기에 선택하였다.
기술 | 장점 | 단점 |
---|---|---|
NestJS | • TypeScript 기본 지원 • DI 시스템 • 데코레이터로 코드 간결화 • 내장 가드 | • 상대적으로 무거움 • 필요 이상의 복잡한 설계 위험 |
✅ Express | • 가볍고 빠른 성능 • 간단하고 직관적인 구조 • 풍부한 미들웨어 생태계 • 자유로운 구조 설계 | • 큰 프로젝트시 구조화 필요 • 타입 지원 부가 설정 필요 |
NestJS가 익숙하지만, 프로젝트 규모를 고려했을 때 Express가 더 적합하다고 판단되었다.
Express의 가벼운 특성은 프로젝트의 KR 중 하나인 P95 0.5초 달성에 유리할 것으로 예상되었고, TypeScript 도입으로 타입 지원 문제도 해결할 수 있어 선정하게 되었다. 미들웨어로 유연한 확장은 덤!
기술 | 장점 | 단점 |
---|---|---|
✅ PostgreSQL | • 복잡한 쿼리 처리 우수 • 강력한 트랜잭션 지원 • JSON 데이터 처리 • 확장성 우수 | • 높은 메모리 사용 |
MySQL | • 읽기 작업 성능 우수 • 가벼운 리소스 사용 • 레퍼런스 많음 | • 복잡한 쿼리시 성능 저하 • 큰 데이터 처리시 성능 이슈 |
MongoDB | • 스키마 변경 자유로움 • 비정형 데이터 처리 용이 • 수평적 확장 쉬움 • JSON 형태 저장 | • 트랜잭션 취약 • 데이터 일관성 관리 어려움 |
TimescaleDB | • 시계열 데이터 특화 • PostgreSQL 기능 모두 사용 가능 • 자동 파티셔닝 지원 • 시계열 분석 도구 제공 | • 높은 리소스 사용량 • 상대적으로 높은 비용 |
✅ SQLite3 | • 파일 기반으로 매우 가벼움 • 초기설정 불필요 • 빠른 읽기 성능 • 쉬운 백업/복구 • 무료 사용 | • 동시성 제한 존재 • 대규모 확장 제한 |
초기에는 대중적이고 많이 사용해본 PostgreSQL
, MySQL
, MongoDB
를 중심으로 검토했으나, 추가 요구사항 분석을 통해 다른 DB 옵션들도 함께 평가했다.
주요 고려사항:
1. Django ORM과의 호환성
2. 쿼리 처리 성능
3. 프로젝트 특성을 고려하지 않은 좁은 폭의 DB
최종적으로 PostgreSQL
과 SQLite3
을 주요 후보로 선정했다. PostgreSQL
은 복잡한 쿼리 처리에 강점을 보이며, Django ORM과의 호환성도 좋다. 반면, SQLite3
는 초기 설정이 간편하고 관리가 용이하지만 동시성 제한은 고려해야 할 요소이다.
프로젝트의 특성에 맞춰 적절한 데이터베이스를 선택하는 것이 중요하다는 점을 깨달았다.
단순히 월별 통계나 대쉬보드를 빠르게 보면 좋으니 '빠른 응답을 위해 캐싱을 도입해야겠군' 이라는 생각에 스택 선정 목록에 넣었다. 하지만 일별 배치 처리라는 특성상 실시간성이 크게 중요하지 않고, 테이블 설계와 인덱스 최적화만으로도 충분한 성능을 얻을 수 있을 것이라고 생각된다.
기술 | 장점 | 단점 |
---|---|---|
✅ Session + Cookie | • 안전한 토큰 관리 • 영구 로그인 구현 용이 • HttpOnly로 XSS 방지 | • CSRF 공격 대비 필요 • 세션 저장소 관리 필요 • 다중 서버시 동기화 필요 • 메모리 사용량 증가 • 설정 복잡도 증가 |
localStorage | • 클라이언트 영구 저장 • 간단한 구현 • 브라우저 지원 우수 • 용량 제한 적음 | • XSS 취약성 • 서버 제어 불가 • 보안성 낮음 • 자동 만료 기능 없음 |
멍청하게도 당연히 회원가입을 생각하여 우리 서버에 token을 발급하고 저장하는 로직을 생각했다. velog의 token 을 기반으로 로그인하는 것이거늘..
토큰 관리에서 고려한 핵심 포인트는 보안과 사용자의 편이다.
accessToken을 Session에 저장하고, refreshToken은 HttpOnly Cookie에 저장한다.
접속 시 refresh token의 maxAge 갱신하여 영구 로그인 요구사항과 토큰 만료 관리 문제, 보안성을 높이면서 보안성과 사용자 경험을 모두 충족할 수 있어 선정하게 되었다.
기술 스택 선정은 결국 "우리 프로젝트에 정말 필요한 것이 무엇인가"라는 질문에 대한 답이었습니다. 완벽한 선택은 없겠지만, 현재 단계에서 최적의 판단을 했다고 생각한다.
역시 원래부터 벨로그에 자주 기록하시던 분이라 그런가 글에 체계가 잘 잡혀있어 읽기 편했습니다.
그리고 KPT 사용해볼 생각이 없었는데, 이 글을 보고 나니 괜히 샘이 나서 이번 회고에 KPT를 조금이나마 도입해봤습니다ㅋㅋ
이 글 이전에 쓰신 근황 글까지 포함해서 잘 읽고 갑니다! 😄