HTTP 무상태를 “브라우저 저장소”로 보완한다
HTTP는 무상태(stateless)라고 했다.
즉 서버는 기본적으로 “이전 요청이 누가 보낸 건지”를 기억하지 않는다.
그런데 로그인, 장바구니, 사용자 맞춤 화면 같은 기능은
이전 상태를 이어서 써야 한다.
그래서 웹에는 상태 유지를 위한 메커니즘이 필요하고,
그 출발점이 쿠키(cookie)이다.
쿠키는 “서버와 브라우저 사이를 오가는 작은 문자열 데이터”이다
쿠키는 기본적으로 이름과 값으로 이루어진 데이터 조각이다.
- 이름(name)
- 값(value)
이 쿠키는 브라우저에 저장되고,
이후 요청에서 자동으로 서버에 다시 전송된다.
즉 쿠키는 브라우저가 들고 다니는 상태 정보이다.
쿠키가 오고 가는 방식은 헤더로 결정된다
쿠키는 HTTP 메시지의 헤더로 주고받는다.
- 서버 → 브라우저: Set-Cookie 헤더로 쿠키 발급
- 브라우저 → 서버: Cookie 헤더로 쿠키 전송
즉 서버는 “응답(response)”에서 쿠키를 내려주고,
브라우저는 “다음 요청(request)”에서 그 쿠키를 붙여서 보낸다.
쿠키 기본 흐름
쿠키는 보통 이런 순서로 동작한다.
- 첫 요청: 브라우저에 쿠키가 없으면 Cookie 헤더 없이 요청한다
- 서버 응답: 서버가 Set-Cookie로 쿠키를 내려준다
- 브라우저 저장: 브라우저가 쿠키를 저장한다
- 다음 요청: 브라우저가 Cookie 헤더로 쿠키를 자동 첨부한다
- 서버는 쿠키 값을 읽어서 사용자 상태를 추적한다
즉 쿠키는 HTTP의 무상태성을 “브라우저 저장”으로 보완하는 장치이다.
쿠키는 서버가 발급하지만, 저장과 전송은 브라우저가 한다
여기서 오해하면 안 되는 포인트가 있다.
- 서버는 쿠키를 “발급”한다(Set-Cookie)
- 브라우저는 쿠키를 “저장”한다
- 브라우저는 조건이 맞으면 쿠키를 “자동으로 전송”한다
즉 서버가 매 요청마다 쿠키를 직접 들고 오는 게 아니라,
브라우저가 알아서 붙여서 보내준다.
쿠키 옵션이 중요한 이유: 언제, 어디로 전송되는지가 결정된다
쿠키는 “그냥 항상 다 붙는 문자열”이 아니다.
대표적으로 아래 옵션이 쿠키 동작을 바꾼다.
- Path: 어떤 경로 요청에 쿠키를 붙일지
- /로 두면 사이트 전체에 붙는다
- /todo로 두면 /todo/... 요청에만 붙는다
- Max-Age: 쿠키가 얼마나 유지될지(초 단위)
- 설정하면 브라우저가 디스크에 저장(지속 쿠키)
- 설정하지 않거나 -1이면 브라우저 종료 시 삭제(세션 쿠키)
그래서 “쿠키가 왜 안 붙지?” 문제의 상당수는
Path/Max-Age 설정에서 나온다.
// ================================
// [서버에서 쿠키 발급] 응답에 Set-Cookie가 포함되게 만든다
// ================================
@WebServlet("/cookie/set")
public class CookieSetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
Cookie cookie = new Cookie("theme", "dark"); // 이름=값
cookie.setPath("/"); // 사이트 전체에서 전송되게
cookie.setMaxAge(60 * 60); // 1시간(초 단위). -1이면 브라우저 종료 시 삭제(세션 쿠키)
resp.addCookie(cookie); // Set-Cookie 헤더로 내려감
resp.setContentType("text/plain; charset=UTF-8");
resp.getWriter().println("cookie set: theme=dark");
}
}
// ================================
// [서버에서 쿠키 읽기] 브라우저가 Cookie 헤더로 보내온 쿠키를 읽는다
// ================================
@WebServlet("/cookie/read")
public class CookieReadServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
String theme = null;
Cookie[] cookies = req.getCookies(); // 없으면 null일 수도 있다
if (cookies != null) {
for (Cookie c : cookies) {
if ("theme".equals(c.getName())) {
theme = c.getValue();
break;
}
}
}
resp.setContentType("text/plain; charset=UTF-8");
resp.getWriter().println("theme = " + theme);
}
}
정리
- HTTP는 무상태라서 상태 유지가 필요하다
- 쿠키는 브라우저에 저장되는 작은 문자열 데이터이다
- 서버는 Set-Cookie로 발급하고, 브라우저는 Cookie 헤더로 자동 전송한다
- Path/Max-Age 같은 옵션이 쿠키 전송 조건을 결정한다
하지만 쿠키는 브라우저에 저장되기 때문에 한계가 있고,
그 한계를 보완하기 위해 서버 쪽 저장소를 쓰는 방식이 세션이다.
'Web > Web Basics' 카테고리의 다른 글
| [상태 유지와 공통처리] 2-1. req.getSession()과 JSESSIONID, HttpSession (0) | 2026.03.30 |
|---|---|
| [상태 유지와 공통 처리] 2. 세션이란? (0) | 2026.03.30 |
| [MVC와 웹 흐름 제어] 7. WEB-INF에 JSP를 두는 이유: “JSP 직접 호출”을 구조적으로 막는다 (0) | 2026.03.29 |
| [MVC와 웹 흐름 제어] 6.PRG 패턴: POST 후에는 왜 redirect를 하는가 (0) | 2026.03.29 |
| [MVC와 웹 흐름 제어] 5. forward vs redirect: 언제 무엇을 써야 하는가 (0) | 2026.03.29 |