AquilaLog
Stateless인증JWTRefresh Token

Stateless란 무엇인가? (수정 중)

aquila profile image
aquila
2026.04.08 09:36수정 2026.04.16 00:43조회 1
댓글 0조회1

시작하며

백엔드 인증을 처음 배우면 대부분 이런 흐름으로 헷갈립니다.

  • “Stateless가 좋다는데, 왜 좋은 거지?”
  • “세션이랑 JWT는 뭐가 다른 거야?”
  • “JWT 쓰면 로그인 상태가 유지되는 거야?”
  • “Refresh Token은 왜 또 따로 있어?”

처음에는 이렇게 외우기 쉽습니다.

세션 = 서버 저장****토큰 = 클라이언트 저장

하지만 이걸로는 절대 이해가 되지 않습니다.

왜냐하면 중요한건 {{color:#34d399|"어디에"}}{{color:#60a5fa| }}저장하느냐가 아니라

요청을 처리할 때 {{color:#fb923c|"무엇이"}}{{color:#fb923c| }}필요하냐 이기 때문입니다.

이 글에서는 가장 헷갈리는 지점부터 하나씩 이해해보겠습니다.


왜 이 문제가 중요한가

보통 처음 인증을 구현한다면 이런 식으로 할 것 입니다

TXT
로그인 -> 세션 생성 -> 이후 요청에서 세션 확인

이 구조는 아주 직관적이지만 한가지 중요한 질문을 만듭니다.

"서버는 도대체 어떻게 이 사용자가 로그인한 상태인지 아는걸까?"

이 질문에 대한 답은 간단합니다.

👉 {{color:#fb923c|서버가 사용자가 로그인한 상태를 기억}}하고 있기 때문입니다

이게 바로 흔히 말하는 {{color:#fb923c|"Stateful"}} 입니다.

그렇다면 만약 {{color:#60a5fa|서버가 사용자의 로그인한 상태를 기억하지 않는다면}}요?

이게 바로 {{color:#60a5fa|"Stateless"}} 입니다.

Stateless 에서는 서버가 사용자의 로그인한 상태를 기억하지 않습니다.


핵심 개념 설명

1. Stateful (세션 기반)

흐름

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: 로그인
    Server-->>Client: Session ID

    Client->>Server: 요청 + Session ID
    Server->>Server: 세션 조회
    Server-->>Client: 응답

핵심 포인트

  • 서버가 사용자 상태를 기억함
  • 요청마다 “이 사용자가 누구인지” 조회 필요

주니어가 헷갈리는 포인트

“Session ID만 있으면 인증되는 거 아닌가요?”

맞습니다.

하지만 중요한 건 이겁니다.

Session ID는 ‘열쇠’일 뿐이고, 실제 정보는 서버에 있다


2. Stateless (토큰 기반)

이제 반대로 생각해봅니다.

❓ “서버가 기억하지 않으려면?”

👉 답은 하나입니다.

요청 안에 모든 정보를 넣는다


흐름 (JWT)

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: 로그인
    Server-->>Client: JWT 발급

    Client->>Server: 요청 + JWT
    Server->>Server: 토큰 검증
    Server-->>Client: 응답

핵심 포인트

  • 서버는 상태를 저장하지 않음
  • JWT 안에 사용자 정보 포함

JWT 내부 예시

JSON
{  "userId": 123,  "role": "USER",  "exp": 1710000000}

주니어가 헷갈리는 포인트

“그럼 서버는 DB 안 보고도 인증이 가능한 건가요?”

👉 맞습니다.

왜냐하면

토큰 자체가 ‘신분증’ 역할을 하기 때문입니다


그런데 여기서 문제가 생깁니다

JWT 구조를 이해하면 자연스럽게 이런 생각이 듭니다.

❓ “그럼 JWT를 오래 쓰면 로그인 계속 유지되겠네?”

👉 맞습니다.

하지만 동시에 큰 문제가 생깁니다.


문제 1. 토큰 탈취

  • 누군가 JWT를 가져가면?
  • 그대로 로그인 가능

👉 서버는 막을 방법이 없음


문제 2. 로그아웃 불가능

  • 이미 발급된 토큰은 계속 유효

👉 서버가 기억하지 않기 때문


문제 3. 권한 변경 반영 안 됨

  • 유저 권한이 바뀌어도
  • 토큰은 그대로

그래서 등장한 것이 Refresh Token


JWT + Refresh Token 구조

sequenceDiagram
    participant Client
    participant Server

    Client->>Server: 로그인
    Server-->>Client: Access + Refresh

    Client->>Server: API 요청 (Access)
    Server-->>Client: 응답

    Client->>Server: Access 만료 → Refresh 요청
    Server-->>Client: 새 Access 발급

역할 정리

토큰역할
Access TokenAPI 인증
Refresh TokenAccess 재발급

왜 둘로 나누는가

주니어 입장에서 가장 중요한 포인트입니다.

❌ 하나로 해결하려 하면

방식문제
Access 길게보안 위험
Access 짧게로그인 자주 끊김

✅ 그래서 이렇게 나눈다

  • Access → 짧게 (보안)
  • Refresh → 길게 (사용자 경험)

잘못 이해하기 쉬운 부분

1. “Refresh Token도 Stateless다” (❌)

👉 대부분은 서버에 저장합니다

왜?

  • 탈취 대응
  • 로그아웃 처리

2. “JWT 쓰면 서버가 아무것도 안 한다” (❌)

👉 실제로는

  • 서명 검증
  • 만료 확인
  • (경우에 따라) blacklist 체크

3. “토큰에 정보 많이 넣으면 좋다” (❌)

👉 변경 반영 안 됨


구현 예시 (학습용 구조)

로그인

TXT
public Token login(User user) {
String access = createAccessToken(user); // 짧게 String refresh = createRefreshToken(user); // 길게
saveRefreshToken(user.getId(), refresh);
return new Token(access, refresh);}

재발급

TXT
public String reissue(String refreshToken) {
if (!isValid(refreshToken)) { throw new UnauthorizedException(); }
return createAccessToken(getUser(refreshToken));}

이 구조에서 꼭 이해해야 할 포인트

  • Access → 서버 저장 없음 (Stateless)
  • Refresh → 서버 저장 있음 (Stateful)

👉 완전 Stateless는 아니다


운영에서 가장 먼저 터지는 문제들 (학습 관점)

1. “로그아웃했는데 왜 계속 요청이 되지?”

👉 이유

  • Access Token이 아직 살아있음

👉 해결

  • 짧은 TTL

2. “토큰 탈취되면 끝 아닌가요?”

👉 맞습니다 (Access 기준)

👉 해결

  • 짧은 TTL
  • Refresh 관리

3. “왜 Refresh Token까지 DB에 넣어요?”

👉 이유

  • 탈취 대응
  • 강제 로그아웃

4. “Access 만료되면 요청 계속 실패하는데요?”

👉 이유

  • 재발급 로직 없음

👉 해결

  • 자동 refresh 요청

운영 체크리스트 (학습용)

영역점검 항목확인 기준
개념 이해Stateless 의미요청만으로 처리 가능한가
토큰 구조Access/Refresh 구분역할 명확
보안HTTPS 사용필수
저장소Refresh 저장DB/Redis
만료Access 짧게15~60분
흐름재발급 로직구현되어 있는가

마치며

Stateless는 “서버가 아무것도 안 하는 구조”가 아닙니다.

오히려 반대입니다.

“서버가 상태를 덜 들고도 동작하도록 설계를 더 많이 고민하는 구조”

세션, JWT, Refresh Token은 각각 다른 기술이 아니라

“상태를 어디에 둘 것인가”에 대한 선택지 입니다.

그리고 주니어 단계에서 가장 중요한 한 문장은 이것입니다.

Stateless는 기술이 아니라, 요청을 완결시키는 설계 방식이다


참고

목록으로 돌아가기

댓글

댓글 0