[SPRING] 배치 어플리케이션 트리거로 Jenkins 어떤데?

wannabeing·2025년 6월 13일
1

SPRING

목록 보기
16/16
post-thumbnail

우리는 구독 기반의 메일 전송 서비스!

  • 매일 10,000명 이상의 메일 발송을 해야한다는 가정을 해보자.

단순히 @Scheduled만 사용하면 되는 걸까?

@Scheduled 어노테이션을 메서드에 붙여주면 특정 시간마다 작업을 실행할 수 있다.
작은 규모의 작업이라면 괜찮지만, 대규모 메일 전송 작업에는 여러 문제가 있다.

  • 500번까지 성공하고 501번에 실패했을 때, 로직을 어떻게 짤 것인가?
  • 단일 쓰레드기반의 스케줄러이기 때문에 서버가 여러대일 경우, 중복실행이 될 수도 있다.

❓ 우리는 어차피 서버(EC2)가 1개인데?

  • 대규모 데이터를 다루는 과정 속에서 사용자 요청이 들어왔을 때, 서버가 버틸 수 있을까? 느려지지는 않을까?

위와 같은 문제점들 때문에 우리는 안정적으로 서버를 실행시킬 수 있는 구조가 필요했다.

배치 프레임워크 (Spring Batch)

바로 배치 어플리케이션 프레임워크인 Spring Batch이다.

배치 어플리케이션 ?

  • 사람과 상호작용이 없는 프로그램들의 실행
  • QA 업무가 힘들기 때문에 테스트 코드가 필연적이다.

❓ vs 웹 어플리케이션과의 차이점

웹 어플리케이션은 사용자 요청에 따라 항상 실행 상태이어야 한다.
배치 어플리케이션은 정해진 작업(Job)이 끝나면 종료되면 된다.

배치 어플리케이션이 필요한 상황

  • 일정 주기로 실행되어야 한다.
  • 실시간 처리가 어려운 대규모 데이터 처리가 필요하다.

💡 스프링 배치를 사용함으로서, 부가적인 고민들을 프레임워크에 맡기거나 지원받고, 개발자는 비즈니스 로직에만 집중할 수 있게 된다!


그럼 이 배치 어플리케이션을 어떻게 실행시킬까?

Spring Batch 로직만 작성한다고 자동으로 실행되진 않는다.
정해진 시간에 트리거(trigger)가 배치 애플리케이션을 실행해줘야 한다.

똑같은 스프링 프로젝트가 있을 때, CLI 명령어를 통해서 웹 어플리케이션 용도로, 배치 어플리케이션 용도로 실행시킬 수 있다.

배치 어플리케이션은 웹 어플리케이션과 다르게 계속 실행중일 필요가 없다.
주어진 업무(Job)만 완료하면 종료되어도 상관없기 때문이다.

여러 트리거(스케줄러)를 찾아보자.

1안) Quartz(쿼츠) 프레임워크 사용

  • 쿼츠는 스케줄링 프레임워크이다.
    ex. 매일 9시에 Batch 작업을 실행
  • 배치는 누군가가 실행시켜줘야 하는데, 그 역할을 쿼츠가 해줄 수 있다.
  • 따라서 쿼츠는 배치 어플리케이션을 도와주는 역할이다.

장/단점

  • 정밀한 스케줄링이 가능하고, 다양한 기능을 제공한다.
  • 하지만 그에 상응하는 학습 곡선이 있다고 생각했다.
  • 실제로 구현은 쉬웠지만, 코드를 이해하는데 어려웠다. ㅠ
  • 또한 보여지는 페이지가 없기에 보통 커스텀으로 만든다고 한다는 점도 걸렸다.

2안) SCDF/TeamCity (CI/CD)

Spring Cloud Data Flow (SCDF)

  • SCDF는 스프링에서 공식적으로 Batch 작업을 도와주는 툴이다.
  • 올 해 4월이후 유료로 전환되었고, 오픈소스 버전은 유지보수가 진행되지 않는다고 한다.

TeamCity (JetBrain 제품)

  • UI/UX도 직관적이고 다른 젯브레인 도구들과 연동도 잘되어있다고 한다.
  • 자료조사를 하면서 두번째로 끌렸던 트리거이다.
  • 하지만 유료인점이...

2안 모두 3안 대비해서 국내 사례가 적기 때문에 제외되었다.

✅ 3안) Jenkins (CI/CD)

  • 2안과 마찬가지로 CI/CD 툴이지만 충분히 트리거 역할에 적합하다.
  • CI/CD 툴이지만 배치 트리거 역할도 가능
  • 웹 UI로 실행 이력, 로그 관리가 편리하다.
  • 다양한 플러그인, 알림 연동(Slack 등), 수동/자동 실행 지원
  • 실제 현업에서도 널리 사용되고 있다.

마지막으로 현업에서도 CI/CD 툴로도 많이 사용하므로, 어떻게든 배워두면 좋겠다는 팀원분들의 의견도 있어서 3안으로 결정하게 되었다.

단점도 있다.

  • t2.micro같은 작은 사이즈의 서버에서 웹/배치 어플리케이션이 동시에 실행될 때, 서버가 힘들어하니 배치 서버를 따로 둬야될 것 같았다..
    우리 배치작업이 많지도 않은데 배치서버를 따로 두는건 오버스펙 같았지만,
    여러 서버를 동시에 사용하면서 얻는 경험도 있을 거라 생각한다.
  • GitActions도 있었지만, DB와의 커넥션으로 비용이 들어가는건 매한가지고, 지원되는 기능이 젠킨스가 더욱 많다고 생각했고, 어드민페이지도 있기에 젠킨스로 마음이 기울었다.

어떻게 실행했어요?

젠킨스 내부에 있는 스케줄러 기능으로 시간을 정해줬다.
여러 방법이 있지만 나는 아래와 같은 명령어를 사용하였다.

java -jar ${JAR_PATH}/app.jar \
	--spring.batch.job.name=${JOB_NAME} \
	--spring.batch.job.enabled=true
	--spring.main.web-application-type=none

그림으로 보여주셈.

운영서버(EC2)

먼저 왼쪽은 일반 웹 서비스가 돌아가는 운영 서버 EC2이다.
스프링부트 기반의 웹 애플리케이션이 도커 안에서 동작하고 있고,
사용자 요청을 실시간으로 처리한다.


배치서버(EC2)

운영서버와 배치서버를 물리적으로 분리해서 리소스 간섭을 피하고,
배치 작업시 서비스 영향도 최소화할 수 있게 하였다.


Jenkins 역할

배치 서버 안에는 Jenkins가 설치되어 있다.
Jenkins는 지정된 시간마다 트리거 역할을 수행하고,
GitHub에서 main 브랜치를 pull 받아서 최신 배치 jar 파일을 확보한 뒤,
java -jar 명령어를 통해 CLI 방식으로 배치 앱을 실행한다.
(doceker 명령어를 사용해도 됨!)

실제 현업에서는 Git Repository가 private이므로,
S3에 배포된 운영서버 *.jar 파일을 저장해놓으면
Jenkins가 S3에 접근해서 최신 배치 jar파일을 가져오는 형식을 사용한다고 한다.


배치 어플리케이션 실행

실행된 스프링 배치 어플리케이션은 도커 내에서 실행되고,
RDS의 MySQL에 접근해 대상 데이터를 조회한 뒤,
메일을 발송하는 작업을 수행한다.


작업 종료 후

모든 배치 작업이 끝나면 애플리케이션은 종료된다.


추후

Grafana/Prometheus 도입

실행 이력/ 로그관리를 Jenkins로만 하기엔 부족할 것 같다는 피드백을 받았다.
따라서 두 소프트웨어를 도입해서 프로젝트를 고도화하고자한다.

Jenkins 대신 AWS Lambda 고려

배치 어플리케이션을 자주 돌리지 않고, 작업(Job)이 많지 않으면 AWS lambda가 어떠냐는 피드백을 받았다. 아무래도 작업 하나에 EC2 하나가 쌩으로 돌아가는 것보다 좋을 것 같다는 생각이다. 추후 적용해보고자 한다.

느낀.

CI/CD 툴이라고 해서 꼭 배포 작업에만 사용하는 건 아니라는 걸 이번 경험을 통해 깨달았다.
기술을 선택하고 적용하는 과정에서 왜 이걸 써야 하는지,
각 도구가 가진 장점과 단점은 무엇인지 스스로 고민해보게 되었다.
한층 더 시야가 넓어졌고, 앞으로 어떤 기술을 도입할 때도 열린마음을 갖자.


출처

https://theliar.tistory.com/14
https://mjin1220.tistory.com/57
https://jojoldu.tistory.com/489
https://soobindeveloper8.tistory.com/1015
[영상] Jenkins로 배포하기
[영상] Spring Batch 애플리케이션 성능 향상을 위한 주요 팁
[영상] 우아한테크세미나 배치 관리도구로서의 Jenkins

profile
wannabe---ing

1개의 댓글

comment-user-thumbnail
2025년 6월 16일

정말 유익하네요 &^^

답글 달기