티스토리 뷰
내 정보를 저장하는 곳에는 쿠키, 세션이 있다.
쿠키는 클라이언트 웹에 저장하는 방식이고 세션은 서버 안에 저장하는 방식이다.
그리고 요즘에는 jwt라고 Json Web Token 이라고 내 정보를 암호화하여서 쿠키로 내려주는 방식으로 정보를 보호한다.
그래서 Token을 사용하여 쿠키를 이용하므로 이번엔 쿠키에 대해서 잘 배워보기 위해서 이 글을 작성하게 되었습니다.
Cookie의 개념
Cookie는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다.
브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 자동으로 함께 전송합니다.
HTTP의 특징인 stateless의 단점으로 생겨 났기 때문에 쿠키로 인해 사용자의 로그인 상태를 유지시킬 수 있습니다.
쿠키를 사용하는 이유
1. 개인화와 사용자 경험 향상
쿠키를 사용하여 사용자의 선호 설정이나 환경을 저장하면 웹사이트는 사용자별로 맞춤화된 경험을 제공할 수 있습니다.
이를 통해서 사용자에게 더욱 편리하고 개인화된 서비스를 제공할 수 있습니다.
예를 들어, 사용자의 로그인 정보나 언어 선택, 장바구니 내용 들을 쿠키에 저장하여 사용자가 사이트를 다시 방문 했을 때 이전의 설정을 기억하도록 할 수 있습니다.
2. 분석과 추적
쿠기를 사용하여 사용자의 행동 패턴을 추적하고 분석할 수 있습니다. 이를 통해 웹사이트는 사용자의 행동을 분석하여 마케팅 전략을 수립하거나 서비스 개선에 활용할 수 있습니다.
예를 들어, 어떤 제품이나 페이지를 사용자가 가장 많이 방문하는지를 추적하여 관련 컨텐츠를 제공하거나 타겟팅된 광고를 보여줄 수 있습니다.
3. 세션관리
쿠키를 사용하여 사용자의 세션 상태를 유지하고 관리할 수 있습니다.
웹사이트의 로그인 기능에서 세션 쿠키를 사용하여 사용자가 로그인 상태를 유지하는 동안 다른 페이지로 이동해도 로그인이 유지됩니다.
이론적으로는 아 쿠키가 이렇게 쓰이는 구나라고 인식이 될텐데요
이게 코드로 보면서 쿠키를 어떻게 사용하는지 알아 보겠습니다.
쿠키의 옵션들
쿠키는 따로 전송하는 것이 아닌 브라우저에 쿠키가 있으면 자동으로 서버에 전송하게 됩니다.
옵션 이름 | 설명 |
이름 (key) | 쿠키의 식별자로 사용되는 쿠키의 이름을 설정합니다. |
값 (Value) | 쿠키에 저장할 값을 설정합니다. |
만료일 (MaxAge) | 쿠키의 유효 시간을 설정합니다. 만료일을 지정하거나 상대적인 시간을 지정할 수 있습니다. |
도메인 (Domain) | 쿠키가 사용될 도메인을 설정합니다. 기본적으로 현재 도메인이 설정됩니다. |
경로 (Path) | 쿠키의 경로를 설정합니다. 기본값으로는 '/'로 전체 도메인에 대해 쿠키가 사용됩니다. |
보안 (Secure) | HTTPS 연결일 때만 쿠키를 전송하도록 설정합니다. |
보안 (HttpOnly) | JavaScript 코드로 쿠키에 접근을 제한합니다. |
쿠키의 생성
Java
import javax.servlet.http.Cookie;
// Java
Cookie cookie = new Cookie("쿠키명", "쿠키값");
JavaScript
// JavaScript
document.cookie = '쿠키명=쿠키값';
쿠키의 라이프 타임
쿠키 유지하는 종류가 2가지가 됩니다.
명시된 시간 이후에 삭제되는 영속적인 쿠키, 현재 세션이 끝날 때 삭제되는 세션 쿠키가 있습니다.
[세션 쿠키]
- 세션 쿠키는 만료 날짜가 지정되어 있지 않아서 브라우저 세션이 유지되는 동안만 존재합니다.
즉, 브라우저를 닫거나 세션 탭을 종료하면 해당 쿠키는 자동으로 삭제됩니다. - 예를 들어, 로그인한 사용자의 세션을 유지하기 위해 세션 쿠기를 사용할 수 있습니다. 사용자가 로그인하면 해당 세션에 관련 정보를 저장하고, 브라우저가 종료되거나 로그아웃할 때 해당 세션 쿠키가 삭제되어 자동 로그아웃되는 효과를 얻을 수 있습니다.
[영속적인 쿠키]
- 영속적인 쿠키는 세션 쿠키와 달리 특정 기산 동안 브라우저나 시스템을 종료해도 삭제되지 않고 존재합니다.
즉, 설정된 만료 시간이 도달할 때까지 유지되는 쿠키입니다. - 초 단위로 설정하는 maxAge, 특정 날짜와 시간으로 설정하는 expires로 설정할 수 있습니다.
- 예를 들어, 로그인하기 전에 아이디를 저장하여서 로그인할 때 편리하게 사용할 수 있습니다.
[쿠키 설정 의미]
- setMaxAge(0) : 이 설정은 클라이언트의 브라우저에게 해당 쿠키를 즉시 삭제하도록 알립니다.
- setMaxAge(-1) : 이 설정은 브라우저가 종료될 때까지 쿠키를 유지하도록 합니다. (= 세션 쿠키)
- setMaxAge(양수) : 해당 값(초) 동안 쿠키를 유지합니다. (= 영속적인 쿠키)
Java (영속적인 쿠키)
import javax.servlet.http.Cookie;
// Java (MaxAge)
Cookie cookie = new Cookie("쿠키명", "쿠키값");
cookie.setMaxAge(1 * 24 * 60 * 60); // 1일 동안 쿠키 유지
// Java (Expires)
Cookie cookie = new Cookie("쿠키명", "쿠키값");
Date expirationDate = new Date(System.currentTimeMillis() + 24 * 60 * 60 * 1000);
cookie.setExpires(expirationDate); // 현재 시간 기준으로 1일 후까지 유지
JavaScript
// JavaScript (MaxAge)
document.cookie = '쿠키명=쿠키값; max-age=3600'; // 60초 * 60 = 1시간 동안 쿠키 유지
// JavaScript (expires)
const date = new Date();
date.setTime(date.getTime() + (1 * 24 * 60 * 60 * 1000)); // 1일 후의 시간을 설정
document.cookie = '쿠키명=쿠키값; expires=' + date.toUTCString();
// JavaScript (expires)2
document.cookie = '쿠키명=쿠키값; expires=Fri, 24 dec 2023 07:28:00 GMT';
// GMT 시간대로 12월 24일 07시 28일까지 유효한 쿠키
Tip) 한국 시간(KTS)은 GMT보다 9시간 더 빠릅니다.
쿠키의 도메인
명시적으로 지정하지 않으면 해당 페이지의 도메인이 기본적으로 설정됩니다.
예를 들어, 현재 페이지의 URL이 "https://www.domain.com/pageA"라면 해당 URL에서 쿠키를 생성하여도 해당 도메인인 "www.domain.com"이 default로 도메인으로 설정됩니다.
Java
import javax.servlet.http.Cookie;
// Java
Cookie cookie = new Cookie("쿠키명", "쿠키값");
cookie.setDomain("example.com"); // 도메인 설정
JavaScript
// JavaScript
document.cookie = '쿠키명=쿠키값; domain=example.com'; // JS로 쿠키 생성과 Domain 설정
쿠키의 Path
Path는 URL의 일부분으로 도메인 이후로 오는 경로라고 이해하시면 됩니다.
도메인이 더 넓은 범위라고 하면 Path는 더 하위 범위라고 볼 수 있겠죠
예를 들어, Path를 "/user"라고 설정하게 되면 "domain.com/user" , "domain.com/user/detail" 와 같이 생성된 페이지 경로와 그의 하위 URI 경로안에서 사용할 수 있게 됩니다. 하지만 "domain.com/member" 혹은 "domain.com/home" 같은 다른 경로로 가진 URL 에는 사용하지 못하게 됩니다.
Java
import javax.servlet.http.Cookie;
// Java
Cookie cookie = new Cookie("username", "aox");
cookie.setPath("/mypage"); // Path 설정
JavaScript
// JavaScript
document.cookie = 'username=aox; path=/mypage'; // JS로 쿠키 생성과 Path 설정
쿠키의 HttpOnly
HttpOnly의 옵션은 JavaScript 코드로 쿠키에 접근 못하게 막는 옵션입니다.
브라우저에서 개발자 도구를 열고 console창에서 document.cookie를 작성하게 된다면 현재 도메인에 가지고 있는 쿠키 목록들이 출력이 되고 그 쿠키들을 사용할 수 있습니다. 하지만 HttpOnly 옵션을 사용하게 된다면 그 해당 쿠키는 JavaScript로 출력이 안 되는 것을 볼 수 있습니다.
설정을 안해주면 Default 값이 false로 되어서 JavaScript가 접근이 가능하니 보안에 신경 써야 하는 정보를 쿠키에 넣었다면 HttpOnly옵션을 true로 설정해 주는 것이 좋겠죠?
Java
import javax.servlet.http.Cookie;
// Java
Cookie cookie = new Cookie("username", "aox");
cookie.setHttpOnly(true); // HttpOnly 설정
JavaScript
JavaScript에서 쿠키로 접근이 안되어야 해서 HttpOnly옵션은 JavaScript로 직접 설정할 수가 없습니다.
서버에서 HttpOnly 옵션을 설정을 해주어야 합니다.
실제 사용해 보기
1. 서버(Spring)에서 전송한 쿠키값 받는 예시 코드
웹 브라우저에서 쿠키가 있는 채로 요청을 보내면 자동으로 보내지기 때문에
지금 컨트롤러에서 받는 코드를 작성하였다.
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class controller {
@RequestMapping("/yourEndpoint")
public String yourMethod(HttpServletRequest request) {
String value = null;
Cookie[] cookies = request.getCookies(); // 요청 헤더에서 쿠키 목록을 가져옴
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("찾을 쿠키명".equals(cookie.getName())) {
value = cookie.getValue(); // 쿠키값을 가져온다.
// 쿠키값을 이용한 처리 로직 가능
break;
}
}
}
return "yourView";
}
}
2. 서버(Spring)에서 쿠키 값 변경하는 예시 코드
요청 보내온 쿠키 값을 변경하여 다시 보내줘야 한다고 했을 때
Request에서 쿠키를 찾아서 값을 넣어 변경하고 Response로 다시 내려주었다.
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class controller {
@RequestMapping("/yourEndpoint")
public String yourMethod(HttpServletRequest request, HttpServletReponse response) {
String value = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("찾을 쿠키명".equals(cookie.getName())) {
cookie.setValue("변경된 쿠키값"); // 쿠키값 변경
cookie.setMaxAge(60 * 60 * 24 * 7); // 유효기간 변경
response.addCookie(cookie); // 변경된 쿠키를 응답 헤더에 추가
break;
}
}
}
return "yourView";
}
}
3. Java 서버에서 쿠키 삭제하기
위에 1, 2번과 스프링 처럼 받을라면 아래 내용만 변경해주면 된다.
HttpServletRequest request;
HttpServletResponse response;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if ("쿠키명".equals(cookie.getName())) {
cookie.setMaxAge(0); // 유효기간을 0으로 설정하여 삭제
response.addCookie(cookie); // 삭제된 쿠키를 응답 헤더에 추가
break;
}
}
}
전체 적인 사용 예시
저는 Spring 서버단에서 Cookie를 클라이언트에게 내려주는 상황을 예시로 들고 예시 코드를 작성해 보겠습니다.
서로 계층을 나누어 코드를 작성하거나 기능으로 빼면 되지만 예시로 한 번에 보여주기 위해 Controller 계층에 다 담게 되었습니다.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
@Controller
public class LoginController {
@Autowired
private UserService userService;
@PostMapping("/login")
public ModelAndView login(@RequestParam String email, @RequestParam String password, HttpServletRequest request,
HttpServletResponse response, ModelAndView mav ) {
User user = userService.getUserByEmailAndPassword(email, password);
if (user == null) {
mav.setViewName("redirect:/login")
mav.addObject("errorMsg", "유효하지 않은 이메일, 비밀번호 입니다.");
return mav;
}
// User 정보를 쿠키로 저장
Cookie userCookie = new Cookie("userId", user.getUserId());
userCookie.setMaxAge(-1); // 세션쿠키로 생성
response.addCookie(userCookie);
mav.setViewName("redirect:/dashboard");
return mav;
}
@GetMapping(value = "/dashboard")
public ModelAndView home(HttpServletRequest request,
ModelAndView mav) {
String userId = null;
// 쿠키에서 user에 저장된 정보 가져오기
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("userId")) {
userId = cookie.getValue();
}
}
}
User user = userService.getUserByUserId(userId);
if (user == null) {
mav.setViewName("redirect:/login");
mav.addObject("errorMsg", "유저 정보가 없습니다.");
return mav;
}
mav.setViewName("/dashboard");
return mav;
}
}
감사합니다.
'프로그래밍 언어 > 🌱JavaScript' 카테고리의 다른 글
[JavaScript] 데이터 타입 변환과 단축 평가 : 마법같은 변신! (0) | 2023.11.14 |
---|---|
[JavaScript] RegExp 정규표현식 : 문자열 패턴 분석의 핵심 가이드! (0) | 2023.10.31 |
[JavaScript] Ajax Fetch: 웹 애플리케이션 데이터 비동기 통신 (0) | 2023.10.23 |
- Total
- Today
- Yesterday
- 프로세스
- 프론트
- 디자인패턴
- DBeaver
- AJAX
- 개발환경
- Spring Security
- 비동기
- 네트워크
- java
- Fetch
- Cors
- git
- 자바스크립트
- 코딩테스트
- 깃허브 액션
- Mac
- spring
- 템플릿
- JavaScript
- 개발자
- 개발블로그
- aws
- 데이터 베이스
- Front
- 오라클
- 개발
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |