1. Cookie 역직렬화
1) 개요
- 쿠키에서 장바구니 데이터를 읽어와 객체로 변환하는 방식을 구현하려고 하였고 처음엔 단순한 형변환으로 데이터를 저장할 수 있다고 생각하였지만 파싱이란 개념을 몰라 문제가 발생하였다.
2) 문제 발생
// 처음에 생각한 방법
List<BasketItemDto> basket = (List<BasketItemDto>) basketCookie.getValue();
- 문제 1.
- 처음엔 단순한 형변환으로 데이터를 저장할 수 있다고 생각하였다. 하지만 여기서 ClassCastException 이라는 exception이 발생하는데 쿠키 값은 단순 문자열이기에 이를 Java 객체로 직접 변환하려고 발생하는 에러인 것을 알았다.
- 문제 2.
- 쿠키 값은 JSON 형식이므로 JSON 데이터를 처리하지 않으면 문자열 데이터인데 쿠키 값을 그대로 사용하려고 하면 문자열 분리와 데이터 추출을 수동으로 구현해야하고 데이터 구조가 복잡해지면 구현이 어려워진다.
- 문제 3.
- 위의 파싱 문제를 해결하는 코드 작성.
private List<BasketItemDto> parseBasketFromCookie(Cookie basketCookie) {
//쿠키가 없으면 빈 장바구니로 반환
if (basketCookie == null) {
return new ArrayList<>();
}
try {
//JSON 문자열인 쿠키 값을 List<BasketItemDto>로 역직렬화, //제네릭 타입을 처리하기 위한 도구.
return objectMapper.readValue(decodedBasket, new TypeReference<List<BasketItemDto>>() {});
} catch (JsonProcessingException e) {
throw new CustomException(ErrorCode.BAD_REQUEST);
}
}
- 하지만 여기서 또 다른 문제 발생하는데 바로 디코딩을 하지 않아서 JSON 파서가 %와 같은 문자를 처리하지 못해 JsonProcessingException 발생.
- 쿠키 값과 Java의 문자열을 비교할 때, 디코딩하지 않으면 항상 불일치한다는 사실 확인.
3) 해결
private List<BasketItemDto> parseBasketFromCookie(Cookie basketCookie) {
//쿠키가 없으면 빈 장바구니로 반환
if (basketCookie == null) {
return new ArrayList<>();
}
try {
// URL 디코딩
String decodedBasket = URLDecoder.decode(basketCookie.getValue(), "UTF-8");
//JSON 문자열인 쿠키 값을 List<BasketItemDto>로 역직렬화, //제네릭 타입을 처리하기 위한 도구.
return objectMapper.readValue(decodedBasket, new TypeReference<List<BasketItemDto>>() {});
} catch (JsonProcessingException | UnsupportedEncodingException e) {
throw new CustomException(ErrorCode.BAD_REQUEST);
}
}
- String decodedBasket = URLDecoder.decode(basketCookie.getValue(), "UTF-8");
- 위 코드를 사용하여 디코딩을 진행하였으며 디코딩을 진행함으로써.
- URL 인코딩된 데이터를 원래의 JSON 형태로 복원
- JSON 데이터를 안전하고 정확하게 처리.
- 문자열 비교, JSON 파싱 등 후속 작업이 가능하도록 데이터를 가공.
4) 결론
- 쿠키 데이터를 JSON에서 Java 객체로 변환함으로써 안정적으로 장바구니 데이터를 처리
- 클라이언트와 서버 간의 데이터 통신에서 발생할 수 있는 오류를 방지
1. Cookie 직렬화
1) 개요
- 장바구니 데이터를 쿠키에 저장하려고 시도하였다.
2) 문제발생
- 문제 1.
- 직렬화를 해주지 않아서 Jav 객체를 텍스트 기반 시스템에 전달할 수 없으므로 데이터 처리가 불가능했다.
- 데이터가 잘못된 형식으로 저장되고 시스템 간 통신이 실패.
- 문제 2.
- 문제 1을 해결하였지만 JsonProcessingException 이 발생하였다.
- 역직렬화에서 디코딩을 한 것 처럼 인코딩을 안해주어서 문제 발생.
- JSON 데이터에 포함된 {}, =, & 등의 문자가 URL에서 해석될 수 있어 URL이 손상된다.
3) 해결
String basketJson = objectMapper.writeValueAsString(basket);
- Jackson 라이브러리에서 제공하는 메서드로 Java 객체를 Json 문자열로 직렬화 해준다.
String encodedBasket = URLEncoder.encode(basketJson, "UTF-8");
- 역직렬화에서 발생한 에러와 같기 때문에 디코딩의 반대인 인코딩 필요하다는 것을 깨닫고 직렬화 Java 객체를 인코딩을 진행.
- URLEncoder.encode(basketJson, "UTF-8")를 사용해 데이터를 퍼센트 인코딩하여 안전하게 변환.
- 해결 코드
private void saveBasketToCookie(List<BasketItemDto> basket, HttpServletResponse response) {
try {
//List<BasketItemDto> 객체를 JSON 문자열로 직렬화
String basketJson = objectMapper.writeValueAsString(basket);
// URL 인코딩
String encodedBasket = URLEncoder.encode(basketJson, "UTF-8");
//직렬화된 JSON 데이터를 쿠키에 저장
Cookie cookie = new Cookie("basket", encodedBasket);
cookie.setMaxAge((int) COOKIE_MAX_AGE); // 쿠키 만료 시간 설정 (24시간)
cookie.setHttpOnly(true); // JavaScript 접근 불가 설정
cookie.setPath("/"); // 모든 경로에서 쿠키 접근 가능
response.addCookie(cookie); // HTTP 응답에 쿠키 추가
}
catch (JsonProcessingException | UnsupportedEncodingException e ) {
throw new CustomException(ErrorCode.BAD_REQUEST);
}
}
4) 결론
- objectMapper.writeValueAsString은 데이터를 JSON 형식으로 변환하여 저장 및 통신 과정에서 발생할 수 있는 문제를 방지하고, 데이터의 호환성 도와줍니다.
- URLEncoder.encode는 데이터가 URL 및 HTTP 요청에서 안전하게 사용될 수 있도록 보장하며, 클라이언트와 서버 간의 통신에서 발생할 수 있는 오류를 방지합니다.
'TIL > Project' 카테고리의 다른 글
TIL 2024-12-31 (Trouble Shooting (Team_Flow) ) (1) | 2024.12.31 |
---|---|
[KPT 회고록] (project : 먹GO) (1) | 2024.12.09 |
TIL 2024-12-05 (outsourcing 2일차) (2) | 2024.12.05 |
TIL 2024-12-04 (outsourcing 1일차) (1) | 2024.12.04 |
TIL 2024-11-28 (Trouble Shooting (통화 환율) ) (2) | 2024.11.28 |