4.png

정산시스템팀

badge.svg?url=https%3A%2F%2Fwww.notion.so%2Fjojoldu%2F5badc2ba03904832bce8fdf3dc4a407b&count_bg=%2379C83D&title_bg=%23555555&title=hits&edge_flat=false

들어가며

안녕하세요? 우아한형제들에서 정산시스템팀 개발자로 일하고 있는 '이동욱'입니다.
정산시스템팀으로 별도의 팀이 생긴지 1년이 지났는데요.
그 1년간 팀 내부의 많은 개선이 진행되었으나, 외부에는 정산시스템에 대한 홍보가 잘 안 되었던 것 같습니다.
아무래도 '정산'이란 단어가 가지는 어색함 때문이라고 생각됩니다.
(정산 == 돈 이미지가 강해서 더더욱 그런것 같습니다.)
.png
출처: SBS 돈워리스쿨
정산이라고 하면 일반적으로 다음과 같은 오해를 종종 듣습니다.
몇 천줄의 프로시저 스토어로 로직이 처리되어있다던가
애플리케이션 보다는 쿼리에 의존한 개발 방식이라던가
회계지식이 필수라던가
기술보다는 도메인 중심의 개발 프로세스가 잡혀있다던가
Java 6, Spring 3.2 등 레거시 기술로 이루어져있고 개선할 생각이 없다던가
다른 팀을 바라볼 때 궁금해하시는 점들
저 회사(혹은 팀) 에서는 배포를 어떻게 하지?
테스트 코드를 진짜 작성하는걸까?
코드리뷰 문화가 정착되어 있는걸까?
개발 프로세스가 어떻게 진행될까?
까지 포함하여 해소해보고자 합니다. 혹시나 지원을 망설이시는 분들이 계시다면! 이 글을 보시고 편한 마음으로 지원해주세요!
💡
현재 정산시스템은 대규모 개편 중이라 시스템 소개 보다는 개발자 분들이 궁금해하실 것 위주로 작성하게 되었습니다. 개편이 완료되면 그땐 기술블로그에 시스템 소개글을 작성하겠습니다 😎

팀 소개

먼저 간략하게 저희팀에 대해서 소개를 드리겠습니다. 저희 팀은 배달의민족에서 이루어지는 정산 업무를 자동화하는 팀입니다. 고객님께서 앱을 통해 결제한 금액을 매일 집계하여 업주님들께 전달드리는 것을 자동화 한다고 보시면 됩니다. 구체적으로는 다음과 같은 일을 하는 팀입니다.
하루에 수백억원이 발생하는 주문 데이터를 계산하는 수십개의 배치 애플리케이션들을 개발하고 운영합니다.
수억건의 데이터들을 가공하여 여러 시스템에 실시간 API로 제공합니다.
수십개의 메뉴가 있는 어드민 시스템을 직접 개발해서 사용합니다.
2500개 이상의 테스트 코드가 매일 수십번씩 수행되어 비지니스를 뒷받침합니다.
모든 코드는 코드리뷰를 진행하고, 코드리뷰가 끝나면 QA를 시작합니다.
대용량 데이터 처리와 1원의 오차도 놓치지 않는 견고한 소프트웨어 시스템을 만들기 위해 노력합니다.
기획/운영/개발이 한팀에 모여 기민하게 움직입니다.
문서의 중요성을 알고 직군 관계 없이 문서화를 진행합니다.

기술 스택

일반적인 모던 자바 애플리케이션 개발 스택을 따릅니다.
Java 8
Spring Boot 2.1.x
Spring MVC, Spring Data JPA, Spring Batch, Spring Security, Spring Rest Docs, ...
JPA & Querydsl
MyBatis와 같은 QueryMapper를 사용하진 않습니다.
정적 타입 개발을 추구하고 있습니다.
AWS (클라우드 100% 이관이 완료되었어요! 💯)
EC2, CodeDeploy, SQS, RDS Aurora (MySQL), S3
Junit4 & Spock
Junit 5로 전환을 시작했어요!
Gradle 6
Git & Gitlab
MacOS & IntelliJ & DataGrip & Upsource
Jetbrains 사의 제품을 적극 활용중이에요.
Nginx & Jenkins
ES6 & Webpack & Npm & React.js & Typescript & Vue.js

온보딩

조직내 새로 합류한 사람이 빠르게 조직의 문화를 익히고 적응하도록 돕는 과정을 온보딩(Onboarding) 라고 하는데요. 저희 팀의 개발자 온보딩은 다음과 같습니다.
1주차: 개발환경 세팅 및 기본적인 업무환경 구성
2주~6주차: 파일럿 프로젝트
7주~8주차: 기술블로그 글 작성 및 기존 프로젝트 분석

1주차

1주차에는 기본적인 개발환경과 업무환경을 세팅합니다.
팀 내 Wiki에 작성된 내용을 참고해서 본인만의 업무환경을 설정합니다.
Untitled.png
신규입사자를 위한 페이지를 별도로 운영하고 있습니다.
기존에 작성된 문서가 없어 처음 일을 시작할때 당황했던 기억이 나는데요.
-.gif
다들 한번씩 있으시죠!?
저희팀 역시 초기에는 문서화가 거의 안되어있어 처음 합류하시는 분들이 적응하는데 허들이 높았습니다.
그래서 이런 문제점을 인지하고 지금은 개발/기획 관계 없이 다들 문서화를 습관적으로 하고 있습니다.
기본적인 OA도구(프린터/스캐너/팩스 등) 사용법 부터 도메인/개발환경/업무요청까지 손쉽게 적응할 수 있습니다.
실제로 최근 합류 하신 분들 역시 문서화로 얻는 장점을 체감하셔서 이제는 팀의 모든 내용을 Wiki에 남기려고 노력합니다.
Untitled.png
Untitled.png

2 ~ 6주차

저희팀은 개발자 채용에 있어서 정산 도메인에 익숙하신 분 보다는 개발을 좋아하는 분을 선호하다보니 정산 도메인을 해보신 분은 1명도 없었습니다. (저를 포함해서)
💡
즉, 정산 도메인을 몰라도 전혀 지장이 없습니다.
그래서 정산 도메인과 개발 컨벤션에 익숙해지기 위해 4주간의 파일럿 프로젝트를 진행합니다. (+1주는 파일럿프로젝트 회고를 기술블로그에 작성합니다)
파일럿 프로젝트는 작은 규모의 정산 시스템을 만들어 보는 것인데요.
기간내에 프로젝트를 완성하시고, 코드리뷰를 진행합니다.
Untitled.png
파일럿 프로젝트 리뷰를 위한 PPT 시연 장표입니다
파일럿 프로젝트에 대한 생생한 후기는 기술 블로그에 올라온 글들을 참고해보시면 좋습니다. (최신순)

7 ~ 8주차

이렇게 4주간의 파일럿 프로젝트가 끝이나면, 이제 본격적으로 업무에 투입이 되는데요.
이때는 바로 작은 일감을 치기보다는 기존 프로젝트에 익숙해지기 위해 기존 코드를 분석하면서 테스트 코드를 추가하는 것부터 시작합니다.
Untitled.png
코드리뷰로 테스트코드만 수정된 내역을 올린 경우입니다.
메인 코드는 작성하지 않고 기존 코드에 테스트 코드만 추가해보는 이유는 다음과 같습니다.
아주 작은 업무 위주로 일을 하게 되면 전반적인 큰 그림을 이해하기가 어려웠습니다.
본인이 기존 로직을 이해한게 맞는지 테스트 코드로 실시간 검증을 해볼 수 있습니다.
본인이 개발하지 않은 코드에 대해서도 테스트 코드를 작성하면서 간접 경험을 해볼 수 있습니다.
신규 입사자가 올때마다 추가되는 테스트 코드로 인해 자연스럽게 견고한 프로젝트가 됩니다.
테스트 코드가 익숙치 않아 개발 생산성이 떨어지는 분들에게는 생산성 향상을 얻을 수 있었습니다.
이렇게 8주간의 과정이 지나면 어엿한 팀의 개발자로서 큰 업무들을 담당할 수 있게 됩니다.

개발자로서 얻을 수 있는 것들

정산시스템은 어떻게 보면 일반적인 웹 서비스와는 결이 조금 다른데요.
이를테면 일반적인 웹 서비스가 커지면서 얻는 노하우라면 보통은 다음과 같습니다.
분당 50만건의 요청이 오면 어떻게 API를 만들어야할까
일일 PV가 1억일 경우 어디까지 캐시 Layer를 둬야할까
하지만 정산시스템의 경우 순간 요청수가 많은 API 보다는 대량의 데이터를 안정적으로 가공/제공 하는 것이 목적인 시스템입니다.
그래서 저희팀에 합류하시면 얻을 수 있는 기술적인 부분을 소개드립니다.

테스트 코드

하루에 계산되는 정산금액이 수백억원인데요.
이들을 여러 결제수단/보조수단/상품정책에 따라 1원의 오차도 없이 계산하기 위해서 테스트 코드를 필수로 작성하고 있습니다.
이렇게 작성된 테스트 코드는 매번 develop 브랜치로 Merge가 될때마다 소나큐브를 기반으로 여러 지표를 뽑아서 슬랙으로 알람을 보냅니다.
Untitled.png
만약 테스트가 깨지거나 커버리지가 낮아지면 다음과 같은 실패 알람이 와서 확인하고 수정합니다.
Untitled.png
2500개의 테스트 중에는 순수 Java만으로 이루어진 빠른 테스트도 있지만, 실제 쿼리를 수행하거나 Spring Context를 사용하는 느린 테스트들도 있는데요.
이런 느린 테스트들로 인해 전체 테스트의 성능 저하가 있어, 테스트 코드의 성능 개선도 꾸준히 진행되고 있습니다.

코드리뷰

컨벤션의 경우엔 IDE 세팅과 정적분석도구를 통해서 해결할 수 있습니다.
하지만 잘못된 기능, 비효율적인 코드, 로직상 오류 등에 대해서는 코드리뷰를 통해 검수해야만 하는데요.
그래서 모든 코드는 QA 시작전에 Jetbrains사의 Upsource를 통해 항상 코드리뷰를 진행합니다.
Untitled.png
코드리뷰에서는 Querydsl로 만들어진 쿼리의 실행계획과 성능도 함께 리뷰를 합니다.
Untitled.png
쿼리에 대한 리뷰가 계속 진행되다보니, 팀 내 주니어개발자분들끼리 Real MySQL 책 스터디도 진행하게 되었습니다.
Untitled.png

대량의 데이터 처리 (Batch)

몇년치의 주문 데이터들을 쌓고 몇달치를 제공하는 등의 기능을 구현하기 위해서는 여러가지 쿼리 튜닝과 Batch 처리에 대해 고민하게 되는데요.
수억건에서 100만건씩을 조회하여 엑셀/메일로 제공하려면 어떻게 해야할까
매일 수백만건의 주문 데이터를 타임아웃 이슈 없이 어떻게 API로 받아낼 수 있을까
수억건의 데이터가 담긴 테이블에서 페이징 처리는 어떻게 해야할까
200만건 중 10만건만 남기고 실패가 나면 어떻게 남은 건들을 처리해야할까
등등 대량의 데이터 가공과 집계를 위해서 여러가지 고민들을 하고 개선을 진행하고 있습니다.
최근에는 주요 테이블들의 데이터가 10억건을 넘으면서 좀 더 효율적으로 데이터를 수신/가공/제공 할 수 있는 방법들을 고민하고 있습니다.

JPA & Querydsl 노하우

일반적으로 JPA와 같은 ORM에 대한 오해로 다음을 들 수 있는데요.
복잡한 도메인 (회계/물류 등) 에서는 ORM을 쓸 수 없다.
저희는 정산이라는 도메인에서 100% ORM으로 서비스가 운영되고 있습니다.
3년이상 운영되고, 지속적으로 비지니스 요구사항에 맞게 개선되고 있는 상황에서도 ORM을 더 적극적으로 사용하고 있는데요.
장점은 더욱 살리고, 단점은 개선 방법을 찾아서 적용하고 있습니다.
JPA에서 복잡한 조회 쿼리는 어떻게 해결할 수 있지?
수억건 데이터 사이에서도 JPA가 성능이슈가 없는 것일까?
OneToMany 관계가 2개 이상인 경우엔 N+1 문제를 어떻게 해결하지?
FetchJoin은 OneToMany 관계의 1개 테이블에만 사용할 수 있습니다.
Spring Batch와 Querydsl를 어떻게 함께 쓸수있을까?
Querydsl의 Paging 기능이 성능이 얼마나 나오며, 성능 저하를 어떻게 해결할 수 있을까?
최근에는 사내 기술 컨퍼런스 (우아콘) 에서 이에 대한 주제로 발표도 하였습니다

어떤 분들과 일하나요?

현재 저희팀에는 저를 포함하여 총 5명의 개발자분들이 계시는데요.
💡
전체 팀원은 10명입니다 (기획/운영 포함)
한분씩 소개드리기 보다는 개발자라면 기술적인 내용을 이야기하는게 더 좋겠죠?
아래는 모두 저희팀 개발자분들이 사내 기술블로그에 작성한 글입니다.
저희팀에 합류하시게 되면 이 글을 쓰신분들과 함께 일하게 됩니다.

이런 사람과 일하고 싶어요

저희팀이 추구하는 개발자, 여태 채용해오신 분들을 보면 다음과 같은 특징을 가지고 있었습니다.
정산 도메인을 많이 아시는 것보다, 기술을 좋아하시는 분
신기술 Hello World 사용자가 아닌 본인이 사용하고 있는 기술에 대해 "진정성" 있게 접근하시는 분
처음 써보는 기술이라도 "팀에 필요한 기술”이라면 언제든 달려들 수 있으신 분
테스트 코드 작성을 당연하게 여기고 계속해서 더 좋은 테스트 구조와 코드에 대해 고민하시는 분
수동작업이 보이면 자동화 대상으로 여기고 자동화를 계속 해오신 분
코드리뷰를 받을때 본인의 코드와 본인을 떼놓고 리뷰 받을 수 있으신 분
기억보단 기록을 좋아하시는 분 (지속적으로 문서화를 하시는 분)
비개발직군분들께 이슈를 설명할 때 그들의 입장에서/그들의 언어로 이야기하는게 당연하신 분
이 글을 보시는 분들께서 이에 해당하신다고 하면 주저없이 지원해주세요! 😉

마무리

뭉쳐진 실타래를 가위로 한번에 끊어서 다시 시작하는 것은 어떻게보면 쉽게 경험할 수 있다고 생각합니다.
반면, 엉키고 묶인 실타래를 하나하나 풀어내서 결국엔 묶여있던 것들을 다 풀어내는 경험은 쉽게 할 수 없다고 생각합니다.
현재의 정산시스템팀에 합류하는 것은 레거시 시스템을 어떻게 점진적으로 개선하는지, 달리는 자동차의 바퀴를 어떻게 교체할 수 있는지 생생하게 경험해볼 수 있는 기회라고 생각됩니다 😇
마지막으로 현재 팀에 계신 분들께 저희팀의 개발파트 장점이 무엇인지 여쭤보고 받은 답변들을 남깁니다.
Q. 저희 팀이 외부 개발자들에게 어필할만한 요소는 뭐가 있을까욤?
Untitled.png
Untitled.png
Untitled.png
Untitled.png
💡
최근 사내 10주년 기념 촬영을 마치고 지하철역까지 동행한 저희팀의 개발자분께서 정산시스템에 대한 소회를 털어놓으셨는데요. 이 글을 보시는분들께 꼭 소개드리고 싶어 마무리로 작성합니다. "이를테면 주문/결제/가게노출과 같은 시스템들을 스타크래프트나 리그오브레전드 같은 실시간 게임이라고 한다면, 정산시스템은 바둑 혹은 체스와 같이 심사숙고해서 한 수 두는 게임이라고 생각해요. 저는 이런 게임들이 취향에 맞아서 지금 일의 만족도가 굉장히 높아요."
긴 글 끝까지 봐주셔서 너무 감사합니다.
-.gif
면접장에서 뵈어요!
Made with 💕 and Oopy