
회원 기능을 구현하려면 세 가지 주요 방식을 선택할 수 있습니다.
첫 번째는 쿠키(cookie), 두 번째는 세션(session), 그리고 세 번째는 JWT(Json Web Token)를 이용한 토큰 방식입니다.
또한, 구글이나 페이스북 계정을 활용한 OAuth 방식도 많이 사용되지만,
이번 글에서는 쿠키, 세션, JWT의 기본 동작 원리와 차이점을 중심으로 정리해 보겠습니다. 😊
01
Http? Https?
회원 인증을 할 때 사용하는 쿠키, 세션, JWT 같은 방식은 결국 브라우저(클라이언트)와 서버가 정보를 주고받는 규칙 위에서 작동합니다. 이 규칙을 정하는 게 바로 HTTP와 HTTPS입니다.
HTTP (HyperText Transfer Protocol)
HTTP는 브라우저와 서버가 서로 대화할 수 있는 기본 규칙이에요.
예를 들어, 브라우저에 어떤 주소(URL)를 입력하면 서버에 요청을 보내고, 서버는 "이거 가져가세요!" 하며 데이터를 보냅니다.
하지만 HTTP에는 큰 단점이 하나 있는데요, 바로 **"상태를 기억하지 못한다"**는 점입니다.
즉, 사용자가 로그인 후 새로고침을 하면 서버는 "이 사람이 누구였더라?" 하고 기억을 잃어버리는 거죠. 😅
HTTPS (HyperText Transfer Protocol Secure)
HTTPS는 HTTP에 보안(SSL/TLS)을 추가한 버전입니다.
데이터를 암호화해서 보내기 때문에 누군가 중간에서 정보를 엿보거나 가로채는 것을 막아줍니다.
특히 HTTPS는 쿠키, 세션, JWT 같은 민감한 정보를 안전하게 보호할 수 있어요.
" 쉽게 비유하자면 "
- HTTP는 공연장에서 관객의 티켓만 확인하는 일반 입구와 같아요.
티켓은 평문으로 작성돼 있어서 누군가 복사하면 쉽게 도용될 수 있습니다. - HTTPS는 같은 입구에 보안 스캐너를 추가한 모습입니다.
스캐너 덕분에 티켓 내용이 암호화되고, 도용이나 복제를 막을 수 있어요.
하지만 여전히 이 입구는 "관객이 이전에 들어왔던 사람인지"를 기억하지 못한다는 점은 같답니다.
" 쿠키, 세션, JWT를 왜 써야 할까요? "
HTTP는 본질적으로 "상태를 기억하지 않는(stateless)" 프로토콜입니다.
서버는 이전 요청과 이후 요청이 같은 사용자인지 알 방법이 없어요.
예를 들어, 사용자가 로그인했다고 하더라도 다음 요청에서는 "이 사용자가 누구인지" 다시 확인할 방법이 없습니다.
이 문제를 해결하기 위해 우리는 쿠키, 세션, JWT 같은 인증 기술을 사용합니다.
쿠키 (Cookie)
쿠키는 브라우저(클라이언트)에 저장되는 작은 데이터 조각입니다.
쉽게 말해, 서버가 브라우저에게 "이걸 기억해 둬!" 하고 전달하는 메모와 같은 역할을 합니다.
브라우저는 이 쿠키를 저장해 두었다가, 서버와 다시 통신할 때 쿠키를 자동으로 포함해 보냅니다.
쿠키는 공연장 입구에서 받는 종이 입장권과 같습니다.
" 어떻게 작동할까? "
- 사용자가 서버에 요청을 보냅니다.
- 서버가 "너는 누구인지 알려줄게!" 하며 쿠키를 전달합니다.
- 브라우저는 이 쿠키를 저장합니다.
- 이후 서버에 요청할 때, 브라우저는 쿠키를 포함해 다시 보냅니다.
- 서버는 쿠키를 확인하고 "아, 이 사람 OOO구나!" 하고 기억합니다.
하지만 티켓을 잃어버리거나 누군가 복사하면 문제가 생길 수 있습니다.
세션 (Session)
세션은 서버가 관리하는 사용자 정보입니다.
클라이언트가 서버와 연결된 동안, 서버는 사용자의 정보를 메모리에 저장해 두고 관리합니다.
이때, 서버는 클라이언트에게 세션 ID라는 것을 발급하며, 클라이언트는 요청마다 이 ID를 서버에 전달합니다.
세션은 공연장에서 받는 VIP 팔찌와 같습니다.
" 어떻게 작동할까? "
- 사용자가 서버에 로그인 요청을 보냅니다.
- 서버가 "VIP로 기록했어!" 하며 세션 ID를 발급합니다.
- 클라이언트는 세션 ID를 저장하고 요청할 때마다 함께 보냅니다.
- 서버는 세션 ID를 확인하고, 사용자를 인증합니다.
하지만 팔찌 정보를 공연장(서버)에서 관리하니 관리 비용이 좀 듭니다.
JWT (Json Web Token)
JWT는 사용자의 정보를 담고 있는 디지털 토큰입니다.
이 토큰은 JSON 형식으로 암호화되어 있으며, 서버가 별도로 저장할 필요가 없습니다.
즉, JWT는 요청 시 포함된 정보만으로 사용자를 인증할 수 있어요.
JWT는 공연장에서 받은 QR 코드 티켓과 같습니다.
" 어떻게 작동할까? "
- 사용자가 서버에 로그인 요청을 보냅니다.
- 서버는 사용자의 정보를 담은 JWT를 만들어 클라이언트에게 전달합니다.
- 클라이언트는 이 JWT를 저장하고, 요청마다 서버에 함께 보냅니다.
- 서버는 JWT를 확인하고 사용자를 인증합니다.
하지만 QR 코드가 유효 기간 동안 노출되면, 다른 사람이 복사해서 사용할 수 있는 위험이 있습니다.
JWT 토큰 구성
토큰은 헤더(Header), 페이로드(Payload), 서명(Signature) 세 가지로 구성되어 있습니다.

헤더 (Header)
헤더는 "이 토큰이 어떤 종류인지"를 알려주는 역할을 합니다.
이 정보는 JSON 형태로 작성되며, Base64 URL로 인코딩 됩니다.
비유하자면, 상자에 붙은 라벨 같은 역할을 한다고 볼 수 있어요.
{
"alg": "HS256",
"typ": "JWT"
}
페이로드 (Payload)
페이로드는 실제로 전달할 정보를 담고 있는 부분입니다.
예를 들어, 사용자 이름, 권한, 토큰의 유효기간(exp) 같은 데이터를 포함할 수 있습니다.
이 부분은 상자 안에 들어 있는 내용물로 생각하시면 이해하기 쉽습니다.
{
"sub": "1234567890",
"name": "John Doe",
"admin": true
}
서명 (Signature)
서명은 헤더와 페이로드를 합친 뒤, 비밀 키로 암호화한 값입니다.
쉽게 말해, 자물쇠 역할을 하는데요, 누군가 내용을 바꾸려고 하면 자물쇠가 안 맞아서 바로 알 수 있습니다.
HMACSHA256(
base64UrlEncode(header) + "." + base64UrlEncode(payload),
secret
)
쿠키, 세션, JWT의 특징 요약
아래는 쿠키, 세션, JWT의 특징을 간단히 비교한 표입니다.
각각의 장단점을 잘 파악해 프로젝트 상황에 맞게 사용해 보세요!
특징 | 쿠키 | 세션 | JWT |
저장 위치 |
클라이언트 | 서버 + 클라이언트 | 클라이언트 |
정보 저장 방식 | 클라이언트에 직접 저장 | 서버에 저장, 클라이언트는 세션 ID만 가짐 |
클라이언트 토큰에 모든 정보 포함 |
보안성 | 비교적 낮음 (도청, 복제 위험 있음) |
서버가 관리하므로 보안성 높음 | 보안 설정에 따라 위험 가능 (디코딩 쉬움) |
처리 속도 | 빠름 | 상대적으로 느림 | 매우 빠름 |
장점 | 클라이언트에서 간단히 관리 가능 | 서버 관리로 보안이 뛰어남 | 서버 부담 적고 확장성이 뛰어남 |
브라우저에서 자동으로 전송 | 상태를 유지하기 쉬움 | 자체 정보 포함으로 빠른 인증 가능 | |
단점 | 보안 취약점 (예: CSRF, XSS 등)이 있음 |
서버에 저장 공간 부담 | 토큰 길이로 데이터 부담 가능 |
클라이언트에서만 정보 유지 가능 |
서버 다운 시 인증 정보 손실 위험 | 한 번 노출되면 도용 위험 있음 |
정리
쿠키
입장권에는 간단한 정보(예: 이름, ID)가 적혀 있습니다.
서버는 요청받을 때 쿠키 정보를 확인해 사용자를 인증하지만, 민감한 정보를 담으면 보안 문제가 생길 수 있어요.
그래서 주로 세션 ID를 저장하는 용도로 많이 사용됩니다.
세션
입장권에는 발급번호(세션 ID)만 적혀 있고, 실제 정보는 서버에 저장됩니다.
서버는 세션 ID를 기반으로 사용자 정보를 찾아 인증하기 때문에, 보안이 뛰어나지만 서버 관리 비용이 발생합니다.
JWT
입장권 자체에 모든 정보를 담고 있는 형태입니다.
서버는 JWT를 읽고, 유효기간만 확인해 인증하기 때문에 확장성이 뛰어나고 처리 속도도 빠릅니다.
하지만 보안 설정을 철저히 하지 않으면 도용될 위험이 있으니 주의가 필요합니다.
프로젝트의 요구사항과 상황에 맞는 방식을 선택하는 것이 가장 중요합니다.
이 글이 선택의 기준을 잡는 데 도움이 되었기를 바랍니다! 😊
'DEVELOPMENT > PROJECT NOTES' 카테고리의 다른 글
잔소리는 많지만 유익한 친구들 ESLint와 Prettier (2) | 2025.02.03 |
---|---|
Context API로 충분한 줄 알았는데... Zustand 써보니 달랐다! (3) | 2024.12.31 |
유저 상태를 Provider로 비비고, Context로 비비자! (7) | 2024.12.26 |
GitHub 로그인 구현? 생각보다 너무 쉽다! (진짜 쉽다…) (3) | 2024.12.19 |
네 구글 로그인이 안전한 이유, 사실은 OAuth 덕분이지 (6) | 2024.12.15 |