최종적으로 카트에 담기까지 구현했따. (강사님이 해주셨지만)
오늘은 간단하게 맛본 백엔드와 이를 GET or POST 한 js 등 최종적으로 정리해보겠다.
CoffeShopApplication.java
: 프로젝트의 진입점(메인 클래스)으로, Spring Boot 애플리케이션을 실행하는 역할.→ 클라이언트(사용자)로부터 요청을 받고 응답을 처리하는 계층.
REST API 엔드포인트를 정의하며, 주로 @RestController
또는 @Controller
어노테이션을 사용함.
CartController.java
: 장바구니 관련 요청을 처리.MemberController.java
: 회원 관련 요청을 처리.ProductController.java
: 상품 관련 요청을 처리.ReviewController.java
: 리뷰 관련 요청을 처리.→ 비즈니스 로직을 처리하는 계층.
데이터를 가공하거나 여러 DAO의 데이터를 조합하여 로직을 수행함.
주로 @Service
어노테이션을 사용하여 선언함.
CartService.java
: 장바구니 관련 비즈니스 로직 처리.MemberService.java
: 회원 관리 비즈니스 로직 처리.ProductService.java
: 상품 관리 비즈니스 로직 처리.ReviewService.java
: 리뷰 관리 비즈니스 로직 처리.→ 데이터베이스와 직접적으로 연결되는 계층.
데이터를 저장, 조회, 수정, 삭제하는 역할을 수행하며, 주로 @Repository
어노테이션을 사용함.
CartDao.java
: 장바구니 데이터 관리.LoginDao.java
: 로그인 관련 데이터 관리.MemberDao.java
: 회원 정보 데이터 관리.ProductDao.java
: 상품 정보 데이터 관리.ReviewDao.java
: 리뷰 데이터 관리.→ 데이터를 전달하는 역할을 하는 계층.
데이터를 하나의 객체로 묶어 클라이언트와 서버 간, 또는 서비스 계층과 DAO 간의 데이터 이동을 원활하게 함.
Cart.java
: 장바구니 정보를 담는 DTO.Login.java
: 로그인 정보를 담는 DTO.Member.java
: 회원 정보를 담는 DTO.Product.java
: 상품 정보를 담는 DTO.Review.java
: 리뷰 정보를 담는 DTO.→ 프로젝트에서 공통적으로 사용하는 기능을 모아둔 폴더.
예를 들면 날짜 포맷 변환, 문자열 처리, 공통적으로 사용하는 상수 등을 포함할 수 있음.
결국 이러한 구조를 통해 책임을 분리하여 유지보수를 쉽게 하고, 코드의 재사용성을 높일 수 있음.
우선 전체 흐름은
(Frontend) JavaScript → (Controller) CartController → (Service) CartService → (DAO) CartDao → (Database) MySQL
순으로 진행한다.
async function addToCart(prodcode) {
try {
const token = sessionStorage.getItem("Authorization");
const email = sessionStorage.getItem("nickname"); // nickname을 email로 사용
const response = await axios.post("http://localhost:8080/addToCart", {
prodcode: prodcode,
email: email,
quantity: 1,
}, {
headers: {
"Authorization": token
}
});
const cart = response.data;
console.log(cart);
} catch (error) {
console.error("장바구니 추가 오류:", error);
}
}
addToCart(prodcode)
함수가 실행됨.http://localhost:8080/addToCart
API에 POST
요청을 보냄.@RestController
@CrossOrigin("http://127.0.0.1:5500/")
public class CartController {
@Autowired
MemberService memberService;
@Autowired
CartService cartService;
@PostMapping("addToCart")
public String addToCart(@RequestHeader String authorization, @RequestBody Cart cart) {
System.out.println(authorization);
System.out.println(cart);
try {
// 1️⃣ 로그인 상태 확인 (토큰 검증)
Login loginInfo = memberService.checkToken(authorization);
if(loginInfo != null && loginInfo.getLoginTime() != null) {
long now = System.currentTimeMillis(); // 현재 시간 (밀리초)
long lastRequestTime = loginInfo.getLoginTime().getTime(); // 로그인 시간
// 2️⃣ 30분 이내 요청만 허용
if ((now - lastRequestTime) <= 1800000) {
cart.setEmail(loginInfo.getEmail());
cart.setQuantity(1);
// 3️⃣ 장바구니에 추가 (Service 호출)
cartService.addToCart(cart);
return "ok";
}
}
return null;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
프론트엔드의 POST요청을 받고 CartController가 실행된다.
세션 토큰 방식에서는 SessionId가 토큰 값 그 자체이다!
그리고 2가지 방식으로 나뉘는데
- 쿠키 방식은 서버가 SessionId를 쿠키에 저장하고, 이후 요청마다 자동 포함됨.
같은 도메인에서만 사용 가능(CORS 문제 발생 가능).- 헤더 방식은 서버가 SessionId를 발급하면, 클라이언트가 이를 Authorization 헤더에 직접 포함.
다른 도메인에서도 사용 가능 (API, 모바일 앱 연동에 유리).
다만 클라이언트가 직접 관리해야 하므로 보안 관리 필요.
-> 현재 프로젝트에서는 Authorization 헤더 방식 사용함
@Service
public class CartService {
@Autowired
private CartDao cartDao;
public void addToCart(Cart cart) throws Exception {
cartDao.addToCart(cart);
}
}
DAO를 호출하여 데이터베이스에 상품을 추가하는 비즈니스 로직이 담겨있다.
@Mapper
public interface CartDao {
public void addToCart(Cart cart) throws Exception;
}
public class Cart {
private String email;
private int prodcode, quantity;
// Getter & Setter
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public int getProdcode() { return prodcode; }
public void setProdcode(int prodcode) { this.prodcode = prodcode; }
public int getQuantity() { return quantity; }
public void setQuantity(int quantity) { this.quantity = quantity; }
// 생성자
public Cart(String email, int prodcode, int quantity) {
this.email = email;
this.prodcode = prodcode;
this.quantity = quantity;
}
// 기본 생성자
public Cart() {}
@Override
public String toString() {
return "Cart [email=" + email + ", prodcode=" + prodcode + ", quantity=" + quantity + "]";
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.shop.cafe.dao.CartDao">
<insert id="addToCart" parameterType="com.shop.cafe.dto.Cart">
INSERT INTO cart (email, prodcode, quantity)
VALUES (#{email}, #{prodcode}, #{quantity})
ON DUPLICATE KEY UPDATE quantity = quantity + VALUES(quantity);
</insert>
</mapper>
이제 영화 예매 사이트 미니 프로젝트를 앞둔 상태인데.. 세션 토큰 방식으로 로그인과 해당 토큰값을 가진 user라면 예매해두었던 마이페이지 등 그러한 기능들을 모쪼록 잘 구현하길 기도하며..