Kim VamPa

[Spring][쇼핑몰 프로젝트][31] 검색 구현(기본 기능 구현) 본문

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

[Spring][쇼핑몰 프로젝트][31] 검색 구현(기본 기능 구현)

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

 

목표

기본적 검색 기능 구현

 

 이번 포스팅부터 검색 기능 구현을 목표로 합니다. 기본적인 '책 제목' 검색뿐만 아니라, '작가' 검색을 할 수 있고, 메인 페이지에서 각 카테고리 가 출력되어 있는 네비 링크를 클릭 시 해당 카테고리의 상품이 검색이 될 수 있도록 하는 것이 최종 목표입니다. 

 

 최종 적인 목표 기능을 바로 구현을 하지는 않고 '기본적 검색 기능 구현' -> '조건 검색 기능 구현(작가 검색, 카테고리 검색)'  -> '메인페이지 카테고리 네비 링크' 순으로 구현을 진행을 할 것입니다.

 

 이번 포스팅에선 기본적인 '책 제목' 검색 기능 구현을 목표로 할 것입니다. 구현하고자 하는 기능과 비슷한 기능을  앞선 포스팅 [Spring][쇼핑몰 프로젝트][19] 상품목록 기능 구현 에서 진행을 하였기 때문에, 기존 코드를 활용하여 빠르게 진행하겠습니다. 

 

※ 게시판의 목록 구현, 검색 구현과 같은 기능입니다. 해당 기능의 자세한 정리는 게시판 프로젝트 포스팅에 정리를 했습니다.

 

 

순서

1. 방향

2. 서버(server)

 2.1 Mapper

 2.2 Service

 2.3 Controller

3. 뷰(view)

4. 테스트

 

 

 

 

1. 방향

 앞선 포스팅에서 이미 검색기능을 구현을 해보았지만 간략히 정리를 하고 넘어가겠습니다.

 

 검색 기능을 크게 뷰(View), 서버(Server) 측면에서의 역할을 살펴보면 아래와 같습니다. 

 

 뷰(view) :
 사용자가 작성한 키워드(keyword)에 대한 데이터와 더불어 검색 결과 페이지에 몇 개의 결과물들을 표시할 것인지(amount), 몇 번째 페이지 볼 것인지(pageNum)에 대한 데이터를 서버에 전송하게 됩니다. (amount와 pageNum을 지정 값을 전송하지 않게 된다면 기본적으로 10, 1의 값이 서버 측에서 가질 것입니다.)

 

=> 

 

 서버(Server) :
 서버는 전달받은 keyword, amount, pageNum을 사용하여 DB에서 검색 결과 데이터를 가져온 뒤 클라이언트에 전송을 할 것입니다. 더불어서 결과화면에 페이지 정보를 출력하기 위해 필요로 한 데이터들 또한 같이 생성하여 전송을 합니다.

 

=> 

 

 뷰(view) :
전달받은 데이터들을 활용하여 검색 결과 목록을 출력하고, 몇페이지에 대한 정보 들을 출력하게 됩니다.


 

  코드들은 [Spring][쇼핑몰 프로젝트][19] 상품목록 기능 구현 에서 사용했던 코드들을 거의 그대로 가져올 것입니다. 데이터들의 전달 수단으로 사용했던 Criteria와 조금 다른 점은 출력시킬 데이터들의 정보가 조금 다르다는 점뿐입니다. 

 

 구현은 Mapper, Service, Controller 순으로 진행하겠습니다. 

 

 

2. 서버측 구현

2.1 Mapper

 

 BookMapper.java

 

 com.vam.mapper 패키지에 BookMapper.java 인터페이스를 생성합니다. 생성 후 아래의 두 메서드 선언부를 작성합니다. (하나의 메서드는 검색 결과에 대한 데이터를, 다른 하나의 메서드는 페이징 데이터를 호출합니다.)

 

그림 2-1

 

	/* 상품 검색 */
	public List<BookVO> getGoodsList(Criteria cri);
	
	/* 상품 총 갯수 */
	public int goodsGetTotal(Criteria cri);

 

그림 2-2

 

 

 BookMapper.xml

 

  src/main/resources -> co/vam/mapper 경로에 BookMapper.xml 파일을 생성 후 해당 파일에 mybiatis를 사용하기 위한 기본 설정 코드 들을 추가합니다.

 

그림 2-3

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
  <mapper namespace="com.vam.mapper.BookMapper">


	
  </mapper>

 

그림 2-4

 

 

 앞서 선언한 메서드가 실행할 쿼리문을 작성합니다. 기존 관리자 페이지 상품 목록 쿼리와 동일한 코드입니다. 단지 검색될 대상 몇몇 데이터들을 수정하였습니다.

 

 Oracle

<-- Oracle -->
	<!-- criteria(검색조건) -->
	<sql id="criteria">
		    <if test="keyword != null">
			    bookName like '%' || #{keyword} || '%' and
			</if>
	</sql>

	
	<!-- 상품 검색 -->
	<select id="getGoodsList" resultType="com.vam.model.BookVO">
	
		<![CDATA[
		    select * from(
		        select /*+INDEX_DESC(vam_book 인덱스ID)*/ rownum as rn, bookId, bookName,
		            (select authorName from vam_author where vam_book.authorId = vam_author.authorId) authorName, authorId,
		            (select cateName from vam_bcate where vam_book.cateCode = vam_bcate.cateCode) cateName,cateCode, publisher, publeYear, bookPrice  
		        from vam_book
		        where 
	    ]]>
	    
	    <include refid="criteria"></include>
	    
	    <![CDATA[
	    		        
		        rownum <= #{pageNum} * #{amount} 
	        	)
	        where rn > (#{pageNum} -1) * #{amount}
		]]>	  		
	
	</select>
	
	<!-- 상품 총 개수 -->
	<select id="goodsGetTotal" resultType="int">
	
		select count(*) from vam_book
		where
		<include refid="criteria"></include> 
		bookId >0
		
	</select>

 

그림 2-5 Oracle

 

MySQL

<-- MySQL -->
	<!-- criteria(검색조건) -->
	<sql id="criteria">
		    <if test="keyword != null">
				where (bookName like concat ('%', #{keyword}, '%'))
		    </if>
	</sql>
	
	<!-- 상품 검색 -->
	<select id="getGoodsList" resultType="com.vam.model.BookVO">
	
			select  bookId, bookName, b.authorName, a.authorId, c.cateName, a.cateCode, publisher, publeYear, bookPrice
			from vam_book a left outer join vam_author b on a.authorId = b.authorId
			left outer join vam_bcate c on a.cateCode = c.cateCode
			<include refid="criteria"></include>
			order by bookId desc 
			limit #{skip}, #{amount}	
	
	</select>
	
	<!-- 상품 총 개수 -->
	<select id="goodsGetTotal" resultType="int">

  		select count(*) from vam_book
  		
		<include refid="criteria"></include>
		
	</select>

 

그림 2-6 MySQL

 

 

 BookMapperTests.java

 

src/test/java -> com.vam.mapper 패키지에 테스트를 위한 BookMapperTests.java클래스를 생성합니다.

 

그림 2-7

 

 Junit 테스트를 위한 기본적인 코드를 추가해주고 BookMapper 객체를 의존성 주입해줍니다. 

 

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("file:src/main/webapp/WEB-INF/spring/root-context.xml")
public class BookMapperTests {
	
	@Autowired
	private BookMapper mapper;
	
}

 

 

 작성한 Mapper 메서드가 정상적으로 동작하는지 확인하기 위해서 Junit 테스트를 합니다.

 

	@Test
	public void getGoodsListTest() {
		
		Criteria cri = new Criteria();
		// 테스트 키워드
		//cri.setKeyword("test");
		System.out.println("cri : " + cri);
		
		List<BookVO> list = mapper.getGoodsList(cri);
		System.out.println("list : " + list);
		
		System.out.println("==========");
		int goodsTotal = mapper.goodsGetTotal(cri);
		System.out.println("totla : " + goodsTotal);
		
	}

 

그림 2-9

 

그림 2-10 키워드 x

 

그림 2-11 키워드 o

 

 

 

2.2 Service

 

BookService.java

 

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

 

그림 2-12

 

 

 아래의 두 개의 메서드 선언부를 작성합니다.

 

	/* 상품 검색 */
	public List<BookVO> getGoodsList(Criteria cri);
	
	/* 상품 총 갯수 */
	public int goodsGetTotal(Criteria cri);

 

그림 2-13

 

 

BookServiceImpl.java

 

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

 

그림 2-14

 

 BookService 인터페이스를 상속하는 키워드와 log() 메서드를 사용하기 위한 어노테이션을 추가해줍니다. 더불어 스프링에서 해당 클래스를 Service로 인식할 수 있도록 어노테이션을 추가해줍니다.

 

그림 2-15

 

 BookMapper 클래스를 의존성 주입해주는 코드를 추가해줍니다.

 

 

그림 2-16

 

 오버라이딩 하여 앞서 작성한 메서드의 구현부를 작성합니다.

 

	/* 상품 검색 */
	@Override
	public List<BookVO> getGoodsList(Criteria cri) {
		
		log.info("getGoodsList().......");
		
		return bookMapper.getGoodsList(cri);
	}

	/* 사품 총 갯수 */
	@Override
	public int goodsGetTotal(Criteria cri) {
		
		log.info("goodsGetTotal().......");
		
		return bookMapper.goodsGetTotal(cri);
		
	}

 

그림 2-17

 

 

2.3 BookController.java 

 

 앞서 작성한 BookService 클래스의 메서드를 사용할 수 있도록 BookService 클래스를 의존성 주입해줍니다.

 

그림 2-18

 

 

 상품 검색을 처리하는 URL 매핑 메서드를 작성합니다. 로직은 AdminController.java 클래스의 goodsManageGET메서드와 동일합니다. 상품 검색 요청을 처리하는 URL은 "/search"로 지정을 하였습니다.

 

	/* 상품 검색 */
	@GetMapping("search")
	public String searchGoodsGET(Criteria cri, Model model) {
		
		logger.info("cri : " + cri);
		
		List<BookVO> list = bookService.getGoodsList(cri);
		logger.info("pre list : " + list);
		if(!list.isEmpty()) {
			model.addAttribute("list", list);
			logger.info("list : " + list);
		} else {
			model.addAttribute("listcheck", "empty");
			
			return "search";
		}
		
		model.addAttribute("pageMaker", new PageDTO(cri, bookService.goodsGetTotal(cri)));
		
		
		return "search";
		
	}

 

그림 2-19

 

 

3. 뷰(view)

 

  먼저 main.css 파일에서 search_area 식별자의 설정 중 색상에 대한 설정을 지웁니다. 이번 포스팅에서는 단순히 기능의 구현을 중점으로 목표를 하기 때문에 css는 추 후에 추가를 하겠습니다.

 

그림 3-1

 

그림 3-2

 

 

main.jsp

 

 클래스 속성 값이 search_area인 div 태그의 내용을 지우고 아래의 코드를 추가해줍니다. 추가 한 코드는 기본적으로 사용자가 검색하고자 하는 키워드를 작성할 수 있는 input 태그와 검색을 요청하는 form, input 태그입니다.

 

                	<div class="search_wrap">
                		<form id="searchForm" action="/search" method="get">
                			<div class="search_input">
                				<input type="text" name="keyword">
                    			<button class='btn search_btn'>검 색</button>                				
                			</div>
                		</form>
                	</div>

 

 

 

 

search.jsp

 

 매핑 메서드에 "search" 뷰가 반환되도록 작성했기 때문에 main.jsp 파일이 위치한 디렉터리에 search.jsp 파일을 새로 생성합니다. 

 

그림 3-4

 

 

 생성 후 이번 포스팅에선 기본적으로 검색 기능이 제대로 수행되는지를 만 볼 것입니다. 따라서 Controller에서 뷰로 보낸 list와 pageMaker 데이터를 확인하기 위한 아래의 코드를 작성하였습니다.

 

<h1>검색결과</h1>
<div>
	${list}
</div>
<div>
	${pageMaker}
</div>

 

그림 3-5

 

 

 

4. 테스트

 작성한 코드가 의도대로 동작하는지 확인하기 위해서 테스트를 합니다.

 

그림 4-1

 

그림 4-2

 

그림 4-3

 

그림 4-4

 

 

REFERENCE

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

 

 

 

DATE

  • 2020.08.24

 

728x90
반응형
Comments