개인 프로젝트 API 인증, JWT랑 세션 중 뭐가 나을까요?
와, 이 질문 진짜 많이 하시는 질문이고, 신입 개발자들부터 주니어 개발자들까지 헷갈리는 부분이라 저도 처음 할 때 며칠 고민했던 부분이에요.
솔직히 말씀드리면, '이게 무조건 좋다'라고 단정 짓기는 어려워요.
어떤 상황이냐, 어떤 아키텍처를 지향하느냐에 따라 장단점이 극명하게 갈리기 때문이에요.
근본적인 작동 원리 차이부터 짚어보고, 질문자님이 말씀하신 '소규모 학습/포트폴리오' 목적에 초점을 맞춰서 제가 느낀 점들 위주로 정리해 드릴게요.
--- ###
핵심 원리 차이: 상태(State) 관리의 유무 가장 중요한 차이점은 **'상태 관리(State Management)'**에 있어요.
1.
세션 기반 인증 (Session-based Authentication) * 원리: 서버가 사용자를 기억하는 방식이에요.
- 사용자가 로그인하면, 서버는 자체적으로 세션 ID를 발급하고, 이 세션 정보를 서버 메모리나 별도의 저장소(Redis 같은 인메모리 DB)에 저장합니다.
- 클라이언트(프론트엔드)는 이 세션 ID를 쿠키(Cookie) 형태로 받아 서버에 요청할 때마다 함께 보냅니다.
- 핵심: 서버가 세션 ID를 받으면, "아, 이 ID는 이 사용자(User ID)와 연결되어 있구나" 하고 서버 내부 저장소에서 사용자 정보를 조회합니다.
(서버가 상태를 유지함) * 장점: 로그아웃 처리가 매우 직관적이에요.
서버에서 세션만 삭제하면 그 사용자는 즉시 로그아웃되는 효과를 볼 수 있어요.
- 단점: **서버 의존성(Stateful)**이 생깁니다.
서버가 다운되거나, 여러 대의 서버(Scale-out)로 늘리려면 세션 관리를 중앙화(Sticky Session 또는 Redis 사용)하는 복잡한 과정이 필요해요.
이게 아키텍처를 복잡하게 만듭니다.
2.
JWT (JSON Web Token) * 원리: 사용자 정보를 담은 '표(Token)'를 클라이언트에게 넘겨주는 방식이에요.
- 사용자가 로그인하면, 서버는 사용자 정보(User ID, 권한 등)를 암호화하여 JWT를 생성하고, 이 토큰을 클라이언트에게 보냅니다.
- 클라이언트는 이 토큰을 요청 시마다 헤더(Authorization: Bearer [Token])에 담아 보냅니다.
- 핵심: JWT 자체에 필요한 정보가 담겨있기 때문에, 서버는 요청을 받을 때마다 토큰을 서버 저장소에 조회할 필요가 없습니다. (서버가 상태를 기억하지 않음) * 장점: **무상태성(Stateless)**이 가장 큰 장점이에요.
서버가 토큰만 검증할 수 있다면, 몇 대의 서버로 확장해도 세션 공유 문제가 발생하지 않습니다.
분산 환경에 최적화되어 있죠.
- 단점: 토큰 자체에 유효기간(Expiry)을 설정해야 하고, 만약 토큰 탈취가 발생했을 때 강제 로그아웃(Revoke) 처리가 세션보다 복잡해요.
서버 저장소에 '블랙리스트'를 만들어야 할 때가 생깁니다.
--- ### 🧑
소규모 포트폴리오/학습 목적에 대한 추천 가이드 질문자님의 목적이 '소규모 API, 학습, 포트폴리오'라면, 제가 경험상 조금 더 추천하는 방향과 그 이유를 설명드릴게요.
1순위 추천: JWT (가장 포트폴리오 친화적) 솔직히 말해서, 요즘 채용 시장에서 'API 인증'을 구현했다고 보여줄 때, JWT를 사용해서 백엔드와 프론트엔드(혹은 다른 서비스) 간의 통신을 구현하는 경험이 더 많이 요구되고, 기술적으로도 '현대적인 분산 아키텍처'에 대한 이해도를 보여주기 좋아요.
- 개발 난이도 측면: 초기 구현 난이도는 세션보다 약간 높을 수 있어요.
(JWT 생성, 서명 로직, 만료 시간 처리 등) * 학습/포트폴리오 측면: 이 방식은 '무상태성'이라는 아키텍처적 개념을 이해하고 있다는 걸 보여주기 좋아요.
면접관들이 가장 듣고 싶어 하는 포인트 중 하나예요.
- 실습 포인트: JWT를 사용하면서 'Refresh Token' 개념까지 구현해보면, "토큰 만료 시 재발급 로직"까지 커버했다는 강력한 어필 포인트가 생깁니다.
2순위 추천: 세션 기반 (만약 프론트엔드가 단순하거나, 웹 앱에 집중한다면) 만약 프로젝트가 '풀스택 웹 애플리케이션'처럼, **서버와 클라이언트가 끈끈하게 연결된 느낌의 SPA(Single Page Application)**에 가깝고, API Gateway 같은 복잡한 레이어를 추가할 계획이 없다면 세션도 괜찮습니다.
- 개발 난이도 측면: 초기 구현은 직관적이라 빠를 수 있어요.
(서버가 세션 관리 라이브러리를 제공해주면 매우 편함) * 주의할 점: 나중에 이 프로젝트를 확장해서, 예를 들어 '모바일 앱용 API'나 '외부 연동 API'를 추가하게 되면, 세션 기반은 벽에 부딪힐 가능성이 높아요.
세션은 보통 '특정 도메인'이나 '특정 브라우저'에 묶여있다는 느낌이 강해서요.
--- ###
️ 실무 팁 및 흔한 실수 정리 (이게 제일 중요함) 어떤 방식을 선택하든, 아래는 반드시 염두에 두셔야 할 실무적인 팁들이에요.
1.
비밀 키(Secret Key) 관리 (JWT 공통) JWT를 사용한다면, 토큰에 서명(Signing)할 때 사용하는 **비밀 키(Secret Key)**를 절대 코드에 하드코딩하면 안 돼요.
반드시 환경 변수(process.env.JWT_SECRET)를 통해 로드해야 하고, 이 키가 유출되면 모든 보안이 무너지니, 이 키 관리 프로세스 자체를 포트폴리오에 언급하는 게 좋아요.
2.
Refresh Token 전략 (JWT 필수 고려) JWT는 만료되잖아요.
매번 로그인할 때마다 액세스 토큰(Access Token)을 재발급받게 하는 건 번거로워요.
실제 서비스에서는 보통 짧은 만료기간의 Access Token과 긴 만료기간의 Refresh Token 두 개를 사용해요.
- 로그인 성공 시: Access Token + Refresh Token 발급 * 클라이언트가 Access Token 만료 시: Refresh Token을 서버에 보내면, 서버가 검증 후 새로운 Access Token을 발급.
이 로직을 구현하는 것만으로도 인증 시스템에 대한 이해도가 엄청나게 올라갑니다.
3.
권한(Scope) 분리하기 사용자 인증(Authentication)과 권한 부여(Authorization)를 분리해서 생각하세요.
- Authentication: "너 누구니?" (로그인 했니?) $\rightarrow$ 토큰 발급 * Authorization: "너 이거 할 수 있니?" (관리자 권한이 있어?) $\rightarrow$ API 요청 시마다 토큰의 Payload(클레임)에서 권한(
role: 'admin')을 체크해서 처리해야 합니다.
4.
쿠키와 헤더 사용 시 주의점 * 세션/JWT를 쿠키로 전달할 경우: 만약 XSS(Cross-Site Scripting) 공격에 대비하고 싶다면, 쿠키 설정 시 HttpOnly 플래그를 꼭 사용하세요.
이렇게 하면 자바스크립트(JS)로 쿠키에 접근하는 것을 막아주어 보안성이 높아집니다.
- API 통신 시: 프론트엔드가 API를 호출할 때, 토큰을
Authorization: Bearer [Token] 헤더에 담는 게 가장 표준적이고 권장되는 방식입니다.
최종 요약 및 결론 | 구분 | 세션 기반 (Session) | JWT 기반 (Token) | | :--- | :--- | :--- | | 상태 관리 | 상태 저장 (Stateful) - 서버가 기억함 | 무상태 (Stateless) - 토큰 자체에 정보가 담김 | | 확장성 | 어려움 (세션 동기화 필요) | 매우 좋음 (서버 수 늘려도 문제 없음) | | 로그아웃 | 매우 쉬움 (서버에서 세션만 삭제) | 어려움 (블랙리스트 필요) | | 추천 용도 | 전통적인 웹 애플리케이션, 단일 서버 환경 | 마이크로 서비스, 모바일/웹 공통 API (가장 범용적) | | 포트폴리오 추천도 | 보통 | 높음 (현대적 아키텍처 이해도 증명) | 결론적으로, 질문자님의 목표가 **'최신 기술 스택과 아키텍처 이해도를 보여주는 포트폴리오'**라면, JWT를 기반으로 Refresh Token 로직까지 구현해보시는 걸 강력히 추천합니다.
처음에는 구조가 복잡해 보여서 막막할 수 있지만, 이 부분이 API 개발의 '깊이'를 보여주는 핵심 포인트가 될 거예요.
궁금한 점 있으면 또 물어보시고, 꼭 멋진 포트폴리오 완성하시길 응원합니다!
