Kim VamPa

[Spring][쇼핑몰 프로젝트][36] 장바구니 기능(장바구니 추가(서버 구현)) - 4 본문

스프링 프레임워크/쇼핑몰 프로젝트

[Spring][쇼핑몰 프로젝트][36] 장바구니 기능(장바구니 추가(서버 구현)) - 4

Kim VamPa 2021. 11. 18. 11:00
728x90
반응형
프로젝트 Github : https://github.com/sjinjin7/Blog_Project
프로젝트 포스팅 색인(index) : https://kimvampa.tistory.com/188

 

목표

장바구니 추가 기능 구현

 장바구니 추가 기능 구현을 목표로 합니다. 서버 측 구현과 뷰 측 구현으로 나누어서 작업할 예정이며 이번 포스팅에선 서버 측 구현을 목표로 합니다. 

 

 

순서

1. 개요

2. CartMapper 수정

3. Service 메서드

4. CartController

5. 테스트

 

 

1. 개요

 구현을 하기 전 우리가 만들 서버 측 장바구니 추가 기능은 어떠한 특징들을 가지는 지 먼저 정리하겠습니다.

 

- 뷰로 부터 '장바구니 추가' 요청을 받게 되고 DB에 등록할 데이터(memberId, bookId, bookCount)를 전달받는다.

- 전달받은 memberId와 bookId와 동일한 데이터를 가지는 vam_cart 행(row)이 있는지 확인하고 존재하지 않을 시 DB에 새로운 행(row)을 추가한다.

- 화면의 이동이 없는 비동기 방식으로 뷰는 요청하도록 할 것이기 때문에 http 바디에 바로 데이터를 삽입해서 반환한다.

- 뷰는 숫자를 반환받도록 한다. (0 : 등록 실패 / 1 : 등록 성공 / 2 : 등록된 데이터 존재 / 5 : 로그인 필요)

 

정리를 하면 뷰에서 비동기 방식으로 카트 등록 요청을 하며 memberId, bookId, bookCount를 서버로 전송합니다. 서버에선 '로그인 여부', '기존 데이터 존재 여부' 등을 거쳐서 '장바구니를 추가' 후 그 결과 숫자를 뷰로 반환하도록 할 것입니다.

 

 그런데 앞선 포스팅에서 "/cart" url 경로를 타는 모든 요청은 Interceptor를 거치도록 하였습니다. 지금 만들 '장바구니 등록' 메서드는 로그인에 관해서도 체크하여 그 결과를 반환하도록 만들 것이기 때문에, 우리가 구현하고자 하는 url("/cart/add") 요청에 대해서만 Interceptor를 거치지 않도록 설정을 변경해주어야 합니다. 이 변경 설정부터 작업을 시작해보겠습니다. 

 

Interceptor 예외 설정

 CartInterceptor 클래스를 스프링에서 관리하도록 설정 해준 servlet-context.xml 파일에 코드를 추가해줄 것입니다. 장바구니 관련 <interceptor> 태그에서 <mapping> 태그 아래에 아래의 코드를 추가해줍니다.

 

<exclude-mapping path="/cart/add"/>

 

 

 

 <exclude-mapping>태그는 interceptor 설정한 url 경로 중 예외 url을 설정해줄 수 있는 태그입니다. 설정을 해석하면 "/cart/**" 경로를 타는 모든 요청은 CartInterceptor 객체를 거친다. 하지만 "/cart/add" 경로는 interceptor 객체를 거치지 않는다입니다. 

 

 

2. CartMapper.java 수정

  

 현재 addCart() 메서드는 DB에 등록 성공 시 1을 반환합니다. (이전 CartMapper Junit 테스트에서 확인할 수 있습니다.) 하지만 제약조건에 맞지 않는 데이터들로 인해 DB등록에 실패했을 경우 0을 반환하지 않고 예외(Exception)가 터지면서 멈춥니다. 

 

 이번 cartAdd()는 실패했을 경우 0을 반환하는것이 목표 중 하나이기 때문에, 단순화를 위해 사용하지 않았던 "throws Exception"을 사용해주겠습니다. "throws Exception"은 메서드를 호출한 주체에게 메서드에서 발생한 예외를 던져주는 역할을 합니다.

 

 "throws Exception"예를들어보면 addCart() 메서드에 "throws Exception"이 없다면 예외상황이 발생하면 실행이 멈춥니다. 문제는 cartAdd() 메서드를 호출한 주체 입장에서는 어떠한 상황이 터졌는지를 알 수 없습니다.  그런데 "throws Exception"이 addCart()에 추가되어 있다면 이 메서드를 호출한 주체가 addCart() 메서드에 예외 상황이 발생했을 때 어떠한 예외 상황인지를 전달받을 수 있게 됩니다.

 

 CartMapper.java 인터페이스의 addCart() 메서드 선언부에 "throws Exception" 키워드를 추가해줍니다.

 

throws Exception

 

그림 2-1

 

 

 

3. Service 메서드

  

 Service 메서드를 추가 해줄 차례입니다. 이 메서드는 '장바구니 DB 등록" 에 대한 요청을 받고 이를 수행하는데, 단순히 등록만 하는 것이 아니라 등록하고자 하는 데이터가 이미 존재하는지를 체크하고, 성공 여부에 따른 int 값을 반환하는 것이 목표입니다. 

 

CartService.java 인터페이스

  com.vam.service 패키지에 CartService.java 인터페이스르 생성합니다.

 

그림 3-1

 

 

 생성한 인터페이스에 '장바구니 추가' 메서드 선언부를 추가해줍니다.

 

	/* 장바구니 추가 */
	public int addCart(CartDTO cart);

 

그림 3-2

 

 

CartServiceImpl.java

 com.vam.service 패키지에 CartServiceImpl.java 클래스를 생성해줍니다.

 

그림 3-3

 

 

 생성한 Service 클래스가 스프링 컨테이너에서 빈으로 관리 될 수 있도록 @Service 어노테이션을 클래스 선언부에 추가해줍니다.

1=

그림 3-4

 

 

 

 생성한 클래스 선언 부에 CartService 인터페이스를 상속 받는 키워드를 추가해줍니다.

 

그림 3-5

 

 

 CartMapper 객체의 메서드를 사용할 것이기 때문에 의존성 주입해줍니다.

 

그림 3-6

 

 

 인터페이스에서 선언한 메서드를 오버라이딩 해줍니다.

 

	@Override
	public int addCart(CartDTO cart) {

	}

 

그림 3-7

 

 

 checkCart() Mapper 메서드를 활용하여 등록하고자 하는 데이터가 이미 DB에 존재하는지 확인하여 존재할 경우 2를 반환하도록 코드를 작성합니다.

 

		// 장바구니 데이터 체크
		CartDTO checkCart = cartMapper.checkCart(cart);
		
		if(checkCart != null) {
			return 2;
		}

 

 

등록하고자 하는 데이터가 DB에 존재하지 않을 경우 실해오디는 코드를 작성합니다. DB 등록하는 addCart() Mapper 메서드를 호출하고 반환받은 값을 return 합니다.

 

		// 장바구니 데이터 체크
		CartDTO checkCart = cartMapper.checkCart(cart);
		
		if(checkCart != null) {
			return 2;
		}
       
       		return cartMapper.addCart(cart);

 

 

 addCart()가 "throws Exception" 통해서 예외를 던지도록 했기 때문에 이 메서드를 호출할 때 try-catch 문으로 감싸주어야 합니다. 감싸주는 코드를 추가하고 예외가 발생한 경우는 DB 등록에 실패한 것이기 때문에 0을 반환하도록 코드를 작성하였습니다.

 

		// 장바구니 데이터 체크
		CartDTO checkCart = cartMapper.checkCart(cart);
		
		if(checkCart != null) {
			return 2;
		}
		
		// 장바구니 등록 & 에러 시 0반환
		try {
			return cartMapper.addCart(cart);
		} catch (Exception e) {
			return 0;
		}

 

그림 3-8

 

 

 CartServiceTests.java

 우리가 작성한 Service 메서드가 의도대로 동작하는지 확인하기 위해 테스트를 해보겠습니다. src/test/java 디렉토리의 com.vam.service 패키지에 CartServiceTests.java 클래스를 생성해줍니다.

 

그림 3-8

 

 

 Junit 테스트를 위한 기본 코드와 테스트할 대상 메서드를 가진 CartService 객체를 의존성 주입해줍니다.

 

그림 3-9

 

 

 아래의 코드를 추가해서 메서드를 Junit 테스트합니다.

 

	//등록 테스트
	@Test
	public void addCartTest() {
		//given
			String memberId = "admin";
			int bookId = 22;
			int count = 5;
			
			CartDTO dto = new CartDTO(); 
			dto.setMemberId(memberId);
			dto.setBookId(bookId);
			dto.setBookCount(count);
		
		//when
			int result = service.addCart(dto);
		
		//then
			System.out.println("** result : " + result);
		
		
	}

 

 

 

 확인해야 할 상황은 3가지입니다.

 

첫 째, DB에 등록된 데이터 값을 넣어서 테스트(기대 반환 값 : 2)

둘 째, DB에 등록되지 않는 값을 넣어서 테스트(기대 반환 값 : 1 & DB 등록)

셋 째, SQL 에러를 발생시킬 값을 넣어서 테스트(존재하지 않는 memberId값 입력)(기대 반환 값 : 0)

 

 

4.  Controller 메서드

 com.vam.controller 패키지에 CartController.java 클래스를 생성합니다.

 

그림 4-1

 

 

 생성한 클래스를 Controller로 사용하기 위한 @Controller 어노테이션을 추가해주고, CartService 객체의 메서드를 사용해야 하기 때문에 의존성 주입해줍니다.

 

그림 4-2

 

 

  장바구니 추가 요청을 처리하는 URL 매핑 메서드를 작성합니다. (@ResponseBody를 사용 할 것이기 때문에 반환 타입은 String으로 하였습니다.)

 

	@PostMapping("/cart/add")
	public String addCartPOST() {

	}

 

 

 이 메서드는 화면을 반환하는 것이 아니라 데이터를 바로 반환하기 때문에 @ResponseBody를 추가해줍니다. (@ResponseBody 대신 반환 타입을 ResponseEntity를 사용해도 상관없습니다.)

 

	@PostMapping("/cart/add")
	@ResponseBody
	public String addCartPOST() {
	}

 

 

 등록할 데이터를 전달받아야 하기 때문에 CartDTO 타입의 파라미터 변수를 선언해줍니다. 추가로 로그인 여부를 확인하기 위해 session 객체가 필요로 하기 때문에 HttpservletRequest 타입의 파라미터 변수를 추가적으로 선언해줍니다.

 

	@PostMapping("/cart/add")
	@ResponseBody
	public String addCartPOST(CartDTO cart, HttpServletRequest request) {
	}

 

 

 먼저 로그인 여부를 체크하고 로그인되지 않았을 경우 5를 반환하도록 코드를 추가해줍니다. 

 

	@PostMapping("/cart/add")
	@ResponseBody
	public String addCartPOST(CartDTO cart, HttpServletRequest request) {
		// 로그인 체크
		HttpSession session = request.getSession();
		MemberVO mvo = (MemberVO)session.getAttribute("member");
		if(mvo == null) {
			return "5";
		}
		
	}

 

 

 장바구니 추가를 수행하는 addCart() 메서드를 호출하고 반환받은 값을 반환하도록 코드를 추가해줍니다. (addCart 반환타입이 int여서 String으로 변환하기 위해 빈 문자열을 더하기 연산 하였습니다.)

 

	@PostMapping("/cart/add")
	@ResponseBody
	public int addCartPOST(CartDTO cart, HttpServletRequest request) {
		// 로그인 체크
		HttpSession session = request.getSession();
		MemberVO mvo = (MemberVO)session.getAttribute("member");
		if(mvo == null) {
			return "5";
		}
		
		// 카트 등록
		
		int result = cartService.addCart(cart);
		
		return result + "";
	}

 

그림 4-3

 

 

REFERENCE

  •  

 

 

DATE

  • 2020.11.17

 

728x90
반응형
Comments