Contents

우아한 스프링 배치 테크세미나 정리 및 후기 (by 우아한 형제들)

지난주 우아한 형제들에서 진행하였던 “9월 우아한 테크 세미나 - 우아한 스프링 배치” 에 다녀왔다. 필자에게 이번 9월은 정신이 어디에 있는지 모를만큼 바쁘고 힘들었지만 예전부터 궁금하기도 했고 요즘들어 관심을 갖던 “배치 어플리케이션"을 어떻게 하면 “우아한 방법"으로 사용할 수 있을지에 대해 여러 생각들이 있었기에 큰 기대를 가지고 지옥철을 견디며 잠실 근처에 있는 우아한 형제들 작은집으로 가게 되었다. 어떤 내용을 발표하였는지에 대해 기억잘하는 똑똑한 앵무새가 되어 정리하기 보다 주요 포인트에 대한 생각과 함께 참여를 못한 분들 위해서라기 보다 내 스스로 정리를 하기 위해 포스팅을 작성해 보고자 한다. (이번에도 불러주셔서 감사합니다 ^=^)

인트로

연사자 분은 워낙에 유명하신 분이라 별도의 설명이 필요 없이 운영하시는 블로그 주소로 대체를 해본다. 이번 행사에 초대되신 분들은 한번이라도 스프링 배치를 써분 분들을 대상으로 진행하게 되었다고 했는데 마침 필자도 팀 내에서 운영하고 있는 배치 어플리케이션을 보다 효율적이고 우아하게 바꿔보고자 하는 니즈가 있었기에 아마 초대된게 아닐까 싶다.

/images/woowabros-spring-batch/small_house.jpg
아기자기한 우아한 형제들 건물 내부

더불어 발표전에 간략히 회사가 원하는 인재에 대하여 언급해주셨는데 그게 어찌나 공감이 가던지. 역시 생각이 남다른 회사구나 하고 다시한번 생각을.

자기보다 경험이 “적은” 사람에게 “설득을 당할 수” 있어야 하고, 자기보다 경험이 “많은 사람을 설득” 시킬 수 있어야 한다.

기본편

배치 어플리케이션이란 컴퓨터에서 사람와 상호작용없이 이어지는 프로그램(작업)들의 실행이라고 위키피디아에 간결&명료하게 정리되어 있다. 그만큼 일반적인 웹 어플리케이션과의 차이가 있는데 웹 어플리케이션은 실시간 처리가 기본이고 요청에 대한 응답을 제공해야 하니 아무래도 속도가 상대적이며 QA시 편한 부분이 있다. 그에 반해 배치 어플리케이션은 웹 어플리케이션에서 말하는 요청이라는 개념보다 후속처리에 가깝고, 속도 또한 절대적이며 QA가 복잡하다는게 특징이다. 따라서 테스트코드는 웹 어플리케이션 보다 배치 어플리케이션이 더 필요하다고 볼 수 있다. 배치 어플리케이션이 필요한 상황은 크게 두가지로 나눠 볼 수가 있다고 한다.

  • 일정 주기로 실행 되어야 할 때
  • 실시간 처리가 어려운 대량의 데이터를 처리 할때

평소 첫번째 상황만 생각하고 배치 어플리케이션을 작성하곤 했었는데 두번재 상황에 대해 생각에 생각을 더 해보니 스프링 배치를 간단하게만 (Tasklet) 사용하고 있는건 아닌가 하는 반성을 해보곤 했다. (Reader, Processor, Writer 등 다양한 레이어가 있는데도…)

특히 스프링 배치에서는 기본적으로 모든 데이터를 메모리에 쌓지 않는 조회방식라고 한다. (DB기준) Paging 혹은 Cursor로 pageSize만큼만 읽어오고 chunkSize만큼만 commit 하는 형태. 이러한 각 레이어별 size를 잘 조정하기만 해도 적은 노력으로 큰 성능을 얻을 수 있는 부분이 프레임워크를 사용하는 이유 아닐까 라고 생각해본다.

또한 @JobScope@StepScope는 Late Binding 즉 배치 어플리케이션이 실행되는 시점이 아니라 Job 이 실행될때 생성이 되기 때문에 이를 활용하여 동적으로 reader / processor / wirter 레이어를 만들 수 있다고 한다.

활용편

스프링 배치를 이용한 배치 어플리케이션이 있고 이를 스케쥴링 등 관리를 해주는 도구들에 이야기를 해주셨다.

  • Cron
    • 리눅스를 어느정도 사용해봤다면 알만한 리눅스 기본 스케쥴링 프로그램인 Cron.
    • 필자도 Cron 으로 주기적으로 실행하도록 설정해보기도 하였지만 배치 어플리케이션의 특성상 로그 및 실행/종료 등 제한사항이 많은 건 사실인것 같다.
  • Spring MVC + API Call
    • 주변에서 사용하고 있다고 하던 방식. 이 방식의 장점은 항상 떠있기 때문에 어플리케이션 구동시간이 별도로 필요 없다는 장점이 있지만 전반적인 관리가 어려운 단점이 있는것 같다.
    • 물론 울며 겨자먹기 식으로 단점을 극복할 방법은 여러가지가 있겠지만 모든건 항상 Trade off
  • Spring Batch Admin (Deprecated)
    • 예전 팀분이 알려주셔서 잠깐 봤던 부분이긴 한데 어느사이에 Deprecated 되었다고 한다.
  • Quertz + Admin
    • http://www.quartz-scheduler.org/
    • 아주 오래전에 써본 기억이 있지만 배보다 배꼽이 더 큰 상황같았던 힘들었던 기억들만 남아있는 구현방법인것 같다. 여러 레이어를 혼용해서 쓰다보면 각 레이어간의 상호 연결성의 위배되는 경우가 많기에…
  • CI Tools (Jenkins / Teamcity 등)
    • 아무래도 가장 추천할만한게 CI Tool 인것 같다. 그중에 필자도 Jenkins라는 툴을 너무 좋아하고.
    • 유료 툴 중에 Teamcity 를 잠깐 언급해주셨는데 찾아보니 한번즈음 써보고 싶을만한 기능들이 있어보였다.

Jenkins 의 장점은 말해뭐해 정도로 배치 어플리케이션과 궁합이 너무 잘 맞는 툴인것 같다. (물론 다른 툴들도 있겠지만 필자개취라 넘어가도록 하자.) 특히 실행시 필요한 플러그인들이 다양하게 많이 있고, 실행방법 또한 수동/스케쥴링 으로 다양하게 할 수가 있으며 RestAPI 지원과 보안, 실행이력관리, 로그 등 최적화 되어있다고 해도 과언이 아닐정도로 다양한 장점들이 있는것 같다.

Jenkins 설정중에 Global properteis 을 통해 환경변수를 설정하는것도 가능하다고 설명해 주셨다. 또한 환경변수들의 묶음을 다시 환경변수로 재 정의해서 사용할 수 도 있고. 참 대단한 Jenkins. 필자는 이제까지 하나의 쉘스크립트를 만들고 공통으로 사용할 파라미터들을 스크립트 단에서 설정후에 Jenkins 에서 쉘스크립트를 실행하는 방식으로 구성하곤 하였는데 이렇게 Jenkins 의 환경변수를 이용하는 방법도 다른 측면에서 활용범위가 높을것 같아 좋아보였다.

무중단 배포에 대해 설명을 해주셨다. 이는 사실 스프링배치 나 Jenkins 와는 관련이 없지만 이 둘을 사용하면서 배포를 할때 리눅스의 명령어니 readlinkln -s를 활용하여 중단없이 배포를 할 수 있도록 한다고 한다. 필자는 이제까지 Jenkins의 끄기전 준비를 실행 하고 스케쥴러에 의해 다음 Job이 실행되지 않는것을 확인 후에 배포를 하곤 했었는데 이러한 기능을 통해 충분히 무중단 배포를 구성 해볼수도 있을껏 같았다. 이 부분은 별도의 포스팅으로 정리를 해볼까 한다.

/images/woowabros-spring-batch/seminar.jpg
정말 중요한 Jenkins의 장점과 멱등성

멱등성에 대해 설명해 주셨다. 필자도 같은 생각인데 배치 어플리케이션을 구성하면서 가장 중요시 생각해야할 개념이 멱등성인것 같다. 우선 멱등성이란 연산을 여러번 적용 하더라도 결과가 달라지지 않는 성질을 의미하는데 코드 내에 LocalDateTime.now()같은게 있다면 과거 기준으로 실행하고 싶어도 해당 코드로 인해 수정/배포를 하지 않고서는 할 수 없는 경우가 생기는것 같다. 그래서 제어할수 없는 코드는 제어할 수 있도록 파라미터를 받아 처리하는 형식으로 구성해야 좀더 효율적으로 실행할 수 있는 것 같다.

배치 어플리케이션에 대한 책을 추천해주셨다. The Definitive Guide to Spring Batch와 내년 상반기에 책을 출간할 예정이라고 하시는데 꼭 들여다 보고 싶을 책인것 같다. (국내 최초 스프링 배치에 대한 내용의 책!)

오늘의 질문

이번에도 어김없이 이 시간을 내것으로 만들기 위해 질문을 하였다. 이 세미나에 온 목적이기도 하다. 젠킨스로 스케쥴링을 하고, jar를 실행시켜 젠킨스에 로깅을 남기는게 일반적인것 실행방식 같은데 그러다보면 jar실행시 job과 관련없는 bean들이 뜨다보니 실행시간이 느려진다. 이부분은 어떻게 해소할수 있을까? ​라는 질문에 @ConditionalOnProperty 어노테이션을 활용하게되면 해당 Job 에서 필요한 bean 만 띄울수 있다고 하셨다. 필자가 운영하고 있는 스프링 배치 버전이 3.x 이기도 하고 멀티 모듈로 구성되어 있으며 (batch가 단독 컴포넌트가 아님…) 필요한 bean만을 지정하기에는 스파게티 코드가 될게 뻔한 상황인것 같아 질문의 답변에서 해법을 찾기에는 조금 힘들었지만 또 언제나 그랬듯 이러한 상황에서 해결방법을 찾아야 하는게 개발자의 숙명 아니겠는가. 좀더 고민해봐야할 부분인것 같다.

마치며

스프링 배치에 대한 기본개념과 관리도구를 활용해서 생생한 현장감과 함께 배치 어플리케이션의 운영 노하우를 들을 수 있어서 너무 좋았던 세미나였다. 이번에도 역시나 내가 고민하고 있던 문제는 누군가 이미 고민했던 문제라는것, 그리고 그러한 고민의 해결방법을 공유함에 있어 생겨나는 가치에 대해 다시한번 온몸으로 뜨거운 열정을 느낄수 있었던 날로 기억에 남을 것 같다.

/images/woowabros-spring-batch/think.gif
충분하면 만족해야만 할까?
출처 : https://vryjam.com/gif.php?id=ODWEBD0bmRGzTq5

다만, 이제까지 A라는 구조로 구성된 어플리케이션에 단순 기능 추가만 할게 아니라 정말 A라는 구조가 최선일까, A의 구조보다 보다 더 효율적이고 유연한 B 나 C 의 구조는 없을까 하는 이러한 고민을 계속 하려는 자세를 가져야 겠구나 하는 생각을 해본다.


Buy me a coffeeBuy me a coffee