로그인

이지예·2026년 4월 28일

개발

목록 보기
8/58

세션 로그인 vs JWT 로그인 — Spring & React 완전 정리

핵심 질문 하나로 전부 이해하기
"로그인 상태를 누가 기억하나?"


📌 목차

  1. 핵심 차이 — stateful vs stateless
  2. 세션 방식 — 서버가 기억
  3. 쿠키 vs 세션 스토리지 — 헷갈리는 개념 정리
  4. JWT 방식 — 클라이언트가 증명서를 들고 다님
  5. React에서 세션 로그인 쓸 수 있나요?
  6. 최종 비교 정리

1. 핵심 차이 — stateful vs stateless

세션 방식JWT 방식
상태 보관 주체서버클라이언트
서버 특성Stateful (상태를 기억)Stateless (상태를 기억 안 함)
브라우저 저장쿠키 (JSESSIONID)쿠키 또는 localStorage

2. 세션 방식 — 서버가 기억

🔄 흐름

① 브라우저  →  서버        : ID/PW 전송
② 서버                     : 세션 생성 후 세션 저장소(메모리/DB)에 저장
③ 서버      →  브라우저    : Set-Cookie: JSESSIONID=abc123
④ 브라우저  →  서버        : 이후 모든 요청에 쿠키 자동 첨부
⑤ 서버                     : 세션 저장소에서 abc123 조회 → 사용자 확인

쿠키는 단순한 "열쇠(ID)" 만 전달
실제 사용자 정보는 서버 세션 저장소

Spring 설정 예시

// Spring Security + 세션 (기본 설정)
@Configuration
public class SecurityConfig {
    http.sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED); // 세션 사용
}

3. 쿠키 vs 세션 스토리지 — 헷갈리는 개념 정리

  • HTTP 헤더(Cookie:)로 자동 전송되는 저장소
  • 서버와 브라우저 양쪽에서 설정 가능
  • 만료일 설정 가능 (영구 보관 가능)
  • 세션 로그인에서는 JSESSIONID 를 쿠키에 담아 전달

📦 세션 스토리지 (SessionStorage)

  • 브라우저 탭을 닫으면 사라지는 JS 전용 임시 저장소
  • HTTP 헤더에 자동으로 붙지 않음 → 서버로 자동 전송되지 않음
  • 세션 로그인(서버 세션)과는 이름만 비슷하고 직접 관계 없음

요약: 세션 로그인 = 서버 세션 + 쿠키(JSESSIONID) 조합입니다.
브라우저 세션 스토리지는 별개의 개념입니다.


4. JWT 방식 — 클라이언트가 증명서를 들고 다님

🔄 흐름

① 브라우저  →  서버        : ID/PW 전송
② 서버                     : JWT 생성·서명 (DB 저장 없음)
③ 서버      →  브라우저    : JWT 반환 (Header.Payload.Signature)
④ 브라우저                 : localStorage 또는 HttpOnly 쿠키에 저장
⑤ 브라우저  →  서버        : Authorization: Bearer eyJ... 헤더에 첨부
⑥ 서버                     : 서명 검증만으로 인증 완료 (DB 조회 없음)

JWT Payload 안에 사용자 ID, 권한, 만료시간 등이 이미 들어있습니다.
서버는 이 내용을 저장하지 않고, 서명(Signature)만 검증합니다.

JWT 구조

eyJhbGciOiJIUzI1NiJ9   ← Header  (알고리즘 정보)
.eyJ1c2VySWQiOjF9      ← Payload (사용자 정보, Base64 인코딩)
.SflKxwRJSMeKKF2QT4fw  ← Signature (서버 비밀키로 서명)

Spring 설정 예시

// Spring Security + JWT 필터
public class JwtAuthFilter extends OncePerRequestFilter {
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain) throws ServletException, IOException {

        String token = extractToken(request); // Authorization 헤더에서 꺼냄

        if (token != null && jwtUtil.validate(token)) { // 서명 검증만 — DB 조회 없음
            setAuthentication(token);
        }

        chain.doFilter(request, response);
    }
}

5. React에서 세션 로그인 쓸 수 있나요?

CORS 설정이 필요

세션 방식의 핵심은 쿠키가 자동으로 붙는 것인데,
React SPA는 보통 localhost:3000, Spring 서버는 localhost:8080 — Cross-Origin(다른 출처) 상황

Cross-Origin에서는 쿠키가 기본적으로 차단

해결 방법 — 양쪽 설정 필수

React 쪽 (axios)

// withCredentials: true — 크로스 오리진에서도 쿠키 허용
axios.post('http://localhost:8080/login', data, {
  withCredentials: true
})

// 또는 전역 설정
axios.defaults.withCredentials = true;

Spring 쪽

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:3000") // ← * 사용 불가, 정확한 origin 지정
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowCredentials(true); // ← 이 설정 필수
    }
}

allowCredentials(true) 와 allowedOrigins("*") 는 함께 쓸 수 없습니다.
반드시 정확한 origin을 명시해야 합니다.


6. 최종 비교 정리

항목세션 방식JWT 방식
상태 보관서버 (DB/메모리)클라이언트 (토큰)
브라우저 저장쿠키 (JSESSIONID)쿠키 또는 localStorage
서버 부하매 요청마다 세션 조회서명 검증만
로그아웃서버 세션 삭제 → 즉시 무효화토큰 만료까지 대기 (블랙리스트 별도 관리)
확장성세션 저장소 공유 필요 (Redis 등)서버 어디서든 검증 가능
React + SpringCORS + withCredentials 설정 필요Authorization 헤더 수동 첨부
보안HttpOnly 쿠키로 XSS 방어 용이토큰 탈취 시 만료 전까지 악용 가능

어떤 걸 선택해야 할까?

  • 단일 서버 + 빠른 구현 → 세션 방식
  • MSA / 서버 여러 대 / 모바일 앱 병행 → JWT 방식
  • React + Spring 신규 프로젝트 → JWT가 일반적 (CORS 설정 단순)

profile
github: @dlwldP

0개의 댓글