프론트와 백 이해하기 4 (최종 정리 느낌)

심영민·2025년 3월 15일
0

유레카

목록 보기
22/33


최종적으로 카트에 담기까지 구현했따. (강사님이 해주셨지만)

오늘은 간단하게 맛본 백엔드와 이를 GET or POST 한 js 등 최종적으로 정리해보겠다.

최종 CoffeeShop 프로젝트 구조

📁 com.shop.cafe

  • CoffeShopApplication.java : 프로젝트의 진입점(메인 클래스)으로, Spring Boot 애플리케이션을 실행하는 역할.

📁 com.shop.cafe.controller

→ 클라이언트(사용자)로부터 요청을 받고 응답을 처리하는 계층.
REST API 엔드포인트를 정의하며, 주로 @RestController 또는 @Controller 어노테이션을 사용함.

  • CartController.java : 장바구니 관련 요청을 처리.
  • MemberController.java : 회원 관련 요청을 처리.
  • ProductController.java : 상품 관련 요청을 처리.
  • ReviewController.java : 리뷰 관련 요청을 처리.

📁 com.shop.cafe.service

→ 비즈니스 로직을 처리하는 계층.
데이터를 가공하거나 여러 DAO의 데이터를 조합하여 로직을 수행함.
주로 @Service 어노테이션을 사용하여 선언함.

  • CartService.java : 장바구니 관련 비즈니스 로직 처리.
  • MemberService.java : 회원 관리 비즈니스 로직 처리.
  • ProductService.java : 상품 관리 비즈니스 로직 처리.
  • ReviewService.java : 리뷰 관리 비즈니스 로직 처리.

📁 com.shop.cafe.dao

→ 데이터베이스와 직접적으로 연결되는 계층.
데이터를 저장, 조회, 수정, 삭제하는 역할을 수행하며, 주로 @Repository 어노테이션을 사용함.

  • CartDao.java : 장바구니 데이터 관리.
  • LoginDao.java : 로그인 관련 데이터 관리.
  • MemberDao.java : 회원 정보 데이터 관리.
  • ProductDao.java : 상품 정보 데이터 관리.
  • ReviewDao.java : 리뷰 데이터 관리.

📁 com.shop.cafe.dto

→ 데이터를 전달하는 역할을 하는 계층.
데이터를 하나의 객체로 묶어 클라이언트와 서버 간, 또는 서비스 계층과 DAO 간의 데이터 이동을 원활하게 함.

  • Cart.java : 장바구니 정보를 담는 DTO.
  • Login.java : 로그인 정보를 담는 DTO.
  • Member.java : 회원 정보를 담는 DTO.
  • Product.java : 상품 정보를 담는 DTO.
  • Review.java : 리뷰 정보를 담는 DTO.

📁 com.shop.cafe.util

→ 프로젝트에서 공통적으로 사용하는 기능을 모아둔 폴더.
예를 들면 날짜 포맷 변환, 문자열 처리, 공통적으로 사용하는 상수 등을 포함할 수 있음.

프로젝트 전체적인 흐름

  1. 프론트에서 특정 API를 호출하면 Controller가 요청을 받음.
  2. ControllerService를 호출하여 비즈니스 로직을 처리함.
  3. ServiceDAO를 호출하여 데이터베이스에서 필요한 데이터를 가져옴.
  4. 데이터가 DTO 객체에 담겨 Service → Controller → 사용자로 반환됨.

결국 이러한 구조를 통해 책임을 분리하여 유지보수를 쉽게 하고, 코드의 재사용성을 높일 수 있음.

장바구니 담기 처리 과정은?

우선 전체 흐름은
(Frontend) JavaScript → (Controller) CartController → (Service) CartService → (DAO) CartDao → (Database) MySQL
순으로 진행한다.

Cart.js

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) 함수가 실행됨.
  • axios를 이용해 백엔드의 http://localhost:8080/addToCart API에 POST 요청을 보냄.
  • 사용자의 이메일(email)상품 코드(prodcode), 수량(quantity=1)을 함께 전달함.
  • 요청 시 토큰(Authorization)을 헤더에 포함하여 인증함.

CartController

@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가 실행된다.

  • @PostMapping("addToCart")을 통해 API 엔드포인트를 지정함.
  • 프론트엔드에서 전달된 Authorization 토큰을 검증하여 사용자가 로그인 상태인지 확인함.
  • 로그인한 사용자의 마지막 요청 시간이 30분 이내라면 CartService를 호출하여 장바구니에 상품을 추가함.

세션 토큰 방식에서는 SessionId가 토큰 값 그 자체이다!
그리고 2가지 방식으로 나뉘는데

  • 쿠키 방식은 서버가 SessionId를 쿠키에 저장하고, 이후 요청마다 자동 포함됨.
    같은 도메인에서만 사용 가능(CORS 문제 발생 가능).
  • 헤더 방식은 서버가 SessionId를 발급하면, 클라이언트가 이를 Authorization 헤더에 직접 포함.
    다른 도메인에서도 사용 가능 (API, 모바일 앱 연동에 유리).
    다만 클라이언트가 직접 관리해야 하므로 보안 관리 필요.
    -> 현재 프로젝트에서는 Authorization 헤더 방식 사용함

CartService

@Service
public class CartService {
    
    @Autowired
    private CartDao cartDao;

    public void addToCart(Cart cart) throws Exception {
        cartDao.addToCart(cart);
    }
}

DAO를 호출하여 데이터베이스에 상품을 추가하는 비즈니스 로직이 담겨있다.

CartDao

@Mapper
public interface CartDao {
	public void addToCart(Cart cart) throws Exception;
}
  • MyBatis의 @Mapper를 사용하여 데이터베이스에 직접 접근함.
  • addToCart(Cart cart) 메서드를 통해 장바구니 테이블(cart)에 데이터를 추가함.

Cart.java (DTO)

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 + "]";
	}
}
  • 장바구니 데이터를 저장하는 객체. (데이터를 객체 형태로 관리)
  • email, prodcode, quantity 필드를 가짐.

Cart.xml

<?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>
  • xml파일로 sql에 쉽게 접근
  • MySQL의 ON DUPLICATE KEY UPDATE를 사용하여 같은 상품이 장바구니에 있을 경우, 수량을 증가시킴.

미니 프로젝트를 앞두고..

이제 영화 예매 사이트 미니 프로젝트를 앞둔 상태인데.. 세션 토큰 방식으로 로그인과 해당 토큰값을 가진 user라면 예매해두었던 마이페이지 등 그러한 기능들을 모쪼록 잘 구현하길 기도하며..

profile
코딩너무어려운대 어떡할과 재학중

0개의 댓글