Kim VamPa

[Spring][쇼핑몰 프로젝트][34] 검색 필터링 기능 - 2 본문

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

[Spring][쇼핑몰 프로젝트][34] 검색 필터링 기능 - 2

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

 

목표

검색 필터링 기능 구현

 

 검색 필터링 기능을 수행하는 Service 메서드와 Controller 메서드 구현하여 뷰(View)로 필터링 데이터를 전송하는 것을 목표로 합니다.

 

 

 

순서

 

1. Service 메서드

2. Service 메서드 테스트

3. BookController.java

 

1. 구현 방향

 이전 포스팅에서 만든 Mapper메서드를 활용하여 Service를 만들어보도록 하겠습니다.

 

 먼저 BookService.java 인터페이스에 '검색 결과에 대한 필터링 정보'를 반환해주는 메서드의 선언부를 선언해줍니다.

 

	/* 검색결과 카테고리 필터 정보 */
	public List<CateFilterDTO> getCateInfoList(Criteria cri);

 

그림 1-1

 

 

 

 BookServiceImpl.java에서 앞서 선언한 메서드를 오버 라이딩해줍니다.

 

	/* 검색결과 카테고리 필터 정보 */
	@Override
	public List<CateFilterDTO> getCateInfoList(Criteria cri) {

		return null;
	}

 

그림 1-2

 

 

getCateInfoList 구현부에 본격적으로 코드를 추가해주겠습니다.

 

 먼저 반환할 데이터가 담길 상자 역할을 할 List<CateFilterDTO> 타입의 filterInfoList 객체를 선언해 및 초기화해줍니다.

 

List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();

 

 

 필터 정보의 대상이 될 '카테고리 코드'를 반환해주는 getAuthorIdList를 호출하고 반환 값을 String 배열 타입의 cateList 변수에 저장해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] cateList = bookMapper.getCateList(cri);

 

 

 그런데 파리미터로 들어오는 Criteria 객체의 type변수에 "A"가 포함된 경우 getCateList() Mapper 메서드가 수행할 쿼리문에 authorId의 정보가 필요로 합니다. 따라서 검색 Service 메서드인 getGoodsList()때와 마찬가지로 type에 "A"가 있을 경우 getAuthorIdList() Mapper메서드를 호출하여 authorId 값들을 반환받고 이를 Criteria객체에 추가해주는 코드를 추가해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);

 

  cateList의 배열에 담긴 각각의 '카테고리 코드'들을  Criteria 객체에 담아서 getcateInfo() Mapper 메서드의 파라미터로 전달할 예정인데 Criteria 객체의 기존 cateCode 값을 유지할 수 없게 됩니다. 기존의 cateCode를 유지해주기 위해 두 가지 방안이 있는데, 첫 번째는 getCateInfo() Mapper 메서드에 전달 파라미터 용도로만 사용해줄 Criteria타입의 객체를 새로 만들어서 거기에 데이터를 담고 사용하는 방법이 있습니다. 두 번째 방법은 기존의 '카테고리 코드(cateCode)'를 새로운 변수를 선언하여 임시로 담고 Service 메서드가 끝나기 전에 임시로 저장해둔 '카테고리 코드'를 Criteria에 다시 저장해주는 방법입니다. 

 

※ Criteria의 'cateCode' 기존 값을 유지 해 주지 않는다면 필터링된 '상품 화면' 결과 화면에서 페이지 인터페이스를 통해 페이지를 이동했을 때 전혀 다른 결과물이 나올 수 있기 때문입니다.

 

 저는 두 번째 방식으로 진행하겠습니다. 임시로 Criteria 객체에 있는 'cateCode'값을 저장해 줄 String 타입의 tempCateCode 변수를 선언해주고 Criteria 객체의 'cateCode'값을 저장해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);
		
		String tempCateCode = cri.getCateCode();

 

 

 cateList 모든 요소들을 순회하여 처리할 수 있도록 향상된 for문을 작성해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);
		
		String tempCateCode = cri.getCateCode();
		
		for(String cateCode : cateList) {
			
		}

 

 for문 구현부에 cateList 요소에 있는 '카테고리 코드'를 Criteria에 "cateCode"변수에 저장을 해주고 Criteria를 파라미터로 하는 getCateInfo() 메서드를 호출해줍니다. 호출한 메서드가 반환한 카테고리 정보가 담긴 CateFilterDTO 타입의 객체를 우리가 작업 중인 Service 메서드 getCateInfoList() 메서드가 반환 할 List 객체(filterInfolist)에 요소로 추가해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);
		
		String tempCateCode = cri.getCateCode();
		
		for(String cateCode : cateList) {
			cri.setCateCode(cateCode);
			CateFilterDTO filterInfo = bookMapper.getCateInfo(cri);
			filterInfoList.add(filterInfo);
		}

 

 

 현재 작업중인 Service 메서드 getCateInfoList()의 주 목적인 '카테고리 필터링 정보'들을 List객체에 담아 주는 작업을 완료했기 때문에 임시로 저장해둔 '카테고리 코드'( tempCateCode) 값을 Criteria의 cateCode 값에 저장해줍니다. 

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);
		
		String tempCateCode = cri.getCateCode();
		
		for(String cateCode : cateList) {
			cri.setCateCode(cateCode);
			CateFilterDTO filterInfo = bookMapper.getCateInfo(cri);
			filterInfoList.add(filterInfo);
		}
		
		cri.setCateCode(tempCateCode);

 

 

 마지막으로 '카테고리 코드'가 담긴 List 객체 "filterInfoList"를 return문에 추가해줍니다.

 

		List<CateFilterDTO> filterInfoList = new ArrayList<CateFilterDTO>();
		
		String[] typeArr = cri.getType().split("");
		String [] authorArr;
		
		for(String type : typeArr) {
			if(type.equals("A")){
				authorArr = bookMapper.getAuthorIdList(cri.getKeyword());
				cri.setAuthorArr(authorArr);
			}
		}
		
		String[] cateList = bookMapper.getCateList(cri);
		
		String tempCateCode = cri.getCateCode();
		
		for(String cateCode : cateList) {
			cri.setCateCode(cateCode);
			CateFilterDTO filterInfo = bookMapper.getCateInfo(cri);
			filterInfoList.add(filterInfo);
		}
		
		cri.setCateCode(tempCateCode);
		
		return filterInfoList;

 

 전체적인 Service 메서드를 완성하였지만 한 가지를 보완해주어야 합니다. type이 "A", "AC"이고 authorArr요소에 authorId가 없는 경우 getCateInfo() Mapper 메서드가 에러가 나기 때문에, authorArr 배열이 요소를 가지지 않는 경우 getCateInfo() 메서드가 실행되지 않도록 해주어야 합니다.

 

 따라서 getAuthorIdList() 메서드를 호출한 바로 다음 공간에 authorArr 배열의 길이를 체크해서 0인 경우 getCateInfo() 메서드가 실행이 될 필요가 없기 때문에 Service 메서드가 바로 return 이 될 수 있도록 코드를 추가해줍니다.

 

				if(authorArr.length == 0) {
					return filterInfoList;
				}

 

 

 

 

 

 

 

2. Service 메서드 테스트

 

 Service 메서드 작성을 완료했기 때문에 테스트를 해보겠습니다. "src/test/java" 경로에 있는 com.vam.service 패키지에 BookService.java 클래스를 새로 생성해줍니다.

 

그림 2-1

 

 

 클래스 선언부에 Junit 테스트를 사용하기 위한 기본적인 설정 어노테이션을 추가해줍니다.

 

그림 2-2

 

 

 BookService 인터페이스의 getCateInfoList() 메서드를 테스트해야 하기 때문에 BookService를 의존성 주입해줍니다. 

 

 

 

 getCateInfoList() 메서드를 테스트하기위해 아래의 코드를 작성하여 Junit테스트를 진행하였습니다. 각 상황은 type이 "TC", "AC", "T", "A"인  경우에 따라 각각 테스트 메서드를 작성하였고, keywrod 변수가 각 메서드에 두 개인 이유는 DB에 존재하는 상품 데이터를 가진 keyword와 그렇지 않은 keyword를 각각 테스트 하기 위함입니다.

 

	@Test
	public void getCateInfoListTest1() {
		Criteria cri = new Criteria();
	
		String type = "TC";
		//String keyword = "테스트";
		String keyword = "없음";	
		String cateCode="103002";

		cri.setType(type);
		cri.setKeyword(keyword);
		cri.setCateCode(cateCode);
		
		System.out.println("List<CateFilterDTO> : " + service.getCateInfoList(cri));
		
	}
	
	@Test
	public void getCateInfoListTest2() {
		Criteria cri = new Criteria();
	
		String type = "AC";
		String keyword = "유홍준";	
		//String keyword = "머스크";	
		String cateCode = "103002";

		cri.setType(type);
		cri.setKeyword(keyword);
		cri.setCateCode(cateCode);
		
		System.out.println("List<CateFilterDTO> : " + service.getCateInfoList(cri));
		
	}	

	@Test
	public void getCateInfoListTest3() {
		Criteria cri = new Criteria();
	
		String type = "T";
		String keyword = "테스트";
		//String keyword = "없음";	
		

		cri.setType(type);
		cri.setKeyword(keyword);
		
		System.out.println("List<CateFilterDTO> : " + service.getCateInfoList(cri));
		
	}	
	
	@Test
	public void getCateInfoListTest4() {
		Criteria cri = new Criteria();
	
		String type = "AC";
		//String keyword = "유홍준";	
		String keyword = "머스크";	
		

		cri.setType(type);
		cri.setKeyword(keyword);
		
		System.out.println("List<CateFilterDTO> : " + service.getCateInfoList(cri));
		
	}

 

 

3. BookController.java

 Service 메서드 테스트까지 완료를 하였다면 '상품 목록' 페이지에 필터 정보를 전달해주기 위해 Controller에 작업을 해주어야 합니다.

 

 "search.jsp"로 이동을 하는 "search" URL 매핑 메서드에 Model 객체의 addAttribute() 메서드를 호출하여 cateGetInfoList() Service 메서드 반환 값(List객체)을 "filter_info"속성명으로 전달해줍니다.

 

model.addAttribute("filter_info", bookService.getCateInfoList(cri));

 

그림 3-1

 

 

 그런데 필터 정보를 만들어내는 cateGetInfoList() Service 메서드는 type이 "A", "AC", "T", "TC"인 경우에만 호출해야 합니다. 따라서 앞서 말한 type의 경우에만 Service 메서드를 호출하도록 코드를 추가해줍니다.

 

		String[] typeArr = cri.getType().split("");
		
		for(String s : typeArr) {
			if(s.equals("T") || s.equals("A")) {
				model.addAttribute("filter_info", bookService.getCateInfoList(cri));		
			}
		}

 

 

 

 

REFERENCE

  • 코드로배우는 스프링 웹 프로젝트(남가람북스)

 

 

DATE

  • 2020.10.05

 

728x90
반응형
Comments