본문 바로가기
Spring Batch

Spring Batch 개발기 ( 5. 영화진흥위원회 API )

by SICDev 2021. 9. 9.
반응형

영화진흥위원회에서 API를 가져와보자~😵

http://www.kobis.or.kr/kobisopenapi/homepg/main/main.do

 

영화진흥위원회 오픈API

OPEN API 서비스 영화진흥위원회 영화관입장권통합전산망에서 제공하는 오픈API 서비스로 더욱 풍요롭고 편안한 영화 서비스를 즐겨보세요.

www.kobis.or.kr


회원가입을 하고 키를 발급받자!!

 

친절하게 jar파일로 라이브러리를 제공해준다..😱

다운로드 페이지에 들어가서 rest 서비스 호출 jar파일을 다운로드받자!


IntelliJ를 키고 build.gradle 파일에 다운받은 라이브러리와 json데이터를 처리해주기 위한 json-simple 라이브러리를 추가해주자❗❗

 

plugins {
    id 'org.springframework.boot' version '2.5.1'
    id 'io.spring.dependency-management' version '1.0.11.RELEASE'
    id 'java'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation files('libs/kobis-opcl-rest-v1.0.jar')
    implementation 'com.googlecode.json-simple:json-simple:1.1.1'
    implementation 'org.springframework.boot:spring-boot-starter-batch'
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-jdbc'
    compileOnly 'org.projectlombok:lombok'
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'mysql:mysql-connector-java'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.batch:spring-batch-test'
}

test {
    useJUnitPlatform()
}

일별 박스오피스를 가져와보자❗❗

API를 가져와서 DB에 넣을 것이기 때문에 api 패키지와 domain인 패키지를 생성한다


JPA를 사용해서 데이터를 넣을것이기 때문에 도메인부터 작성해보자

일별 박스오피스에서 response 해주는 data들을 다 넣을 거다❗

 

DailyMovie.java

package com.example.batchtest.domain;

import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;

import javax.persistence.*;
import java.time.LocalDateTime;

@Data
@Entity
public class DailyMovie {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "daily_movie_id")
    private Long id;

    /*박스오피스 종류*/
    private String boxofficeType;

    /*박스오피스 조회 일자*/
    private String showRange;

    /*순번*/
    private String rnum;

    /*해당일자의 박스오피스 순위*/
    private String rank;

    /*전일대비 순위의 증감분*/
    private String rankInten;

    /*랭킹에 신규진입여부 “OLD” : 기존 , “NEW” : 신규*/
    private String rankOldAndNew;

    /*영화의 대표코드*/
    private String movieCd;

    /*영화명(국문)*/
    private String movieNm;

    /*영화의 개봉일*/
    private String openDt;

    /*해당일의 매출액*/
    private String salesAmt;

    /*해당일자 상영작의 매출총액 대비 해당 영화의 매출비율*/
    private String salesShare;

    /*전일 대비 매출액 증감분*/
    private String salesInten;

    /*전일 대비 매출액 증감 비율*/
    private String salesChange;

    /*누적매출액*/
    private String salesAcc;

    /*해당일의 관객수*/
    private String audiCnt;

    /*전일 대비 관객수 증감분*/
    private String audiInten;

    /*전일 대비 관객수 증감 비율*/
    private String audiChange;

    /*누적관객수*/
    private String audiAcc;

    /*해당일자에 상영한 스크린수*/
    private String scrnCnt;

    /*해당일자에 상영된 횟수*/
    private String showCnt;

    /*DB 저장 일자*/
    private String targetDt;

    @CreationTimestamp
    private LocalDateTime modification_date_time;
}

 

 

레포지토리도 만들어주자❗

 

DailyMovieReposiroty.interface

package com.example.batchtest.domain;

import org.springframework.data.jpa.repository.JpaRepository;

public interface DailyMovieRepository extends JpaRepository<DailyMovie, Long> {
}

 

그럼 이제 api를 호출해서 DB에 넣는 코드를 만들어보자❗

주석을 달아놓았으니.. 설명은 패스한다..❗

 

BoxOfficeApi.java

package com.example.batchtest.api;

import com.example.batchtest.domain.DailyMovie;
import com.example.batchtest.domain.DailyMovieRepository;
import com.fasterxml.jackson.databind.ObjectMapper;
import kr.or.kobis.kobisopenapi.consumer.rest.KobisOpenAPIRestService;
import lombok.RequiredArgsConstructor;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Component
@RequiredArgsConstructor
public class BoxOfficeApi {

    private final DailyMovieRepository dailyMovieRepository;

    //발급키
    String key = "발급받은키를 넣으세요";

    public void dailyBoxOffice(){

        String dailyResponse = "";

        //전날 박스오피스 조회 ( 오늘 날짜꺼는 안나옴.. )
        LocalDateTime time = LocalDateTime.now().minusDays(1);
        String targetDt =  time.format(DateTimeFormatter.ofPattern("yyyMMdd"));

        //ROW 개수
        String itemPerPage = "10";

        //다양성영화(Y)/상업영화(N)/전체(default)
        String multiMovieYn = "";

        //한국영화(K)/외국영화(F)/전체(default)
        String repNationCd = "";

        //상영지역별 코드/전체(default)
        String wideAreaCd = "";

        try {
            // KOBIS 오픈 API Rest Client를 통해 호출
            KobisOpenAPIRestService service = new KobisOpenAPIRestService(key);

            // 일일 박스오피스 서비스 호출 (boolean isJson, String targetDt, String itemPerPage,String multiMovieYn, String repNationCd, String wideAreaCd)
            dailyResponse = service.getDailyBoxOffice(true, targetDt, itemPerPage, multiMovieYn, repNationCd, wideAreaCd);

            //JSON Parser 객체 생성
            JSONParser jsonParser = new JSONParser();

            //Parser로 문자열 데이터를 객체로 변환
            Object obj = jsonParser.parse(dailyResponse);

            //파싱한 obj를 JSONObject 객체로 변환
            JSONObject jsonObject = (JSONObject) obj;

            //차근차근 parsing하기
            JSONObject parse_boxOfficeResult = (JSONObject) jsonObject.get("boxOfficeResult");

            //박스오피스 종류
            String boxofficeType = (String) parse_boxOfficeResult.get("boxofficeType");

            //박스오피스 조회 일자
            String showRange = (String) parse_boxOfficeResult.get("showRange");

            ObjectMapper objectMapper = new ObjectMapper();
            JSONArray parse_dailyBoxOfficeList = (JSONArray) parse_boxOfficeResult.get("dailyBoxOfficeList");
            for(int i=0; i<parse_dailyBoxOfficeList.size(); i++){
                JSONObject dailyBoxOffice = (JSONObject) parse_dailyBoxOfficeList.get(i);
                //JSON object -> Java Object(Entity) 변환
                DailyMovie dailyMovie = objectMapper.readValue(dailyBoxOffice.toString(), DailyMovie.class);
                //DB저장
                dailyMovie.setTargetDt(targetDt);
                dailyMovie.setBoxofficeType(boxofficeType);
                dailyMovie.setShowRange(showRange);
                dailyMovieRepository.save(dailyMovie);
            }
        }catch(Exception e){
            e.getMessage();
        }
    }
}

application.yml 파일을 수정 안 했다.. 아차차... JPA관련 소스를 추가해보자❗

spring:
  datasource:
    hikari:
      driver-class-name: com.mysql.cj.jdbc.Driver
      jdbc-url: jdbc:mysql://ip:3306/DB명
      username: 아이디
      password: 비밀번호
  jpa:
    open-in-view: true
    hibernate:
      ddl-auto: create
      naming:
        physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
      use-new-id-generator-mappings: false
    show-sql: true
    properties:
      hibernate:
        format_sql: true

api를 호출하는 service단도 만들자😎

간단하게만 만들어보자 api가 잘 호출되는지만 확인할 것이기 때문에👍

package com.example.batchtest.service;

import com.example.batchtest.api.BoxOfficeApi;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class BoxOfficeApiService {

    private final BoxOfficeApi boxOfficeApi;

    public void insertDailyBoxOffice(){
        boxOfficeApi.dailyBoxOffice();
    }
}

모든 준비는 완료되었다..❗

 

이전에 만들어 놓은 BatchConfig에서 insertDailyBoxOffice()를 호출해서 배치를 실행시켜보자❗❗

 

package com.example.batchtest.job;

import com.example.batchtest.service.BoxOfficeApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.JobScope;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Slf4j
@RequiredArgsConstructor
@Configuration
public class BatchConfig {
    private final JobBuilderFactory jobBuilderFactory;
    private final StepBuilderFactory stepBuilderFactory;
    private final BoxOfficeApiService boxOfficeApiService;

    @Bean
    public Job testJob() {
        return jobBuilderFactory.get("testJob")
                .start(testStep(null))
                .build();
    }

    @Bean
    @JobScope
    public Step testStep(@Value("#{jobParameters[testParameter]}") String testParameter ) {
        return stepBuilderFactory.get("testStep")
                .tasklet((contribution, chunkContext) -> {
                    boxOfficeApiService.insertDailyBoxOffice();
                    return RepeatStatus.FINISHED;
                })
                .build();
    }
}

 

파라미터는 오늘 날짜로 설정하고 실행❗❗❗ 두둥두둥...

 

 


로그를 보면

ddl 옵션이 create이기 때문에 테이블을 드랍하고 새로 생성한다❗

 

그리고❗❗ insert문을 날려 DB에 값이 들어갔다👍👍

 

DB를 확인해보면 아주 잘 들어간 것을 확인해볼 수 있다👍


다음엔 제대로 된 Job을 만들고 스프링 스케쥴러를 이용해서 반복적으로 job을 실행시켜보겠다👍

반응형