본문 바로가기
프로젝트 & 실습/VarChar_JSP_ver_Proj

[프로젝트] 필터 검색을 통해 원하는 정보 출력하기(ft. FrontController)

by hhyyyjun 2023. 1. 8.

프로젝트의 메인 기능인 필터 기능을 구현해보았다.

필터는 연료/지역/가격/주행거리/연식 총 5개의 카테고리로 분류하여 검색하도록 하였다.

연료와 지역의 경우에는 각 항목에서 다중선택을 할 수 있도록 하였다.

SearchVO.java - 필터 검색에 필요한 데이터가 들어가는 곳

SearchDAO.java - sql문을 통해 필요한 데이터를 출력할 메서드 선언

CarSearchAction.java - FrontController를 통해 들어온 요청을 처리할 기능 및 출력할 데이터의 속성값 선언

FrontController.java - 사용자 요청이 들어왔을 때 해당 경로(action)로 이동

index.jsp - 처음 서버를 실행할 페이지

filter.jsp - 필터검색을 위한 html 구조 및 표현언어 사용하여 웹페이지에서 데이터 값 출력

rangeSlider.js - 범위 슬라이더 플러그인(Jquery 사용)

selectOption.js - 가격/연식 카테고리에서 최대값이 최소값보다 작게 선택되지 않기위해 js 로직 구현

CAR(TABLE) - 크롤링된 자동차의 데이터 값들이 저장될 DB 테이블

filterSearch.css - 범위슬라이더 플러그인 css

1. SearchVO

연료와 지역의 경우에는 각 항목에서 다중선택을 할 수 있도록 하였다.

연료와 지역은 다중선택을 위해 하나의 파라미터에 여러 데이터를 담아야 하기 때문에 배열 객체를 선언하였다.

가격/주행거리/연식

가격, 주행거리, 연식은 정수값으로 각 최소값과 최대값을 담을 변수로 선언하였다.


2. SearchDAO

전체 흐름 - 메서드를 하나로만 사용하기 위해 사용자가 검색한 필터 값에 따라 조건식을 통하여 초기 sql문에 삽입되도록 코드 작성

초기 sql 문 - sql_selectAll

SELECT A.* FROM

(SELECT * FROM CAR WHERE 1=1 " + CfuelSql + " " + CcitySql+ " " +CyearSql + " " + CkmSql + " " + CpriceSql + ") A;

CfuelSql , CcitySql, CyearSql, CkmSql, CpriceSql

필터 기능이 사용되면 각 조건식에 따라 삽입될 sql문의 String 객체

사용자가 필터를 선택하지 않을 시에는 각 조건식에 들어가지 않고 공백처리하여 sql문에 삽입된다.

SELECT A.* FROM (SELECT * FROM CAR WHERE 1=1) A

이 sql문은 SELECT * FROM '테이블명' 과 같은 전체 데이터를 출력한다.

 

WHERE 1=1을 사용하는 이유

WHERE 1=1은 동적으로 변하는 SQL문을 사용하기 위해 사용하였다.

조건에 따라 쿼리를 붙이기 위해 첫번 째 조건에 어떤 것이 올지 모르므로 1=1 인 참(true)인 조건을 걸고, 이후 AND로 조건들을 붙이기 위해 사용

WHERE 1=1은 항상 참을 의미


연료 필터 검색 시 사용되는 로직(지역 필터 검색 로직과 동일)

연료나 지역 필터를 사용 시 다중선택을 할 수 있으므로, 여러 카테고리를 통해 검색할 수 있도록 하기위해

IN 절을 사용하여 초기 selectAll sql 문에 넣을 수 있도록 하였다.

IN 절

IN ('테이블에서 검색할 데이터명1', '테이블에서 검색할 데이터명2', .....)

IN 의 서브쿼리 내에 사용자가 지정한 값이 있는 경우 값을 출력할 수 있다.(SELECT인 경우)

로직 순서

만약 연료에 대한 필터를 검색 시 검색할 값을 1개를 가질수도 있고, 여러개를 가질수도 있다.

1) 필터 검색을 위한 데이터가 배열에 존재할 때 == 배열.size() > 0

append 메서드를 사용하기 위해 StringBuiler 클래스를 통하여 문자열을 붙일 객체를 선언한다.(사진에서는 cfuelSB 객체)

2) 필터 검색에 사용될 카테고리가 저장된 배열 값들을 DAO내에서 또다른 배열 객체를 선언하여 저장

3) for문을 통해 카테고리가 저장된 배열의 길이만큼 반복문 진행

3-1) 반복문이 진행되면서 i 값에 해당하는 배열의 인덱스 값을 객체 cfuelSB에 붙인다.

=> '카테고리명' 형태로 저장해야 하므로 역슬래쉬(\)를 통해 '를 문자열로 추가하여 붙여야 한다.

3-2) 배열에 저장된 값이 2개 이상일 경우 i+1의 값이 배열의 길이보다 작다면 ' , ' 를 붙인다.

3-3) 초기 sql문 WHERE 1=1 뒤에 추가할 문자열을 CfuelSql 에 저장한다.

ex) 필터 검색에 데이터값 전기, 가솔린 선택 후 검색 시

CfuelSql = AND CFUEL IN ('전기','가솔린')


연식 필터 검색 시 사용되는 로직(가격/주행거리 로직에도 동일)

연식/가격/주행거리 필터는 정수형을 사용하고 범위를 이용하여 데이터를 검색한다.

따라서 BETWEEN 절을 사용한다.

BETWEEN절

컬럼명 BETWEEN '최소값' AND '최대값'

최소값과 최대값 사이 범위에서 컬럼명에 해당하는 값들을 출력한다(SELECT인 경우)

로직순서

1) View에서 최소값과 최대값 선택 후 검색했을 때 최소값이 0보다 크다면

초기 sql 문에 추가될 문자열에 최대값, 최소값을 불러와 삽입한 후 CyearSql에 저장한다.


**초기 sql문(sql_selectAll)을 아래에 배치

sql문이 상단에 위치할 경우 이미 실행되었으므로 위 조건들에 따른 sql문들이 삽입되어도 원하는 데이터를 출력할 수 없기 때문이다

사용자가 값을 입력할 때 ? 로 받는 것이 아니라 조건에 따라 sql문이 작성되고 삽입되는 것이기 때문


3. filter.jsp / rangeSlider.js (범위슬라이더 플러그인)

테스트를 하기 위해 만든 View용 jsp 파일

1) form 태그를 사용하여 필터 검색에 사용할 카테고리/최대값,최소값 선택 후 검색버튼 클릭 시 form태그의 속성 action을 통하여 액션기능을 한다.

2) 데이터 전달 방식은 GET 방식을 사용하여 URL로 어떤 필터를 사용하였는지 확인할 수 있다.

3) 연료와 지역 카테고리는 '다중선택'을 위해 input태그의 type속성 checkbox를 사용하였다.

3-1) 다중선택을 하기 때문에 동일한 name을 가지고 있고, 각각 파라미터 값을 전달할 value 값을 가지고 있다.

4) 가격과 연식 카테고리는 select 태그를 사용하여 최소값/최대값을 선택할 수 있도록 하였다.

4-1) 옵션 태그로 각 전달할 데이터들을 넣었다.

5) 주행거리 카테고리는 범위 슬라이더 플러그인을 사용하여 데이터를 출력하도록 하였다.(사진보다 코드가 더 있다)

6) start = 처음 화면 시작 시 화면에 출력될 최소값과 최대값

step = 범위슬라이더 이동 시 값이 변경되는 범위

range : min = 범위슬라이더의 최소값, max = 범위슬라이더의 최대값

document.getElementById("slider-range-value1").innerHTML = values[0];

=> 해당 id 값을 가지고 있는 태그에 values[0] (최소값) 출력 (최대값 출력도 동일하다)

document.querySelector("input[name='min-value']").value = moneyFormat.from(values[0]);

=> name이 'min-value' 인 input 태그의 value 값을 values[0]으로 지정 => 추후 파라미터 값으로 들어간다.


4. CarSearchAction

1) 연료와 지역의 필터는 '다중선택'하여 검색할 수 있어 필터의 값들을 배열로 저장하도록 하였다.

=> 하나의 name으로부터 여러개의 파라미터 값을 받아와야하기 때문에 getParameterValues를 사용하였고, 이를 String 형의 배열 객체에 저장하였다.

2) DAO에서 사용할 필터 데이터를 위해 배열 객체를 선언하였다.

3) View를 통해 받아온 파라미터 값을 저장한 String 배열( 1)에서 생성한 객체)의 길이만큼 반복문 진행하였다.

4) i 인덱스 값을 ArrayList 객체에 삽입하였다.

5) ArrayList 객체 데이터를 SearchVO의 배열 객체에 저장하였다.

6) 가격/연식/주행거리 필터는 정수형으로 데이터를 출력하기 때문에 형변환을 하여 파라미터 값을 저장하였다.

7) 첫 검색필터 페이지로 이동 시 jsp파일을 거치지 않기 때문에 파라미터 값이 'null'이다. 따라서 null 인 경우 if문을 거치지 않고 지나가게 되고

null이 아닌 경우(=범위 설정을 위해 값을 입력하고 검색한 경우) 최소값, 최대값을 설정하도록 하였다.

** 파라미터 값이 null인 경우 SearchVO에서 선언한 각 int형의 최소값 최대값의 변수들이 0이 되어 처음 검색필터 페이지가 실행 시 전체 데이터가 나오지 않는 문제가 발생하였다.

해결

SearchVO에서 기본 생성자를 생성 후 각 int형 변수에 초기값 설정

각 카테고리 범위의 최소값, 최대값을 초기값 설정하여 처음 페이지 이동 시에 전체 데이터가 나올 수 있도록 하였다.

8) 데이터를 출력하는 메서드 실행, 인자로는 각 조건식을 통해 데이터가 저장된 SearchVO의 객체 svo가 들어간다.

9) View에서 EL 식으로 사용하기 위해 배열 객체 datas의 데이터를 'datas' 속성명으로 저장하였다.


5. selectOption

가격/연식 필터 카테고리에서 범위를 선택 시 최소값 > 최대값 인 경우가 있다.

이 때 최소값 선택 시 최대값은 최소값보다 높은 값의 옵션태그만 출력되도록 하였다.

** 주의점 : 최소, 최대의 select option태그의 개수는 동일해야 작동한다.

1) 각 select태그의 클래스명과 option 태그들을 불러와 상수 지정

2) option태그의 개수를 상수에 저장

최소값 버튼의 onchange 이벤트 발생 시

3) option 개수만큼 반복문이 돌아가며 각 옵션 태그들의 display 속성을 block 처리한다.

4) 선택된 최소값의 index를 minValIndex 상수에 저장

5) 만약 minValIndex가 타입과 데이터 값이 모두 같으며 0 이라면 그대로 반환하여 최대값까지의 모든 option태그들을 보여준다.

6) 5 조건식에 들어가지 않는다면 minValIndex 값만큼 반복하여 최대값 설정하는 option 태그들의 display 속성을 none 처리한다.

ex) 최소값이 5000 으로 선택된다면, 최대값은 5000 미만의 option 태그들을 'none'처리하고 5000 이상의 태그들만 선택할 수 있도록 처리

최대값 버튼의 onchange 이벤트 발생 시

위의 로직과 같다.

7) 아래의 for문에서 최소값 option 태그의 길이만큼 반복 진행하면서 maxValIndex (최대값이 선택된 부분의 index) + 1인 option 태그들의 display 속성을 none 처리한다.

ex) 최대값이 8000 으로 선택된다면, 최소값은 8000 초과되는 option 태그들을 'none'처리하고 8000 이하의 태그들만 선택할 수 있도록 처리


결과

영상 확인  : https://blog.naver.com/yyhhhjun/222864534759

 

[프로젝트] 필터 검색을 통해 원하는 정보 출력하기(ft. FrontController)

프로젝트의 메인 기능인 필터 기능을 구현해보았다. 필터는 연료/지역/가격/주행거리/연식 총 5개의 카테고...

blog.naver.com

필터 검색 시 단일 선택, 다중 선택인 각각의 경우에 원하는 값들이 필터링되어 출력되는 것을 확인하였다.

댓글