Skip to content

빅데이터를 이용한 전국 시장 농식품 현황 검색 시스템(가격,품질,가격 변동 현황, 지도 서비스)

Notifications You must be signed in to change notification settings

qkrqudcks7/Market_Project

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 

Repository files navigation

지역시장 지킴이 ( 농식품 유통 빅데이터 프로젝트 )


프로젝트 설명

image

한국농수산식품유통공사에서 제공받은 농식품 유통 빅데이터를 기반으로 제작.

전국의 전통시장들을 대상으로 농식품들에 대한 정보를 검색할 수 있는 페이지.

전국의 시장별 , 품목별 , 가격별 , 품질별 , 도-소매 별 검색 카테고리 제공.

가격별, 품질별 도-소매별 우선정렬로 필터링 검색 기능 제공

카카오 지도 api를 이용한 위치 정보 제공

1년 단위의 월별 가격 변동 사항 제공, (평균가 , 상한가 , 하한가)


front

Thymeleaf 템플릿

back: Spring boot , Spring Data JPA , Query DSL , Postgresql

1. postgresql에 xlsx 파일 저장

빅데이터 엑셀 파일에 결측치를 제거하고 정제하는 과정을 가짐. 저장할 때 csv파일로 바꿔 저장함. db에 엑셀 연동 저장방식 중, csv 저장 방식을 사용하기 위함.

엑셀 항목 중 가격, 상품명 , 품질 등과 같은 필수적인 컬럼은 nullable=false , 그 외 나머지 값들은 nullable=true 지정.

맵핑하기 위한 각각의 Long 타입 id값 생성

csv 저장 성공 후, spring boot와 연동


spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/--------
    driver-class-name: org.postgresql.Driver
    username: ------
    password: -----
 
 

2. MVC 패턴

Repository - Service - domain - dto - controller 방식으로 구현


3.1. 카테고리별 검색(Spring Data Jpa , Query Dsl)

image


Page findMainByKeyword2(String keyword,Pageable pageable,String priority);
 
 

위 코드와 같이 검색 단어인 keyword 변수 , 페이징 처리를 위한 pageable 변수 , 가격 품질 등의 카테고리를 뜻하는 priority 변수를 참조.

 
NumberExpression productRankPath = new CaseBuilder()
                .when(main2.productRank.eq("유기농")).then(1)
                .when(main2.productRank.eq("무농약")).then(2)
                .when(main2.productRank.eq("무항생제")).then(3)
                .when(main2.productRank.eq("상품")).then(4)
                .when(main2.productRank.eq("중품")).then(5)
                .when(main2.productRank.eq("M과")).then(6)
                .when(main2.productRank.eq("S과")).then(7)
                .when(main2.productRank.eq("1+등급")).then(8)
                .when(main2.productRank.eq("1등급")).then(9)
                .when(main2.productRank.eq("냉장")).then(10)
                .otherwise(11);
 
 

가격과 같은 우선순위는 orderby로 쉽게 정렬할 수 있다. 또한 ㄱ,ㄴ,ㄷ 순의 문자일 경우도 마찬가지이다. 하지만 위와 같은 카테고리일 경우 커스텀 정렬이 필요하다. 예를들어 NumberExpression 방법을 쓸 수 있다. new caseBuilder()를 통해 정렬의 우선순위를 내가 임의로 정할 수 있다. if else와 비슷하다고 볼 수 있다. 유기농일 경우 1순위 ... 냉장이면 10 순위와 같은 방식이다.

 
JPQLQuery query = from(main2).where(main2.day.eq(20191108)
                .and(main2.itemName.contains(keyword)));

        if(priority.equals("가격높은순")){
            query=query.orderBy(main2.price.desc());
        }
        if(priority.equals("가격낮은순")){
            query=query.orderBy(main2.price.asc());
        }
        if(priority.equals("품질높은순")){
            query=query.orderBy(productRankPath.asc());
        }
        if(priority.equals("품질낮은순")){
            query=query.orderBy(productRankPath.desc());
        }
        if(priority.equals("도매")) {
            query=query.orderBy(productClsRankPath.asc());
        }
        if(priority.equals("소매")) {
            query=query.orderBy(productClsRankPath.desc());
        }
 
 

따라서 NumberExpression으로 제작한 커스텀 정렬을 productRankPath의 변수에 담아 query DSL로 작성할 수 있다. 전체적인 코드를 설명하면, main2 도메인으로부터 날짜가 2019-11-8이고 아이템 이름이 keyword에 해당하면 다음과 같은 정렬을 이룬다는 것이다. 필자가 설명한 것처럼 가격은 desc나 asc로 편하게 작성할 수 있지만 , 품질과 같은 카테고리는 커스텀 정렬을 한 것을 볼 수 있다.


3.2. 3중 필터링 정렬 검색

image image

쉽게 설명하면 예를 들어, 고객이 1순위로 가격이 낮은순 2순위로 품질이 높은순 3순위로 소매가인 상품을 보고 싶은 것이다.


Page findByKeyword(String keyword, String nation, Pageable pageable,String priority1,String priority2,String priority3);
 
 

3개의 필터가 필요하기 때문에 priority 변수도 총 3개를 불러왔다. (nation은 지역을 의미하는 변수이다)


JPQLQuery query = from(main).where(main.stateName.eq(nation)
                .and(main.day.eq(20191108))
                .and(main.itemName.contains(keyword)));

        if(priority1.equals("가격높은순")){
            query=query.orderBy(main.price.desc());
        }
        if(priority1.equals("가격낮은순")){
            query=query.orderBy(main.price.asc());
        }
        if(priority1.equals("품질높은순")){
            query=query.orderBy(productRankPath.asc());
        }
        if(priority1.equals("품질낮은순")){
            query=query.orderBy(productRankPath.desc());
        }
        if(priority1.equals("도매")) {
            query=query.orderBy(productClsRankPath.asc());
        }
        if(priority1.equals("소매")) {
            query=query.orderBy(productClsRankPath.desc());
        }

        if(priority2.equals("가격높은순")){
            query=query.orderBy(main.price.desc());
        }
        if(priority2.equals("가격낮은순")){
            query=query.orderBy(main.price.asc());
        }
        if(priority2.equals("품질높은순")){
            query=query.orderBy(productRankPath.asc());
        }
        if(priority2.equals("품질낮은순")){
            query=query.orderBy(productRankPath.desc());
        }
        if(priority2.equals("도매")) {
            query=query.orderBy(productClsRankPath.asc());
        }
        if(priority2.equals("소매")) {
            query=query.orderBy(productRankPath.desc());
        }

        if(priority3.equals("가격높은순")){
            query=query.orderBy(main.price.desc());
        }
        if(priority3.equals("가격낮은순")){
            query=query.orderBy(main.price.asc());
        }
        if(priority3.equals("품질높은순")){
            query=query.orderBy(productRankPath.asc());
        }
        if(priority3.equals("품질낮은순")){
            query=query.orderBy(productRankPath.desc());
        }
        if(priority3.equals("도매")) {
            query=query.orderBy(productClsRankPath.asc());
        }
        if(priority3.equals("소매")) {
            query=query.orderBy(productClsRankPath.desc());
        }
 
 

이런 방식으로 각각 priority1 , 2 , 3 순서로 그에 해당하는 우선순위를 배당하는 방법이다. 확실히 노가다성이 보여, 좋은 코드는 아닌 것 같다. 일단 직접 페이지에서 쇠고기를 검색해본 결과(가격 낮은순, 품질 높은순 , 소매가) 가격이 7000원으로 같으면 품질이 높은 소고기를 우선으로 보여주는 정렬이 확인 되었다. 위 코드를 간추려 더 좋은 기능을 하는 코드를 만들려면 고민을 많이 해봐야 할 것 같다.


4. 카카오 지도 API

image

Link: Kakao Developer

카카오 지도 api를 사용하여 각 시장별 위치 서비스를 제공하였다. 우선 kakao developer에서 map api를 받아온다. 그 다음 js에 api key를 저장하고 각종 기능들을 구현한다. 각 시장들의 위치 좌표를 작성하여 저장하는 방식으로 구현하였다. 따라서 그 좌표를 보내주면 바로 그 시장을 볼 수 있다.


// 맨 오른쪽 변수 이름 수정하여 지도 변경 가능
const map = new kakao.maps.Map(container, mapName);

// 일반 지도와 스카이뷰로 지도 타입을 전환할 수 있는 지도타입 컨트롤 생성
var mapTypeControl = new kakao.maps.MapTypeControl();

map.addControl(mapTypeControl, kakao.maps.ControlPosition.TOPRIGHT);

// 지도 확대 축소를 제어할 수 있는 컨트롤 생성
var zoomControl = new kakao.maps.ZoomControl();
map.addControl(zoomControl, kakao.maps.ControlPosition.RIGHT);

// 마커 표시 위치
var markerPosition = mapName.center;

// 마커 생성
var marker = new kakao.maps.Marker({
    position: markerPosition
});
 
 

5. 각 제품들의 월별 가격 변동 현황 사진

image

About

빅데이터를 이용한 전국 시장 농식품 현황 검색 시스템(가격,품질,가격 변동 현황, 지도 서비스)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published