728x90
반응형

요약 한 줄
쿠키는 브라우저가 들고 다니는 작은 메모, 세션은 서버가 기억하고 쿠키(JSESSIONID)로 찾아오는 저장공간입니다. 로그인/장바구니는 보통 “세션”으로, “아이디 기억하기”는 “쿠키”로!
 

목차

  1. 쿠키 vs 세션 한눈 비교
  2. 쿠키: 브라우저가 저장하는 메모
  3. 세션: 서버가 관리하는 사용자 상태
  4. 로그인 흐름(쿠키·세션 조합) 실전 이해
  5. 보안 옵션(HttpOnly/Secure/SameSite) 핵심
  6. 서블릿/톰캣 기준 코드 예제
  7. 빈출 질문 & 실수 모음
  8. 체크리스트(면접/시험 대비)

1) 쿠키 vs 세션 한눈 비교

구분                                       쿠키(Cookie)                                                                                           세션(Session)

저장 위치클라이언트(브라우저)서버(메모리/세션 저장소)
식별 방식Cookie 헤더로 키-값 전달JSESSIONID 쿠키로 세션을 조회
수명Max-Age/Expires로 지정(영구/단기)유휴 시간(예: 30분) 지나면 만료
용도아이디 기억, 다크모드, A/B 실험 등로그인 상태, 장바구니, 권한 정보
보안탈취 위험 → HttpOnly/Secure/SameSite 필수서버 보안 중심, 세션 고정 공격 주의
용량도메인당 수 KB 수준서버 자원 사용(사용자 수↑ = 메모리↑)
 

포인트: “민감한 정보는 쿠키에 절대 직접 저장하지 말고, 세션에 저장하고 식별용 세션ID만 쿠키로!”


2) 쿠키: 브라우저가 저장하는 메모

  • 구성: name=value; Path=/; Domain=.example.com; Max-Age=2592000; Secure; HttpOnly; SameSite=Lax
  • 수명
    • 세션 쿠키: 브라우저 종료 시 삭제(수명 미지정)
    • 영속 쿠키: Max-Age/Expires 지정
  • 도메인/경로: 전송 범위를 최소화하면 노출면을 줄여 보안↑
  • 보안 옵션
    • HttpOnly: JS로 접근 차단(XSS 완화)
    • Secure: HTTPS에서만 전송
    • SameSite: 크로스사이트 전송 제어(Lax 기본 추천, 제3자 필요 시 None; Secure)

3) 세션: 서버가 관리하는 사용자 상태

  • 생성: 로그인 성공 → HttpSession에 사용자 정보를 저장
  • 식별: 컨테이너가 발급한 랜덤한 세션ID를 쿠키(JSESSIONID)로 클라이언트에 심음
  • 유지: 요청마다 JSESSIONID로 세션을 찾아서 상태를 이어감
  • 만료: 유휴 시간 초과 or 명시적 invalidate()
  • 확장: 서버 다중대응 시 스티키 세션 또는 외부 세션 저장소(예: Redis) 고려

4) 로그인 흐름(쿠키·세션 조합)

  1. 사용자가 로그인 폼 제출 → 서버에서 인증 성공
  2. HttpSession에 loginUser 저장, 세션ID 발급 → Set-Cookie: JSESSIONID=...
  3. 이후 요청에서 브라우저는 JSESSIONID를 자동 전송 → 서버는 해당 세션으로 사용자 식별
  4. “아이디 기억하기”는 별도 쿠키(rememberId)로 저장(민감정보 X)

5) 보안 옵션 핵심 정리

  • 항상 HttpOnly + Secure(HTTPS 전제)
  • SameSite=Lax 기본. 외부 리다이렉트/결제 등 크로스사이트 필요 시 SameSite=None; Secure
  • 세션 고정 방지: 로그인 성공 시 세션 재발급(invalidate 후 새 세션)
  • 쿠키 범위 최소화: Path, Domain 축소
  • 민감정보(토큰·개인정보) 쿠키 값에 직접 저장 금지(서버 세션 or 안전 저장소 사용)

6) 서블릿/톰캣 기준 코드 예제

6-1. 세션 사용 (로그인 성공 시)

// 로그인 검증 이후
HttpSession session = req.getSession();               // 없으면 생성
session.setAttribute("loginUser", user);              // 사용자 객체/ID 등
session.setMaxInactiveInterval(30 * 60);             // 30분 비활성 시 만료

// 필요 시 세션 고정 방지: 새 세션 발급
session.invalidate();
HttpSession newSession = req.getSession(true);
newSession.setAttribute("loginUser", user);

6-2. 로그아웃

HttpSession session = req.getSession(false); // 있으면 가져오고, 없으면 null
if (session != null) {
    session.invalidate();                    // 세션 파기
}
resp.sendRedirect("/");                      // 홈으로

6-3. “아이디 기억하기” 쿠키

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import jakarta.servlet.http.Cookie;

// 로그인 폼에서 remember 체크 시
String userId = req.getParameter("userId");
Cookie remember = new Cookie("rememberId",
        URLEncoder.encode(userId, StandardCharsets.UTF_8));
remember.setPath("/");                // 필요한 최소 경로
remember.setMaxAge(60 * 60 * 24 * 30);// 30일
remember.setHttpOnly(true);           // JS 접근 차단
remember.setSecure(true);             // HTTPS에서만
resp.addCookie(remember);

6-4. SameSite 설정(서블릿 표준 속성 미지원 시 헤더로)

// Some containers still need manual header for SameSite
String cookie = "rememberId=" + URLEncoder.encode(userId, StandardCharsets.UTF_8)
        + "; Max-Age=2592000; Path=/; HttpOnly; Secure; SameSite=Lax";
resp.setHeader("Set-Cookie", cookie);

6-5. 쿠키 읽기

Cookie[] cookies = req.getCookies();
if (cookies != null) {
    for (Cookie c : cookies) {
        if ("rememberId".equals(c.getName())) {
            String id = java.net.URLDecoder.decode(c.getValue(), StandardCharsets.UTF_8);
            // 폼 기본값으로 채우기 등 활용
        }
    }
}

7) 빈출 질문 & 실수 모음

  • Q. 세션은 어디 저장되나요?
    A. 기본은 서버 메모리(컨테이너). 규모가 커지면 외부 저장소/세션 클러스터링.
  • Q. 쿠키에 토큰/JWT 넣어도 되나요?
    A. 가능하나 HttpOnly+Secure+SameSite를 지키고, 만료·회수 전략 및 XSS/CSRF 대비 필수.
  • Q. 로드밸런싱에서 세션이 사라져요!
    A. 스티키 세션(같은 서버로 라우팅) 또는 공유 세션 저장소를 사용하세요.
  • 실수1: 쿠키에 개인정보/권한을 평문으로 저장
  • 실수2: HttpOnly/Secure 빠짐
  • 실수3: 로그인 시 세션 재발급 미흡(세션 고정 취약점)
  • 실수4: SameSite 미설정으로 외부 연동 시 쿠키 전송 안 돼서 로그인 깨짐

8) 체크리스트(면접/시험 대비)

  • 쿠키/세션 차이 10초 안에 설명 가능?
  • JSESSIONID 역할 & 세션 재발급 타이밍 이해?
  • HttpOnly/Secure/SameSite 각각의 의미/기본값/언제 쓰는지?
  • 분산 환경에서 세션 유지 전략(스티키 vs 저장소) 장단점?

썸네일/타이틀 이미지

  • 파일: session_cookie_title.png
  • 컨셉: 쿠키 캐릭터가 “세션” 메모를 브라우저에게 전달하는 귀여운 낙서 스타일
  • 티스토리 글 상단에 업로드 후 대표 이미지로 설정하세요.
728x90
반응형
728x90
반응형

목차

  1. 서블릿이란? (쉬운 비유)
  2. 서블릿의 핵심 특징
  3. 서블릿 컨테이너(예: Tomcat)의 역할
  4. 서블릿 동작 흐름(요청→매핑→doGet/doPost→응답)
  5. 서블릿 생명주기(init → service → destroy)
  6. JSP는 뭐고, 서블릿과 어떻게 다른가
  7. 실전 예제: HelloServlet (Annotation 기반)
  8. 자주 하는 실수 & 베스트 프랙티스
  9. 마무리 체크리스트(면접/시험 대비)

1) 서블릿이란? (쉬운 비유)

사용자(브라우저)가 “로그인해줘!”라고 부탁하면, 서블릿이 그 요청을 받아 DB를 확인하고 결과 페이지(응답)를 만들어 돌려주는 자바 클래스입니다.

  • “요청을 받아 응답을 만든다” = Controller 역할에 딱 맞음.

2) 서블릿의 핵심 특징

  • 동적 웹 컴포넌트: 요청 시점에 필요한 내용을 만들어 응답.
  • HttpServlet 상속: javax.servlet.http.HttpServlet(Jakarta EE에선 jakarta.servlet.http.HttpServlet)을 상속.
  • 스레드 기반 동작: 컨테이너가 요청마다 스레드를 재사용/관리.
  • MVC에서 Controller로 자주 사용.
  • (구)HTML을 자바 코드로 println 하던 시대 → 유지보수 어려워서 JSP/템플릿과 분리해서 씀.

3) 서블릿 컨테이너의 역할 (Tomcat 대표)

  • 웹 서버와 통신을 대신 처리(소켓, HTTP 파싱 등).
  • 생명주기 관리: 로딩→init()→요청 시 service()→종료 시 destroy().
  • 멀티스레드 처리: 요청마다 스레드 할당/관리.
  • 선언적 보안: 설정 파일/어노테이션 기반으로 인증·인가 처리.

4) 서블릿 동작 흐름

  1. 클라이언트가 URL 요청 → 컨테이너가 HttpServletRequest/Response 생성
  2. URL 매핑(web.xml 또는 @WebServlet)으로 대상 서블릿 찾기
  3. service()가 호출되어 메서드 분기(doGet/doPost 등)
  4. 서블릿이 응답을 만들어 HttpServletResponse로 전송
  5. 컨테이너가 마무리 정리

5) 서블릿 생명주기 (Life Cycle)

  • init(): 서블릿 최초 로딩 시 1회 호출(공유 리소스 초기화에 적합)
  • service(): 매 요청마다 호출되어 doGet()/doPost()로 분기
  • destroy(): 컨테이너 종료/교체 시 1회 호출(정리 작업)
[로딩] → init() → (요청 n번) service() → ... → destroy() → [언로드]

6) JSP는 무엇이고, 서블릿과 어떻게 다른가

  • JSP(Java Server Pages): HTML 안에 자바를 삽입해 화면 구성에 특화.
  • 최종적으로 JSP도 서블릿으로 변환되어 실행됨.
  • 일반적으로 서블릿=로직/제어, JSP=뷰 로 분리해서 MVC 구조를 만든다.

7) 실전 예제: HelloServlet (Annotation 기반)

// jakarta.servlet-api를 사용하는 최신 톰캣 기준 예시
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {

        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=UTF-8");

        PrintWriter out = resp.getWriter();
        out.println("<!DOCTYPE html>");
        out.println("<html><head><meta charset='UTF-8'><title>Hello</title></head>");
        out.println("<body><h1>안녕하세요, Servlet!</h1>");
        out.println("<p>요청 URI: " + req.getRequestURI() + "</p>");
        out.println("</body></html>");
    }
}

Tip: 구형 프로젝트는 web.xml 매핑을 쓰지만, 요즘은 @WebServlet("/path") 어노테이션 매핑이 간편합니다.

8) 자주 하는 실수 & 베스트 프랙티스

  • 인스턴스 변수에 상태 저장 금지: 서블릿은 다중 스레드가 공유합니다.
  • 문자 인코딩 설정: resp.setContentType("text/html; charset=UTF-8") 등 필수.
  • 비즈니스 로직 분리: DAO/Service로 분리하고 서블릿은 흐름 제어만.
  • 에러/예외 처리: 공통 에러 페이지, 필터/인터셉터로 로깅과 인증 처리.
  • JSP에서 스크립틀릿 최소화: EL/JSTL, 템플릿 엔진(Thymeleaf 등)로 표현만 담당.

9) 마무리 체크리스트 (면접/시험 포인트)

  • 서블릿과 JSP의 관계 설명 가능?
  • 컨테이너 역할(생명주기·스레드·보안) 술술 말할 수 있는지?
  • Life Cycle 순서/용도 정확히 아는지?
  • URL 매핑(@WebServlet vs web.xml) 차이 이해했는지?

SEO용 FAQ

Q1. 서블릿은 왜 필요한가요?
A. HTTP 요청을 자바로 처리해 동적 페이지를 만드는 표준 컨트롤러이기 때문입니다.

Q2. JSP랑 뭐가 달라요?
A. JSP는 화면 템플릿, 서블릿은 로직/흐름 제어. JSP도 결국 서블릿으로 변환돼 실행됩니다.

Q3. 스프링 MVC랑 관계는?
A. 스프링 MVC도 내부적으로 서블릿(DispatcherServlet)을 사용합니다. 서블릿 개념을 알면 스프링이 쉬워집니다.

728x90
반응형

+ Recent posts