코딩/sparta TIL

TIL 31 - 1 : Cookie(쿠키), Session(세션)

americanoallday 2025. 3. 31. 16:48

🍪 쿠키를 사용하는 이유

로그인 같은 상태 정보를 유지하기 위해 활용한다.

웹브라우저 쿠키 찾아보기
브라우저 개발자도구(F12) → Application → Cookies
서버에 전송하지 않고 브라우저에 단순히 데이터를 저장하고 싶다면 Web Storage(localStorage, sessionStorage)를 사용하면 된다. 하지만 보안에 취약하기 때문에 주민번호와 같은 민감정보를 저장하면 안된다.

 

동작 방식

더보기

1. Set-Cookie

  • 로그인시 전달된 ID, Password로 User 테이블 조회하여 일치여부 확인
  • 일치한다면 Set-Cookie를 활용해 Cookie에 사용할 값 저장
    • Cookie는 보안에 취약하다.

 

2. 로그인 이후 요청 : Cookie 

  • 로그인 이후에는 모든 요청마다 Request Header에 항상 Cookie 값을 담아서 요청한다.
    • 네트워크 트래픽이 추가적으로 발생된다.
    • 최소한의 정보만 사용해야한다.
  • Cookie에 담겨있는 값으로 인증/인가 를 진행한다.

Cookie Header

1. Set-Cookie : Server에서 Client로 Cookie 전달(Response Header)

2. Cookie : Client가 Cookie를 저장하고 HTTP 요청시 Server로 전달(Request Header)

 

Response 알아보기

set-cookie: 
sessionId=abcd; 
expires=Sat, 11-Dec-2024 00:00:00 GMT;
path=/; 
domain=spartacodingclub.kr;
Secure

 

Cookie의 생명주기

더보기
  1. 세션 Cookie
    • 만료 날짜를 생략하면 브라우저 완전 종료시 까지만 유지된다.(Default)
      • expires, max-age 가 생략된 경우
    • 브라우저를 완전 종료 후 다시 페이지를 방문했을 때 다시 로그인을 해야한다.
  2. 영속 Cookie
    • 만료 날짜를 입력하면 해당 날짜까지 유지한다.
      • expires=Sat, 11-Dec-2024 00:00:00 GMT;
        • 해당 만료일이 도래하면 쿠키가 삭제된다.
      • max-age=3600 (second, 3600초는 한시간. 60 * 60)
        • 0이 되거나 음수를 지정하면 쿠키가 삭제된다.

Cookie의 도메인

더보기
  • 쿠키가 아무 사이트에서나 생기고 동작하면 안된다!
    • 필요없는 값 전송, 트래픽 문제 등이 발생한다.
  • domain=codingclub.kr
    • domain=codingclub.kr를 지정하여 쿠키를 저장한다.
    • dev.codingclub.kr와 같은 서브 도메인에서도 쿠키에 접근한다.
  • domain을 생략하면 현재 문서 기준 도메인만 적용한다.

Cookie의 경로

더보기
  • 1차적으로 도메인으로 필터링 후 Path가 적용된다.
  • 일반적으로 path=/ 루트(전체)로 지정한다.
  • 위 경로를 포함한 하위 경로 페이지만 쿠키에 접근한다.
    • path=/api 지정
      • path=/api/example 가능
      • path=/example 불가능

Cookie 보안

더보기
  1. Secure
    • 기본적으로 Cookie는 http, https 구분하지 않고 전송한다.
    • Secure를 적용하면 https인 경우에만 전송한다. s = Secure
  2. HttpOnly
    • XSS(Cross-site Scripting) 공격을 방지한다.
      • 악성 스크립트를 웹 페이지에 삽입하여 다른 사용자의 브라우저에서 실행되도록 하는 공격
    • 자바스크립트에서 Cookie 접근을 못하도록 막는다.
    • HTTP 요청시 사용한다.
  3. SameSite
    • 비교적 최신 기능이라 브라우저 지원여부를 확인 해야한다.
    • CSRF(Cross-Site Request Forgery) 공격을 방지한다.
      • 사용자가 의도하지 않은 상태에서 특정 요청을 서버에 전송하게 하여 사용자 계정에서 원치 않는 행동을 하게 만든다.
    • 요청 도메인과 쿠키에 설정된 도메인이 같은 경우만 쿠키 전송

Cookie 문제점

1. 쿠키 값은 임의로 변경할 수 있다.

브라우저 개발자도구(F12) → Application → Cookies → 값 수정 가능

 

2. Cookie에 저장된 Data는 탈취되기 쉽다.

 

보안 대처방법

  1. 쿠키에 중요한 값을 저장하지 않는다.
  2. 사용자 별로 일반 유저나 해커들이 알아보지 못하는 값을 노출한다.
    • 일반적으로 암호화된 Token을 쿠키에 저장한다.
    • 서버에서 암호화된 Token과 사용자를 매핑해서 인식한다.
    • Token은 서버에서 관리한다.
  3. 토큰은 해커가 임의의 값을 넣어도 동작하지 않도록 만들어야 한다.
  4. 해커가 토큰을 탈취해도 사용할 수 없도록 토큰 만료시간을 짧게 설정한다.
  5. 탈취가 의심되는 경우 해당 토큰을 강제로 만료시키면 된다.
    • 접속기기 혹은 IP가 다른 경우 등

Session

서버에서 중요한 정보를 보관하며 로그인 연결을 유지하는 방법을 Session 이라고 한다. 앞서 배운 Cookie는 중요한 정보를 Client측에서 보관하고 있는것이다.

1. 로그인 성공
   ↓
2. 서버가 세션을 생성하고, 고유한 세션ID 발급
   ↓
3. 세션ID를 브라우저에 `Set-Cookie`로 심음
   ↓
4. 이후 요청부터 브라우저가 쿠키로 세션ID 자동 전송
   ↓
5. 서버는 세션ID로 사용자 정보 확인 가능

 

Session 생성 순서

  1. 로그인에 성공하면 Server에서 임의로 만든 Session ID를 생성한다.
    • Session ID는 예측이 불가능해야 한다.
    • UUID와 같은 값을 활용한다.
  2. 생성된 Session ID와 조회한 User 인스턴스를 서버의 Session 저장소에 저장한다.
    • 서버에 유저와 관련된 중요한 정보를 저장한다.

 

Session 동작 순서

1. 로그인

  • 상태유지를 위해 Cookie를 사용한다.
    • 서버는 클라이언트에 Set-Cookie: SessionId=임의생성값 을 전달한다.
    • 클라이언트는 Cookie 저장소에 전달받은 SessionId 값을 저장한다.
  • Sessions을 사용하면 유저와 관련된 정보는 클라이언트에 없다.

2. 로그인 이후 요청

  • 클라이언트는 모든 요청에 Cookie 의 SessionId를 전달한다.
  • 서버에서는 Cookie를 통해 전달된 SessionId로 Session 저장소를 조회한다.
  • 로그인 시 저장하였던 Session 정보를 서버에서 사용한다.

 

Session 특징

  1. Session을 사용하여 서버에서 민감한 정보들을 저장한다.
    • 예측이 불가능한 세션 ID를 사용하여 쿠키값을 변조해도 문제가 없다.
    • 세션 ID에 중요한 정보는 들어있지 않다.
    • 시간이 지나면 세션이 만료되도록 설정한다.
    • 해킹이 의심되는 경우 해당 세션을 제거하면 된다.
  2. Session은 특별한것이 아니라 단지 Cookie를 사용하여 클라이언트가 아닌 서버에서 데이터를 저장해두는 방법이다.
  3. Servlet은 Session 을 자체적으로 지원한다.

Servlet의 HttpSession

HttpSession은 자바 서블릿(Servlet) 표준에서 제공하는 인터페이스로

abstract 추상클래스 혹은 interface 로 만들어 상수 값만 사용하도록 만든다.

key-value(키-값) 형태로 저장

 

Servlet을 통해 HttpSession 을 생성하게되면 SessionIdJSESSIONID로 생성되고 JSESSIONID의 Value는 예측 불가능한 랜덤값으로 생성된다

 

HttpServletRequest request

HttpSession session = request.getSession(true) 의미

true → 기존 세션이 없으면 “새로 생성” 
false → null 반환!! ❌ 생성 안 함
// Session의 Default Value는 true이다.
// Session이 request에 존재하면 기존의 Session을 반환하고,
// Session이 request에 없을 경우에 새로 Session을 생성한다.
HttpSession session = request.getSession();

“세션에서 가져온 값이 일부 정보만 갖고 있는데, 내가 넣으려는 클래스는 필드가 더 많은 경우 어떻게 되지?”

public class User {
    private String name;
    private String pw;
    private String email;
}
User user = new User();
user.setName("sun"); // pw, email 없음!

session.setAttribute("loginUser", user);
User sessionUser = (User) session.getAttribute("loginUser");

 

👉 잘 작동하나, 필드 중 값이 없는 것들은 null로 남아있음. 다만 작동 도중 관련 메서드에서 NullpointerException이 터질 수 있어서 관련 null체크 진행 필요

 

Spring의 Session : @SessionAttribute

이미 로그인이 완료된 사용자를 찾는 경우 즉, Session이 있는 경우에 사용한다.

@Controller
@Requiredargsconstructor
public class SessionHomeController {
		private UserService userService;
        
		@GetMapping("/v2/session-home")
        public String homeV2(
            // Session이 필수값은 아니다. 로그인 했거나 안했거나 판별해야하니 required false
            @SessionAttribute(name = Const.LOGIN_USER, required = false) UserResponseDto loginUser,
            Model model
            ) {
            // session에 loginUser가 없으면 Login 페이지로 이동
            if (loginUser == null) {
            return "session-login";
            }
            // Session이 정상적으로 조회되면 로그인된것으로 간주
            model.addAttribute("loginUser", loginUser);
            
            // home 화면으로 이동
            return "session-home";
    	}
}

 

URL이 아닌 Cookie를 통해서만 Session을 유지하고자 한다면?

server.servlet.session.tracking-modes=cookie

 

HttpSession 메서드 정보

  1. session.getId();
    • jsessionId 값을 조회할 수 있다.
  2. session.getMaxInactiveInterval();
    • 세션의 유효시간
    • second 단위 default는 30분(1800초)이다.
  3. session.getCreationTime();
    • 세션 생성시간
    ex) Sat Dec 9 15:40:23 KST 2024
  4. session.getLastAccessedTime();
    • 해당 세션에 마지막으로 접근한 시간
    ex) Sat Dec 9 15:40:23 KST 2024
  5. session.isNew();
    • 새로 생성된 세션인지 여부
  6. session.invalidate();
    • 세션 종료

Session TimeOut

Session의 문제점

더보기
  • HTTP는 Connectionless 특성을 가지고 있어서 서버가 브라우저 종료 여부를 판별하지 못한다.
  • 서버에서 Session을 언제 삭제해야 하는지 판단하기 힘들다.
  • JSESSIONID의 값을 탈취 당한 경우 해당 값으로 악의적인 요청을 할 수 있다.
  • 세션은 서버 메모리에 생성되고 자원은 한정적이기 때문에 꼭 필요한 경우만 생성해야 한다.

ex) 로그인한 유저가 100만명 이라면..?

Session 생명주기

  • 기본적으로 30분을 기준으로 세션을 삭제한다.
  • 실제 로그인 후 30분 이상의 시간동안 사용중인 사용자의 세션 또한 삭제된다.
  • 다시 로그인 해야하는 경우가 발생한다.

HttpSession 사용

  • 세션 생성시점 30분이 아닌 서버에 최근 Session을 요청한 시간을 기준으로 30분을 유지한다.
  • HttpSession은 기본적으로 해당 방식으로 세션의 생명주기를 관리한다.
  • Session 정보에서 LastAccessedTime 을 기준으로 30분이 지나면 WAS가 내부적으로 세션을 삭제한다.

Session의 한계

  • 서버가 DB 혹은 메모리에 저장된 세션 정보를 매번 조회하여 오버헤드가 발생한다.
  • 서버가 상태를 유지해야 하므로 사용자 수가 많아질수록 부담이 커진다.
  • Cookie는 웹 브라우저에만 존재하여 모바일 앱 등의 다양한 클라이언트에서 인증을 처리할 수 없다.
  • Scale Out(수평적 확장)에서 서버간 세션 공유가 어렵다.
오버헤드(Overhead)란? 어떤 처리를 하기 위해 들어가는 간접적인 처리 시간, 메모리 등을 의미한다.

 

정리

더보기

인증과 인가

  1. 인증(Authentication)
    • 사용자가 누구인지 확인하는 과정
      ex) 로그인
  2. 인가(Authorization)
    • 사용자가 어떤 권한을 가지고 있는지 결정하는 과정
    • 반드시 인증이 선행되어야 한다.
      ex) 회원만 조회 가능한 게시글, 본인이 작성한 게시글 수정
  3. 쿠키(Cookie)
    • 정의
      • 웹 브라우저(Client 측)에 저장되는 데이터
    • 용도
      • 사용자의 방문 기록, 로그인 상태 유지, 개인 맞춤 설정 등을 저장, HTTP 특성 극복, 광고 정보
    • 특징
      • 클라이언트 측에 저장되며, 서버에 요청을 보낼 때마다 포함되어 전송됨.
    • 수명
      • 만료 날짜를 설정할 수 있음, 세션 쿠키(브라우저 종료 시 삭제)와 영속 쿠키(지정된 기간 동안 유지)로 구분됨.
  4. 세션(Session)
    • 정의
      • 사용자와 서버 간의 상태를 유지하기 위한 방법.
    • 용도
      • 로그인 정보, 사용자 활동 등을 서버 측에서 관리.
    • 특징
      • 서버 측에서 저장되며, 세션 ID가 쿠키에 저장되어 클라이언트와 연결됨.
    • 수명
      • 브라우저를 닫거나 일정 시간이 지나면 만료됨.
    • Session 관리
      1. 세션은 메모리를 사용한다.
        • 세션이 많아지면 서버의 장애가 발생할 수 있다.(메모리 리소스 부족)
        • 최소한의 데이터만 저장해야 한다.
      2. HttpSession은 LastAccessedTime을 기준으로 30분의 생명주기를 가지고 있다.
      3. 세션의 시간을 너무 오래 유지하여도 메모리 리소스가 부족할 수 있다.
        • 적당한 시간 설정이 꼭 필요하다.(Default 30분)