반응형
Spring Boot, Spring Security, JPA, MySQL을 활용하여 간단한 프로젝트를 진행하는 과정중 장바구니 상품 삭제에서 오류가 발생했다.
@PostMapping("/delete")
public String deleteCartItem(@RequestParam("cartNo") Integer cartNo, RedirectAttributes redirectAttributes) {
try {
System.out.println("cartNo: " + cartNo);
cartService.removeCartItem(cartNo);
redirectAttributes.addFlashAttribute("message", "상품이 삭제되었습니다.");
} catch (Exception e) {
redirectAttributes.addFlashAttribute("error", "상품 삭제 중 오류가 발생했습니다.");
}
return "redirect:/cart/list"; // 삭제 후 장바구니 목록으로 리다이렉트
}
<td>
<button class="btn btn-danger btn-delete" th:data-cart-no="${item.cartNo}">삭제</button>
</td>
// 개별 삭제 버튼 기능
$(".btn-delete").off("click").click(function() {
let cartNo = $(this).data("cart-no"); // 버튼에서 cartNo 값 가져오기
console.log(cartNo);
if (confirm("해당 상품을 삭제하시겠습니까?")) {
$.ajax({
url: "/cart/delete",
type: "POST",
data: { cartNo: cartNo },
beforeSend: function(xhr) {
// CSRF 토큰을 요청 헤더에 추가
xhr.setRequestHeader(csrfHeader, csrfToken);
},
success: function(response) {
alert("상품이 삭제되었습니다.");
location.reload(); // 삭제 후 페이지 새로 고침
},
error: function(xhr, status, error) {
alert("삭제 중 오류가 발생했습니다. 다시 시도해 주세요.");
console.error("Error:", xhr.responseText);
}
});
}
});
삭제버튼을 눌렀을때 confirm 으로 "해당 상품을 삭제하시겠습니까?" 창이 뜨고, '확인' 을 누르면 삭제가 되어야하고 위의 코드로 그것을 기대했다.
그런데 계속해서 403에러가 뜨는 것이다.
GPT한테 물어보니 일반적으로 Spring Security 사용시 POST 요청에서는 CSRF 토큰을 전달해야 하는데, 그걸 전달하지 않았는지 확인해보라고 했다.
그런데 그부분도 알려준대로 설정을 했었다.
1. HTML <head></head> 태그 안에 <meta> 태그로 설정
<head>
<meta charset="UTF-8">
<meta name="_csrf" content="${_csrf.token}"/>
<meta name="_csrf_header" content="${_csrf.headerName}"/>
...
...
</head>
2. JavaScript(jQuery)에서 CSRF 토큰 가져오기
// CSRF 토큰 가져오기
let csrfToken = $("meta[name='_csrf']").attr("content");
let csrfHeader = $("meta[name='_csrf_header']").attr("content");
3. Ajax 사용시 토큰 전달
// 개별 삭제 버튼 기능
$(".btn-delete").off("click").click(function() {
let cartNo = $(this).data("cart-no"); // 버튼에서 cartNo 값 가져오기
console.log(cartNo);
if (confirm("해당 상품을 삭제하시겠습니까?")) {
$.ajax({
url: "/cart/delete",
type: "POST",
data: { cartNo: cartNo },
beforeSend: function(xhr) {
// CSRF 토큰을 요청 헤더에 추가
xhr.setRequestHeader(csrfHeader, csrfToken);
},
success: function(response) {
alert("상품이 삭제되었습니다.");
location.reload(); // 삭제 후 페이지 새로 고침
},
error: function(xhr, status, error) {
alert("삭제 중 오류가 발생했습니다. 다시 시도해 주세요.");
console.error("Error:", xhr.responseText);
}
});
}
});
위와같이 코드를 짰는데 계속해서 403 에러가 났다.
그런데 한참을 찾다가 어이없는 곳에서 해결책을 찾았다.
현재 Thymeleaf를 사용중이었는데, <head></head> 태그 안에서 <meta> 태그로 설정한 부분에서 Thymeleaf 문법을 사용하지 않았던 것이다..
이걸로 엄청 시간 낭비했는데 Thymeleaf 쓸때는 가장 기본적인 부분을 놓치지 말아야겠다 싶어서 글을 남긴다.
<head>
<meta charset="UTF-8">
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
<title>website</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
<link href="/css/commmon.css" th:href="@{/css/common.css}" type="text/css" rel="stylesheet">
<link href="/css/main.css" th:href="@{/css/main.css}" type="text/css" rel="stylesheet">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="/js/main.js" th:src="@{/js/main.js}"></script>
</head>
반응형
'IT개발 > Spring Boot' 카테고리의 다른 글
(React + Typescript) + (Spring Boot + JPA + MySQL) 프로젝트 세팅 / tailwind css 설치 오류 포함 (1) | 2025.02.12 |
---|---|
Spring Boot 서비스 구조 (0) | 2025.01.23 |
lombok 설치방법(IntelliJ & Eclipse), MacOS (0) | 2024.12.20 |
Spring Boot Entity 클래스(스프링/부트/자바/백엔드개발/프로그래밍/Java/backend) (1) | 2024.11.28 |
Spring Boot JPA Hibernate란?(자바/백엔드/개발/프로그래밍/스프링) (1) | 2024.11.25 |
댓글