본문 바로가기
BackEnd/Project

[PT Manager] Ch04. 이용권 서비스 요구사항 기능 확인

by 개발 Blog 2024. 8. 29.

공부 내용을 정리하고 앞으로의 학습에 이해를 돕기 위해 작성합니다.

이 글에서는 이용권 서비스에 대한 시나리오를 만들어보고 기능 테스트를 진행한다. 테스트를 위한 시나리오는 아래 이미지와 같이 구성되며, 각 단계별로 기능을 확인하게 된다.

 

테스트 시나리오

추가 개발 사항

테스트를 진행하기 전에 추가로 개발해야 할 부분이 있다. Job을 실행하는 방법은 여러 가지가 있는데, 그동안은 스프링 부트를 실행하여 테스트를 진행했다. 그러나 이번 시간에는 REST API를 통해 Job을 실행하는 방법을 사용한다. 이를 위해 JobLauncher라는 인터페이스를 사용할 것이다.

 

JobLauncher는 하나의 메서드만 가지고 있으며, 이 메서드는 실행할 잡(Job)과 잡에 전달할 잡 파라미터를 받아 잡을 실행시키는 역할을 한다. 우리는 REST API를 만들어서 JobLauncher에게 요청(Request)을 전달하여 특정 Job을 실행하도록 할 것이다.

 

REST API를 통한 Job 실행 구현

package com.example.pass.controller;

import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.configuration.JobRegistry;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("job")
public class JobLauncherController {

    private final JobLauncher jobLauncher;

    private final JobRegistry jobRegistry;

    public JobLauncherController(JobLauncher jobLauncher, JobRegistry jobRegistry) {
        this.jobLauncher = jobLauncher;
        this.jobRegistry = jobRegistry;
    }

    @PostMapping("/launcher")
    public ExitStatus launchJob(@RequestBody JobLauncherRequest request) throws Exception {
        Job job = jobRegistry.getJob(request.getName());
        return this.jobLauncher.run(job, request.getJobParameters()).getExitStatus();

    }
}
package com.example.pass.controller;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersBuilder;

import java.util.Properties;

@Getter
@Setter
@ToString
public class JobLauncherRequest {
    private String name;
    private Properties jobParameters;

    public JobParameters getJobParameters() {
        return new JobParametersBuilder(this.jobParameters).toJobParameters();
    }
}

 

YAML 설정

서버 포트가 겹치지 않도록 8081 포트를 추가 설정한다.

server:
  port: 8081

테스트 진행

첫 번째 시나리오 : 이용권 일괄 지급

이 시나리오에서는 특정 회원 그룹에 대해 이용권을 일괄 지급하는 기능을 테스트한다. 이를 통해 배치 작업이 정상적으로 동작하여, 각 회원에게 지정된 이용권이 올바르게 지급되는지 확인한다.

 

이용권 일괄 지급 준비

특정 회원 그룹에게 이용권을 일괄 지급하기 위해 bulk_pass 테이블에 관련 데이터를 등록한다. 이 데이터는 각 회원 그룹에 대해 지급될 이용권 정보, 시작 일시 및 종료 일시 등의 정보를 포함한다.

  • SAMDE400 그룹: 무료 이벤트 파워리프팅 PT 1회
  • SAMDE500 그룹: 고급 PowerLifting PT 50회
  • SAMDE600 그룹:  바디 챌린지 PT 8주 

이렇게 해서 이용권을 일괄지급 해보겠다.

 

배치 실행

Talend API Tester와 같은 도구를 사용해 addPassesJob을 POST 요청으로 실행한다.

 

이용권 지급

배치 작업이 실행되면, bulk_pass 테이블의 데이터를 기반으로 각 회원에게 지정된 이용권이 지급된다.

이 과정에서 배치 작업은 각 회원의 pass 테이블에 관련 데이터를 삽입하여, 회원이 이용할 수 있는 PT 이용권을 생성한다.

결과 확인

  • 배치 작업이 완료된 후, bulk_pass 테이블의 status가 "지급 완료"로 변경되며, 각 회원에게 지급된 이용권이 pass 테이블에 기록된다.
  • 관리자는 웹 페이지를 통해 각 회원 그룹별로 이용권이 정상적으로 지급되었는지 확인할 수 있다.

DB 및 웹 페이지 확인

DB의 user, pass, bulk_pass 테이블을 확인하여 데이터가 올바르게 반영되었는지 확인한다.

 

user 테이블

 

pass 테이블

 

bulk_pass 테이블

 

마지막으로, 회원별로 웹페이지에서 해당 이용권을 조회해 본다. 각 그룹별로 정상적으로 이용권이 지급되었는지 확인할 수 있다.

 

3대 400그룹 

 

3대 500그룹

 

3대600그룹

두 번째 시나리오: 취소된 예약에 대한 통계 집계

이 시나리오에서는 booking 테이블에 9월 10일 자로 취소된 예약 데이터를 추가하고, Job을 실행하여 취소 건수가 1 증가하는지 확인한다.

 

동작 원리

  • 데이터 조회
    • 배치 작업이 시작되면, 지정된 기간(예: 2024-09-01 00:00부터 2024-09-11 00:00까지)의 예약 데이터를 BookingEntity 테이블에서 조회한다.
    • 이때 cancelled_at 컬럼에 값이 있는(즉, 예약이 취소된) 데이터를 기준으로 통계 집계가 진행된다.
  • 통계 집계
    • 조회된 예약 데이터 중에서 cancelled_at 컬럼에 값이 있는 경우, 이는 취소된 예약으로 간주된다.
    • 배치 작업은 해당 날짜에 대한 StatisticsEntity의 cancelled_count 값을 증가시킨다.
  • 통계 저장
    • 집계된 통계 데이터는 Statistics 테이블에 저장된다.
    • 이 과정에서 취소된 예약 수(cancelled_count)가 증가하게 된다.

테스트 시나리오 수행

사전 작업

booking 테이블에 9월 10일 자로 취소된 예약 데이터를 추가한다. 이 데이터는 cancelled_at 필드에 날짜 값이 들어가게 된다.

 

배치 실행

Talend API Tester를 사용해 makeStatisticsJob을 POST 요청으로 실행한다.

 

결과 확인

 

  • 배치가 완료된 후, Statistics 테이블에서 9월 10일의 cancelled_count가 1로 증가한 것을 확인할 수 있다.
  • 이는 배치 작업 중에 BookingEntity 테이블의 cancelled_at 필드에 값이 있는 데이터를 발견하여, 해당 취소된 예약이 통계에 반영되었기 때문이다.

회고 및 마무리

이번 프로젝트에서는 서비스 요구사항에 맞춰 데이터를 설계하고, 총 8개의 테이블에 이용권 서비스 데이터를 저장하였다. 이를 바탕으로 배치를 개발하였으며, 총 5개의 Job을 다양한 flow로 구현하였다. 특히, Tasklet, Chunk, 멀티 스텝, 스텝 내 멀티스레드 수행, 아이템 프로세서와 아이템 라이터를 비동기로 실행하는 방식, 그리고 스텝 자체를 병렬로 처리하는 등 다양한 배치 플로우를 적용해 보았다. 이는 대부분의 서비스 요구사항에서 활용할 수 있는 유용한 기술들이다.

 

또한, 타임리프(Thymeleaf)를 사용하여 웹 페이지를 구현하였다. 사용자가 이용권을 조회할 수 있는 화면과 관리자가 이용권을 등록하고 조회할 수 있는 어드민(Admin) 화면을 구축하여 테스트 시나리오를 만들었다. 이를 통해 실제 데이터가 생성되고 활용되는 과정을 눈으로 확인할 수 있었다.

 

이번 프로젝트를 통해 배치 프로세스와 웹 인터페이스의 연동, 그리고 데이터베이스 설계 및 운영에 대한 전반적인 이해를 높일 수 있었다. 다양한 기술을 실습하며 실질적인 요구사항을 충족시키는 프로젝트를 수행했다는 점에서 큰 성과가 있었다고 평가한다. 이번 경험을 토대로 더욱 발전하는 개발자가 되기 위해 노력할 것이다.