
단순히 아는 것과 활용하는 것, 그 차이를 줄여나갈 때 비로소 내가 배우고 있는 것에 의미를 부여할 수 있었다.
2025년 동안 다사다난한 한 해를 보냈지만, 짧게나마 어떤 직무로 어떤 역할들을 해왔는지 정리해보고자 한다.
2024년 9월에 보험사에 입사해 AA직무를 맡으며, 많은 것들을 경험할 수 있었다.
이 보험사 AA직무의 역할자체는 쉽게 말해, 보험 비즈니스 로직을 개발자들이 오로지 개발에만 집중할 수 있도록 돕기 위한 나머지 일들 중 .. (인프라, DBA 등등)의 개발을 포함한 일들을 담당하는 역할이다.
보험 기간계, 채널계 등등의 로직을 자체 Framework위에서 개발하기 때문에, 자체 Framework를 개발 및 유지보수 한다던지, 보험의 비즈니스 로직을 제외한 자체 개발한 공통시스템이나 솔루션들을 담당한다.
나에게 주어진 역할은, Spring 기반의 자체 Fremework 개발 및 유지 보수 / Redis 운영 / Kafka 기반의 로그 시스템 개발 및 운영 / 원장변경시스템 운영 / Spring 기반의 개발자들이 로그를 확인할 수 있는 웹 시스템 개발 및 운영 / 배치를 웹 상에서 수행하기 위한 웹 시스템 개발 및 운영 / AI 모델 솔루션 담당 / 형상관리 솔루션 담당 / 공통 모듈 시스템 개발 / 배치 솔루션 담당 / Telegram 알림 시스템을 사용하기 위한 데몬성 웹 개발 담당 / 사내 관리배치 담당 / GPU장비 모니터링 시스템 개발 및 운영 / 감사 대응 업무 등등의 역할을 맡았다..
주어진 역할이 너무나도 많았기 때문에, 일단 운영업무를 무사히 수행할 수 있도록 환경에 적응하는 것이 우선이였다.
보험사의 시계가 너무나도 빠르게 지나간다는 것을 다시한번 느낄 수 있었던 경험이였다.
입사 후 6개월 간은 운영업무를 익히는데에 많은 시간을 투자했다. 개발자들의 문의에 대응한다던지, 급한 장애 이슈를 처리한다던지, 정말 공통 모듈을 담당하면서 개발해야 되거나 익혀야 하는 것들이 너무나도 많았다.
그 중에서도, 운영업무를 제외하고 큼지막한 업무 위주들로 작성해보고자 한다.
운영업무에 어느정도 적응이 될 때쯤에,
첫번째로, Kafka를 활용한 사이버마케팅 업무의 로그 수집 지연을 해소 과제를 수행했다.
기존의 기간계는 NAS -> Filebeat -> Logstash(Kafka Producer) -> Kafka -> Logstash(Kafka
Consumer) -> Tibero DBMS 구조를 가지고 있었지만 사이버마케팅은 NAS -> Filebeat -> Logstash -> Tibero DBMS의 구조를 가지고 있어, Kafka로 전환하기 위해 기존 기간계 로그 수집 로직이 어떻게 되어있는지를 파악하고 이를 그대로 사이버 마케팅에 적용하였다.
업무가 워낙 많기 때문에, 최소한의 리소스를 가지고 로그 수집 지연 현상을 최대한으로 해소하기 위해 많은 고민을 했다.
기존 기간계의 서버는.. 대략 20개정도 되었고 WAS는 약 200대 정도 되었다. 이 WAS들은 자체 Framework기반에서 작성된 비즈니스 로직들이 올라가있고, 이 코드들은 java 1.8 버전으로 이루어져있다. 이 WAS에서 NAS에 파일로 남긴 로그파일들부터 시작해 최종적으로 Tibero DBMS에 적재되는 구조이다.
로그 수집 서버는 VM서버로 6~7개를 유지하고 있었고 Filebeat, Logstash, Kafka, Kafka-exporter, Grafana, Prometheus, KSQL 등등의 프로세스는 총 100개 이상의 프로세스를 유지하고 있었다. 너무나도 많고 복잡한 구조여서, 처음엔 대략적인 흐름정도로만 이해하고 넘어갔다.
사이버마케팅의 업무를 Kafka에서 새로운 토픽을 만들고 파티션을 80개로 설정해 세팅해두고, 로그스태시에서 바로 Tibero로 적재되는게 아닌 Kafka를 거치도록 수정해서, 피크 시간대(오전 10:30) 기준, 로그 적재 지연 개선 As-is : 1 시간 / To-be : 10 초 라는 결과를 만들어낼 수 있었다.
두번째로, U2L (Unix to Linux) 기반 배치 시스템 이관
기존에 수행되는 배치서버는, 모두 유닉스기반의 고성능 서버에서 돌아가는 서버였다. 이 비싼 유닉스 장비에서 리눅스로 넘어가기 위해 인프라분과 같이 진행했던 과제이다.
배치도, Spring Batch 프레임워크 기반으로 돌아가고있고, 일부 고성능이 필요한 배치는 Java기반의 솔루션을 이용해 개발하고 있었다.
Unix 환경 배치 시스템을 Oracle Linux 8 로 마이그레이션하기 위해, 플랫폼 차이(경로, 파일 시스템, 권한)를 해결하고 프레임워크의 일부 로직등을 수정한다던지 솔루션이 잘 작동하는지등을 개발자들에게 테스트 요청하고 개발계까지만 PoC를 진행했던 과제이다.
배치를 수행하는 웹 -> 배치서버에 올라간 쉘을 수행할 수 있는 데몬성 웹 -> 배치서버의 쉘 수행과 같이 동작하는데, 이 과정에서 리눅스기반으로 수정하고 테스트하는데 많은 에너지를 들였다.
IBM E1050(8 코어) -> HCI x86 가상화(16 코어) 배치 개발계 U2L 전환을 통해 운영계 AIX 교체 비용 대비 절감은 했지만, 유닉스 장비의 성능을 따라가진 못하여 실제 운영계에 반영되진 못했다.
이번 과제를 통해서, 인프라분들이 어떤 일들을 하는지, OS 관점에서 봤을때 성능을 개선할 수 있는 포인트들이나, Java GC 알고리즘에 따른 (G1GC, Parallel GC에 따른 배치 수행시간 차이나 성능 비교) Full GC 해결 등을 고민해볼 수 있는 과제였다.
특히나, 유닉스 기반의 JDK와 리눅스 기반의 JDK에 따라 GC가 어떤게 있고 어떤걸 사용해야 효율적인지, Java 여러 실행옵션 (xms, xmx 등등) 인프라분과 함께 테스트해보고 고민하며 단순히 Java로 코드를 짜는 것만이 아닌, 실행환경에 따라 많은것들을 좌지우지 할 수 있고 이런 옵션들을 이해하기 위해 CS지식에 대한 필요성을 많이 느낄 수 있었다.
세번째로, GPU 모니터링 시스템 개발
회사의 기조가 AI를 적극적으로 활용하고 도입함에 따라, 우리팀은 무지무지 바빠졌다. 인프라분들이 GPU장비를 들여오고 이를 개발자분들이 활용해 GPU를 활용한 AI 프로젝트들을 다수 준비하면서 GPU가 정말 효율적으로 사용되는게 맞는지 최소한 인프라 시점에서 모니터링이 필요했다.
결론적으로, Grafana 대시보드를 구축하여 Nvidia GPU 리소스 현황을 실시간으로 시각화 해야했다. k8s기반의 GPU서버는 이미 업체가 세팅을 해준 상황이였고, 데몬셋으로 gcgm-exporter가 띄워져있는 상황이였다.
이 gcgm-exporter API를 활용해 Prometheus 로 메트릭을 수집하여 GPU 사용량이나 온도 등을 기본적으로 체크하는 화면을 만들었다. 추가로 중요한 Application Log를 개발자들이 RDBMS에 쌓아주시면, 이걸 Loki로 수집하여 Grafana에 보이도록 시각화하였고, 알림까지 구성하였다. 기존 회사에서 사용하는 텔레그램 데몬은 HTTP 쿼리스트링 방식만 지원하여 Grafana 에서 동적 쿼리스트링 생성 불가하여서, 이를 해결하기 위해 Spring Boot 기반 Alert Daemon 을 별도 개발, Grafana Alert 의 JSON Payload 를 쿼리스트링으로 변환해 Telegram 과 연동하였다.
이러한 작업들을 통해.. 운영팀이 GPU 리소스 병목·애플리케이션 오류를 사전에 감지하고 즉시 대응 가능할 수 있도록 체계를 마련하였다.
Grafana나 Prometheus등은 이전 게임회사에서 경험을 해본적이 있었고, Loki는 이전 프로젝트에서 사용해본적이 있던 터라 비교적 빠른 시일내에 과제를 수행할 수 있었지만, 기존 텔레그램 알림을 연동하기 위해 기존 로직을 파악해야했고, 이 부분에서 많은 에너지를 소비하였다.
AI Native한 시대가 정말 다가왔구나를 뼈저리게 느낄 수 있었던 순간이였다.
네번째, 신정원 API 호출 로그 분석 관리 배치 개발
기간계에서 무수히 많은 외부 시스템들을 사용하기 위해 외부 API를 호출하게 되는데, 그 중에서도 오류가 많이 나는 신용정보원 API가 어느정도되고 어떤 호출에서 에러가 났는지 분석하기 위해 사내 관리배치를 개발하고 이 데이터를 웹으로 보기 위한 웹개발을 진행하게 되었다.
솔루션 DBMS 에 저장된 기간계에서 신정원 API를 호출한 이력(Row)에서 전문 데이터 컬럼을 파싱하고 사내 DBMS에 적재하기 위해 관리배치를 먼저 개발하였다.
대용량 데이터 처리(일 200 만 건)에 대비하여 파티션 테이블 생성을 DBA분께 요청드리고, 배치 개발을 수행하였다.
따라서, 일 200 만 건 로그를 안정적으로 처리 가능한 구조를 확보하고, 기존 수작업 분석 방식 → 자동화된 배치 시스템으로 전환하여 운영 효율을 개선한 업무였다.
API 호출 분석을 통해 서비스별 사용량을 가시화할 수 있는 데이터 기반 체계 마련하였고 파티션 테이블 적용을 통해 파티션 프루닝을 적용할 수 있어 Select 쿼리 속도를 개선하였다. As-is : 5~15 초 / To-be : 0.3~1.5 초
대용량 데이터를 처리하기 위해 필요한 테이블 설계나 커밋 수를 조절하기 위해, DB관점에서 많은것들을 공부하고 DBA분께 물어가며 많은걸 이해하고 바로잡을 수 있었던 시간이였다.
다섯번째, Redis 키 부분 삭제 기능 개발
기존, 현업에서 DB 값을 업데이트하면 Redis 재기동을 통해 수동으로 최신 값을 반영하였으나, 불필요한 키가 삭제되어 무수히 많은 캐시 미스로 인해 기간계 CPU 사용량이 급증하는 현상이 발생하고 있었다.
기존의 DBMS의 값을 바꾸면 레디스의 값을 바꾸던 삭제하는 기능이 있었어야 되지 않나.. 라고 생각했지만 그런 기능이 처음부터 존재하지 않았다.
따라서, DBMS의 값이 바뀌면 레디스의 키를 삭제하던 업데이트를 하던 Framework의 로직을 수정하려 했으나, 워낙 복잡한 시스템이라 개발자와 협의하여 수동으로 지우는 요청이오면 해당 키를 삭제하는 기능을 만드는 것으로 결론지었다.
업무별 Redis 프로세스(최소 2 개~최대 8 개)들에 대해 SCAN + DEL 조합을 통해 업데이트 대상 키 그룹을 패턴 기반으로 탐색하였고 이를 사내 시스템에서 버튼하나로 지우기 위해 로직을 개발해야 했다.
현재 사용하고 있는 Redis 버전은 2.6, Jedis 2.9 버전인터라, 키를 삭제하는 명령어가 동기 방식으로 삭제되는 DEL 명령어밖에 사용이 불가능했고, Redis 4.0이상에서만 사용이 가능한 비동기로 삭제되는 UNLINK명령어가 사용이 불가능했다.
따라서, 많은 고민을 했다. 기존 Redis 2.6은 내가 DEL명령어를 수행하는 로직을 날리면, Redis 메인스레드는 단일스레드이기때문에 해당 키 삭제 처리는 블로킹때문에 다른 처리가 불가능하여 문제가 있다고 판단했다. 하지만 Redis 버전을 4.0 이상으로 업그레이드 하면, UNLINK로 Redis 메인스레드는 Key 삭제 분리만 처리하고 실제 메모리 할당 해제는 백그라운드 스레드에서 동작하여 Key 삭제 로직을 빠르게 처리할 수 있었다.
하지만 Redis 버전 업그레이드에 따라 기존 로직에 대해 많은 반복 테스트가 필요하다고 판단하여 장기 과제로 놔두고, 단기간에 DEL 명령어를 사용해서라도 필요한 Key만 삭제하도록 과제를 수행하였다.
업무별로 프로세스가 다르고, 프로세스가 업무별로 1개가 아니기 때문에, 각 프로세스 별로 멀티스레드 기반 병렬삭제를 하도록 수행하였다.
결론적으로 시간에 따라 삭제해야할 Key의 양은 다르지만, 600 만개 키 삭제 작업을 1 분 이내에 완료하여 재기동 시 캐시미스로 인한 CPU 과부화 현상은 방지할 수 있었다.
기간계 CPU 사용률 개선 As-is : 40~60% / To-be : 20~40%
이 과제를 통해, 단순히 개발자로서 개발하는 역량도 중요하지만 단기과제 / 장기과제로 나누어 문제를 어떻게하면 효율적으로 처리할 수 있었을지 고민해봤던 시간이였다.
마지막으로 여섯번째, Kafka를 활용한 기간계 로그 수집 지연 개선
위에서 첫번째로 언급한 사이버마케팅말고, 기간계의 로그 수집지연이 TPS가 높아짐에 따라 많은 지연이 있었다.
로그수집이 지연됨에 따라, 사내에서 실시간으로 로그를 확인하는 웹 시스템에서 개발자들이 확인이 불가능했고, 이 로그테이블을 활용한 통계성 테이블도 무수히 많았는데, 이 데이터들도 부정확해 TPS가 높으면 데이터를 신뢰할 수 없는 상황이 발생했다.
특히나, 배포날에 로그수집이 지연되면 개발자들은 로그를 다른 솔루션을 통해 확인해야 했어서, 많은 불편함이 발생했다.
따라서, 이 업무를 수행하기 위해서,, 많은 시간을 투자했다. 로그 수집 지연이 어디가 병목인지 파악하기 위해서 먼저 봤던건 Kafka-exporter를 활용한 그라파나 대시보드였다.
밀릴때의 해당 토픽의 LAG가 적게는 백만개부터 많게는 천만개의 메세지가 쌓여있었다.
NAS -> Filebeat -> Logstash(Kafka Producer) -> Kafka -> Logstash(Kafka Consumer) -> Tibero DBMS 구조에서, 중간 Kafka에 많은 LAG가 쌓여있다는걸 확인해, Kafka의 앞단은 볼 필요가 없었다.
그래서 내가 봐야했던건 Kafka -> Logstash(Kafka Consumer) -> Tibero DBMS 에서 어디가 막히느냐였다. 먼저 인프라적인 측면에서 해당 프로세스가 깔려있는 서버의 CPU 사용량이나 메모리 사용량을 확인해보니 특이점은 없어서 SW를 확인했다.
Kafka Consumer역할을 하는 Logstash의 로그를 확인해보니, DBMS로 Insert가 실패해 재처리를 수행했다는 에러로그는 있었지만, 역시나 로그수집지연에 영향을 줄 만큼의 별 문제점은 없어보였다.
기존 구조를 이해하고 더 깊게 분석해야했다.
카프카의 해당 토픽의 파티션수는 120, 전체 로그스태시 설정은 pipeline.batch.size는 1000, pipeline.delay.ms는 50ms, pipeline.workers=80였고, Logstash는 Input, filter, output구조로 되어있는데 아래는 각 기존 설정에 대한 값들이다.
카프카에서 데이터를 가져와 큐에 적재하는 카프카 컨슈머는 총 4개의 프로세스이고 각 스레드 30개였다. (카프카 파티션이 최종적으로 120개라서 매핑되는 컨슈머 프로세스 수 4 x 컨슈머 스레드 수 30 = 120), 정리하자면 Kafka input 플러그인은 프로세스당 30개의 consumer thread를 생성해, 각 스레드가 Kafka partition을 소비하였다.
filter, output에서 사용하는 스레드는 pipeline.workers=80 설정에 따라 80개의 스레드였다.
filter는 일부 데이터를 필터하고,
output은 Logstash output jdbc 플러그인을 사용하고 있었다. Logstash output jdbc 플러그인에서는 오토커밋이켜져있었고 flush_size는 아래 주소를 확인해보니 1000개였다.
<Logstash jdbc output Github Link>
https://github.com/theangryangel/logstash-output-jdbc.git
어디가 병목인지 어떻게 확인할 수 있을까 고민했다. 로그스태시는 API로 해당 메세지가 어떻게 처리되고있는지 확인하는 기능을 제공한다.
http://<logstash_host>:9600/_node/stats과 같이.. curl로 수치들을 확인했는데 JDBC output 플러그인이 받은 이벤트 수와 JDBC output 플러그인이 정상 처리 후 내보낸 이벤트 수가 꽤나 차이가 나는걸 확인할 수 있었다.
따라서, jdbc output에서 병목이 일어나고 있다는걸 확인했지만 리소스를 최소한으로 쓰기 위해 먼저 간단한 테스트를 해볼 수 있는것부터 수행하였다. 기존 Insert쿼리가 Direct Path Insert가 가능한 append 힌트가 붙어있는지, 불필요한 인덱스는 없는지, 카프카 컨슈머의 각 프로세스당 스레드를 늘린다던지, 카프카 토픽의 파티션수를 늘려 로그스태시 큐에 최대한 더 적재한다던지, 배치 사이즈를 늘려 처리한다던지 테스트를 해봤지만, 모든 테스트가 실패하였다.
따라서, 처음 확인했던 병목현상을 구체적으로 분석하기 위해 깃허브의 링크를 타고 들어가 jdbc.rb 파일을 보니, 배치 단위로 insert SQL을 받아도 커밋이 명시적으로 없어도 오토커밋이 켜져있어 1 insert -> 1 commit -> 1 insert -> 1 commit이 수행되는 구조였다. 너무많은 커밋수를 줄이고 배치단위로 커밋할 수 없을까 고민했다.
그래서, JDBC output 플러그인을 변경해야 했지만 이 플러그인의 최신 버전은 5.4.0 버전이였고, 플러그인의 버전을 변경하려니 마지막 업데이트가 7년전이였다.
인터넷을 통해 찾아보니 카프카 컨슈머로 사용되는 Kafka Connect JDBC Sink가 대중적으로 널리 사용되었지만 신규 Application을 개발하고 테스트하는데 시간이 많이 소요될 것 같아, 장애에 빠르게 대응하려고 최소한의 리소스로 최대한의 성능개선을 위해 기존 루비코드를 수정하기로 결정하였다.
이 루비파일을 배치단위로 insert를 수행하고 최종적으로 배치단위가 끝나면 Commit을 수행하도록 로직을 변경하고 적용하였더니 검증된 최소 5000TPS까지는 실시간으로 처리될 수 있었다.
적은 리소스로 업무를 수행하려다보니 많이 돌아간 부분이 있었지만, 최종적으로는 플러그인의 코드를 수정하여 이 업무는 끝이났다.
내가 잘못 알게 된 오개념들도 정리하고 넘어갈 수 있었던 좋은 시간이였고, TPS가 적을땐 하루에 약 2억 Row가 쌓이는 대용량 로그성 파티션 테이블에 적재하기 위해 어떻게 접근해야 하고 어떻게 문제를 해결하기 위해 노력했는지 상사분과 회의실에서 그림그려가며 분석하고 했던 과정들이 내 자산이 된 것같아 뿌듯하고 좋은 시간이였다.
이런 업무들 외에도 운영업무를 하는데 무수히 많은 장애들을 맞이하지만 다 글로 적을 수 없을 것 같다.
요즘 들어 개발자에 대한 나의 생각이 조금씩 바뀌고 있다. 단순히 코드를 잘 짜는 역량도 중요하지만, 그보다 더 중요한 것은 문제를 마주했을 때 어떤 방식으로 접근하고, 무엇부터 의심하며, 어떻게 해결책을 찾아가는지라는 생각이 든다. 결국 개발자의 가치는 기술 그 자체보다 문제를 해결하는 과정에서 드러난다고 느끼게 되었다.
이런 생각을 갖게 되면서 제게 주어진 과업들은 넘어야 할 장애물이 아니라, 매일 마주하는 도전 과제와 같았다. 그 도전들을 하나씩 해결해 나가며 이전보다 더 나은 자신으로 성장할 수 있었던 것 같다.
2025년은 업무적으로도, 개인적으로도 좋았던 순간과 슬펐던 순간이 함께 공존한 한 해였다. 그럼에도 불구하고 결국 버텨내기 위해 노력했고, 그 과정에서 이전보다 조금은 단단해진 나 자신을 마주할 수 있었다.
현재 IT 산업은 비약적인 발전을 이루었지만, 이 변화가 끝이라고는 생각하지 않는다.
2026년에도 계속 도전하고 배우며 살아가려 한다. 개발자로서도, 개인으로서도 멈추지 않고 성장하며 주어진 자리에서 결국 해내는 사람이 되고 싶다.


'회고록' 카테고리의 다른 글
| 갑진년 연초 회고록 : 게임회사의 게임서버개발자 1년 돌아보기 (2) | 2024.02.26 |
|---|---|
| [Project] 연합동아리 잇타, 이삼이상 회고록 (0) | 2022.08.19 |
| [Project] 교내 팀 프로젝트, Tlover(트러버) 회고록 (0) | 2022.08.13 |
| [Project] 연합동아리 큐시즘 24기, Hurry up HUP! 회고록 (4) | 2022.08.13 |
| [Mentoring] 청년고민해결단 온라인 멘토링 회고록 (4) | 2022.04.02 |