우당탕탕 25년 2Q 회고

혁콩·2025년 8월 9일
post-thumbnail

어김없이 늦어버린 2분기 회고

대형 금융사의 PoC를 한 분기에 2번이나 하게 되다니, 정말이지 바쁜 2분기였습니다.

이번 회고에선 2개의 PoC를 진행하며 각각 무슨 일을 했는지를 되돌아볼까 합니다.

두 가지 도전 과제

버그 수정, 기능 개선과 신규 기능들으 여럿 개발했지만, 그 중 가장 기억에 남는게 두 가지가 있습니다.

2번의 PoC에서 요구되었던 사항들에 대해 얘기해볼까 해요.

첫 번째 과제, 유량 제어

첫 PoC에서 나온 요구 사항이었습니다.
어찌보면 처음 담당한 큰 규모의 기능 개발인 것 같아요.

제가 속한 팀이 담당하는 제품인 AnyLink는 Inbound / Outbound 어댑터를 통해 기관끼리의 연결, 통신을 담당하고 있어요.

보통 유량 제어, RateLimiter의 동작은 주로 서버가 감당할 수준의 요청만을 처리하기 위해 유입되는 트래픽을 제어한다고 생각합니다.

위 AnyLink 서비스 플로우 엔진 트리거링 사진에서 보면 Inbound Adapter에서 요청이 인입될 때 제어하는거겠죠.

그런데, 이미 유량 제어에 대한 설정 화면이 존재하네요.

이미 거래라는 단위로 유량을 제어하는 기능이 존재했는데, 간단히 말하면 호출되는 API별로 트래픽을 제어할 수 있었어요.

그렇다면 어째서 유량 제어 기능을 또 구현하게 된걸까요?

바로.. Outbound Adapter에서 트래픽을 제어하는 기능에 대한 요구였기 때문입죠.

이 부분에서 트래픽을 제어해야 합니다.

Flow Engine은 사용자가 정의한 Flow에 맞춰 동작을 수행하다가, Outbound에 대한 요구를 만나면 Delivery Channel을 통해 Outbound Adapter로 해당 동작을 위임합니다.

이런 저런 고민을 한 후, Outbound Adapter에서 외부로 요청을 보낼 때 제어 여부를 판단해 로직을 blocking하는 비교적 간단한 방법을 적용해봤어요.

blocking 하는 방법은 뭐.. 여러 가지가 있습죠. LockSupport를 이용하는 방법, CountDownLatch를 이용하는 방법, 아니면 Thread.sleep()이나 Thread.wait() 등..?

무엇을 이용했던 해당 방식으로 구현 후 테스트를 진행했습니다.
처음에는 아~~무 문제 없이 동작했죠. 구현한대로 많은 양의 트래픽을 발생시켜도 요청 우선 순위에 따라 거래를 수행했어요.

다만, 2가지 문제가 생겼는데

1. 스레드 고갈

인터페이스 프레임워크인 AnyLink는 사용자가 특정 거래에 대해 사용할 스레드 풀을 선택하고, 해당 스레드 풀의 최대/최소 스레드 수 등 자세한 설정을 할 수 있습니다.

blocking 방식의 문제는 여기서 처음 시작되는데...

최대 스레드 개수가 100개일 경우, 100개의 요청이 대기중이라면 유량 제어하는 거래와는 상관없는 거래들 또한 수행하지 못하게 되었습니다.

더 큰 문제는 Outbound Adapter만 멈추는 것이 아닌, Inbound Adapter 또한 동작을 할 수 없었다는거죠. 사용 가능한 스레드가 없으니깐요.

2. EventLoop blocking

거래에 사용하는 스레드풀이 마르는 현상뿐만 아니라 다른 문제도 존재했는데요.
참 문제가 많은 방식이었네요,,,

TCP Adapter는 기본적으로 비동기로 동작합니다. 외부로 요청을 보내는 메소드를 호출해도, 실제 요청은 이벤트 루프 스레드가 수행한 후 응답이 오면 콜백을 통해 알려주는 식이예요.

문제는 해당 어댑터 동작 과정 중 이벤트 루프 내부에서 재귀적으로 외부 요청을 수행하는 경우가 존재했다는거죠.

이벤트 루프가 외부 요청을 수행했을 경우, 해당 거래가 유량 제어 설정이 되어있다면 모든 요청을 처리하는 이벤트 루프 스레드가 blocking 되어버리는 대 참 사가 발생했습니다.


그래서?

그래서 기존 프레임워크의 동작에 맞게 비동기 방식으로 동작하도록 수정했습니다. 스레드 자체를 멈춰버리던 기존 방식을 버리고, Outbound Adapter가 유량 제어 설정을 확인하면 해당 정보를 RateLimiter에 전달하고, 수행하던 거래 흐름을 끊습니다. 이후 RateLimiter는 제어 설정과 우선 순위에 따라 저장해놨던 정보를 통해 Delivery Channel에 다시 전달하고, 거래가 다시 수행되는 흐름으로 변경했습니다.

다행히도 잘 동작했네요..!

두 번째 과제, HTTP 2.0

두 번째 PoC에서 나온 요구 사항이었습니다.
신규 프로토콜을 추가하는 요구에 대응하기 위해선 참 많은 것들이 개발되어야 했는데요.

연결 정보를 설정하는 웹 어드민에 설정 화면이 추가되어야하고, 데이터를 관리하는 데이터 통합 서버에 저장을 해야하며, 인터페이스를 정의하는 스튜디오에 설정하는 화면과 로직이 추가되어야 합니다. 마지막으론 거래 로직을 수행하는 런타임 엔진에도 기능이 추가되어야 하죠.

제품의 코어 로직을 제외한 모든 것을 추가해야하는... 그래서 작업량이 꽤 많았습니다.

HTTP 2.0 명세도 파악해야하고, 파악한 명세에 대해 설정 화면은 어떻게 가져갈건지, 어떤 방식으로 거래를 수행하도록 할 것인지 등등

프로토콜을 처음 추가해봤다보니 이런저런 버그들도 많이 생겼구요. (화면 출력이 잘 안된다거나,,, 이클립스 기반 어플리케이션 개발은 참 복잡한 것 같습니다)
기능 추가 완료 후에 확인해보니 1만줄가량 코드가 추가됐더라구요.

기회가 된다면 공부했던 HTTP/2에 대해 공유하는 글을 작성해볼까 해요.

마무리하면서

취업 준비할때는 글 쓰는게 참 재밌었던 것 같은데, 바쁘게 살다보니 글을 잘 안쓰게되고, 실력도 줄고, 재미도 없어지는 것 같아요,,

그래도 써야지.. 하면서 8월에 되어서야 2분기 회고를 들고 오네요.

이제 어느정도 적응도 했고, 최근엔 덤프 분석, 버그 분석부터 동시성 이슈도 몇 개 수행했습니다.
다만, 저런 세부적인 내용은 블로그에 자세히 쓰기 좀 그러니 3분기 회고엔 이런저런 쓸 이야기가 별로 없을 것 같네요 :(

다들 행복하셨으면 좋겠습니다! 그럼 안녕

profile
아는 척 하기 좋아하는 콩

1개의 댓글

comment-user-thumbnail
2025년 11월 10일

멋지게 보내신 3Q, 4Q 이야기는 언제 만날 수 있을까요 ?
손꼽아 기다리고 있어요 😄

답글 달기