미리보기
기본 정보

안녕하세요. 팀 협업을 통해 프로젝트 성과를 높이고 성장하는 백엔드 엔지니어 정호준 입니다. 1. 동료들과의 협업을 통해 함께 성장하는 과정을 좋아합니다. - 현업에서 API 문서화 도입을 통해 협업을 강화했습니다. - 사내 스터디를 만들어 서로가 공부한 내용을 공유하는 자리를 만들었습니다. 2. 빠른 실행과 꾸준한 개선을 추구합니다. - 작은 단위로 작업을 쪼개어 빠르게 완료하고 이후 지속적으로 개선해 나가는 방식을 선호합니다. 3. 사용자 경험을 기반으로 성능 개선을 하는것을 추구합니다. - 테스트 과정에서 유튜브 연동의 요구사항이 생겨 유튜브 API를 사용한 연동을 진행했습니다. - 데이터의 양이 많아지면서 어드민 페이지에서 속도 저하가 일어나 리팩토링을 통해 성능을 향상했습니다.
경력
(주)알엠소프트
매니저 | 백엔드개발팀
2023.02. ~ 2024.04. (1년 3개월)
SNAPPI 서비스 개발
영상 업로드, 결제, 알림, 리뷰, 쿠폰 서비스 및 어드민 페이지등 다양한 API의 설계, 개발 및 유지보수
CLIVEWORKS 서비스 개발
정산, 알림, 작업물 할당, 데이터 정제 서비스 및 어드민 페이지 등 다양한 API의 설계, 개발 및 유지보수
비동기 처리를 이용한 서버 안정화 및 사용자 경험 향상
RabbitMQ를 이용한 비동기 처리 도입
Scale-Out을 통한 여러 서버에서 병렬 처리를 수행을 통해 속도 향상 및 부하 분산
TUS 프로토콜의 도입을 통한 안정적인 대용량 파일 업로드
500MB 이상의 영상 업로드 실패 확률 평균 1% 미만으로 개선
실패시 중단 지점부터 재개 가능하게 하여 사용자 경험 향상
Redis를 활용한 캐시 도입
자주 이용되는 영상 정보를 캐시처리하여 유튜브 API 호출량 평균 60% 감소
외부 API 연결이 적어지고 캐시를 통한 데이터 제공을 통해 응답속도 평균 30% 향상
어드민 페이지 쿼리 리팩토링을 통한 성능 개선
JOIN 방식 변경, 서브쿼리 수정, 조건절 순서 변경, 동적 쿼리를 통한 쿼리 실행 속도 향상
자주 사용되는 데이터 캐싱 처리
2s -> 평균 150ms 로 응답속도 약 92% 향상
Jenkins를 통한 서버리스 방식으로 운영비 절감
상시 운행 서버에서 Jenkins를 이용한 서버리스 방식으로 Batch 서버 설계
약 20만원 -> 약 4만원 운영비용 80% 절감
팀 내 개발문화 확립
공통 API 문서 도입 및 알림 시스템을 통한 협업 강화
Git Flow 와 GitHub Flow의 하이브리드 방식을 도입하여 개발 워크플로우 개선
사내 스터디를 만들어 지식 공유 및 커뮤니케이션 강화
프로젝트
SNAPPI
알엠소프트
2023.10. ~ 2024.04.
개요
영상의 자막과 번역을 추출하여 사용자에게 제공
언어의 제약없이 많은 영상을 시청할 수 있도록 하는 것이 주된 목표
AI를 활용하여 영상의 자막과 번역을 추출하는 서비스
서비스 소개
이 프로젝트의 목표는 영상의 자막과 번역을 추출하여 사용자에게 제공하는 것이었습니다.
사용자가 원하는 동영상을 업로드하거나 유튜브 링크를 입력한 후 원하는 언어의 자막, 번역을 선택하면 AI를 활용하여 영상의 자막과 번역을 추출하는 서비스로 언어의 제약없이 많은 영상을 시청할 수 있도록 하는 것이 주된 목표였습니다.
그에 맞게 WhisperAI와 Deepl을 사용하여 자막과 번역을 추출할 수 있도록 하였으며 TOSS API를 이용하여 수익 창출을 실현하였습니다.
주요 성과
주요 서비스(결제, 쿠폰, 리뷰, 동영상 업로드, 알림) 설계, 개발, 운영 참여
결제 후 비동기 처리를 이용한 서버 안정화 및 사용자 경험 향상
TUS 프로토콜의 대용량 파일 업로드 및 중단 재개 기능 사용으로 사용자 경험 향상
Redis 캐시 시스템을 도입을 통해 유튜브 API 호출량 60% 절감, 속도 30% 향상
알람 호출 방식 변화(short polling → sse)을 통한 API 호출 98% 감소 및 서버 안정화
결제 성공 후 동영상 자막, 메시지 큐를 이용한 번역 비동기 처리
번역 및 자막 생성 서비스를 운영하면서 결제 완료 후 자막 서버를 비동기 호출하는 구조로 개발되었습니다. 이때 사용자가 동시에 결제를 진행하면 자막 서버가 다수의 요청을 동시에 처리하게 되어 서버 과부하로 인한 서비스 다운이 발생하는 문제가 있었습니다.
위 문제점을 해결하기 위해 메시지 큐 기반 구조로 변경하였습니다. 메시지 큐의 종류는 다양했지만, 이전 프로젝트에서 사용했고 순서를 보장하고 ACK 메커니즘을 제공하는 RabbitMQ를 사용하였습니다.
기본적으로 결제가 성공을 하면 해당 영상의 정보를 메시지 큐에 적재하고 자막 서버가 차례대로 처리하도록 개발을 진행하였습니다.
또한, 메시지 큐에 요청이 많아지면 마지막 요청자는 서비스를 이용하기 위해 오랜 시간 기다려야 하는 문제점이 있었기 때문에 Scale-Out을 이용하여 서버를 추가 배포하여 병렬 처리 능력을 확보하였습니다.
마지막으로 서버의 특정 에러로 인하여 실패를 하게 된다면 실패 메시지 큐에 저장하도록 했습니다. 서버가 새로운 작업을 시작하기 전에 실패 메시지 큐를 먼저 확인하게 실패한 작업을 재처리하도록 하여 안정성을 강화했습니다.
위의 해결책을 통하여 다수의 결제 요청에도 안정적인 운영이 가능해졌고 병렬 처리를 가능하게 함으로 사용자의 대기 시간이 감소했으며 실패 메시지 큐를 통한 재시도 로직 덕분에 작업 성공률을 높일 수 있었습니다.
결과적으로 자막, 번역 생성 과정에서 대기 시간이 짧아지고, 장애 발생 시에도 빠른 복구가 가능해 사용자 경험을 향상했습니다.
대용량 파일 업로드를 위한 TUS 프로토콜 도입
해당 프로젝트는 사용자가 자신이 가지고 있는 동영상을 업로드해서 자막과 번역 기능을 사용할 수 있는 기능이 있었습니다. 그렇기 때문에 동영상 업로드 서버에서는 10MB ~ 2GB까지 다양한 크기의 영상이 업로드될 수 있었고 500MB 이상의 영상부터는 업로드 실패되는 확률이 80% 이상으로 증가하였습니다.
기존 영상 업로드 방식은 브라우저에서 서버로 직접 업로드하는 방식이었으나 이는 네트워크 타임아웃 혹은 Out of Memory Exception이 발생하였습니다. 또한 사용자에게 진행 상황을 보여 줄 수 없기에 같은 화면으로 오랜 시간 멈춰 있어 UX 상으로 좋지 않았습니다.
문제점을 해결하기 위해 검증되었고 HTTP 프로토콜을 기반으로 사용할 수 있는 TUS 프로토콜을 사용하기로 하였습니다.
TUS 프로토콜은 파일을 청크(Chunk) 단위로 나누어 전송하는 방식으로, 대용량 파일을 효과적으로 업로드할 수 있습니다. 또한 업로드 중 특정 원인 탓에 실패하더라도 이미 전송된 청크는 유지된 상태에서 실패 지점부터 다시 전송을 시작할 수 있어 안정적인 파일 업로드를 보장합니다.
이를 통해 대용량 파일 업로드의 효율성을 극대화하였고 서버의 메모리 사용량을 줄여 자원을 효율적으로 사용하였습니다.
또한 실패 지점에서 재개할 수 있는 기능과 진행률 정보 제공 기능을 통해 사용자 경험을 향상했습니다.
Redis를 활용한 캐시 전략
유튜브 링크를 입력하면 유튜브 API를 통해 영상을 가져오는 로직이 있었습니다. 이때 사용자가 악의적으로 같은 영상을 반복해서 요청하게 되면 유튜브에서 제공한 API 할당량이 금방 소진되는 것을 확인했습니다. 또한 같은 영상의 정보임에도 불구하고 계속해서 중복 정보가 쌓인다는 문제점이 있었습니다.
이를 해결하기 위해 유튜브 API 키를 여러 개 발급받아 할당량이 소진되면 다른 API 키를 사용하여 진행하는 방법과 연동된 영상의 정보를 캐싱 처리하여 데이터를 관리하였습니다.
여러 개의 API 키의 경우에는 env파일로 관리를 하면서 실시간으로 할당량을 체크하면서 소진하게 되면 키를 변경하는 식으로 진행하였습니다.
또한 캐싱 처리에 관해서는 다음과 같은 로직으로 캐싱 처리를 하였습니다.
1. 요청을 한 동영상 정보는 DB에 저장한다.
2. 요청된 횟수를 레이스에 저장한다
3. 요청 횟수가 10회 이상이 된다면 동영상의 정보를 레디스에 저장한다.
4. 같은 영상에 요청이 들어온다면 유튜브 API를 통한 정보 제공이 아닌 레디스에 있는 정보 제공
요청 횟수를 10회로 했을 때 캐시 히트율이 가장 높게 측정되었기에 선택하였습니다.
또한 동영상 정보를 캐시 처리 했기에 사용자에게 정보제공의 속도가 빨라져 사용자의 경험을 향상했습니다.
결론적으로 유튜브 API 호출량은 60% 절감하였고 사용자 응답 속도는 약 30% 향상되었습니다.
CliveWorks
알엠소프트
2023.02. ~ 2023.10.
개요
사용자가 작업물을 할당 받고 해당 작업물에 작업을 할 수 있는 서비스
국가 AI 학습 모델 데이터를 확보하는 것이 목표
자신이 진행한 작업물에 관해 정산을 받을 수 있습니다.
서비스 소개
국가 AI 학습 모델 사업의 일환으로 특정 동영상에 관하여 나오는 대사를 사용자가 입력을 하고 해당 대사를 3개국 언어(영어, 중국어, 일본어)로 번역하는 서비스 입니다.
사용자는 각자 작업 해야 할 동영상을 할당 받고 작업을 완료하면 단가에 맞는 금액을 정산 받을 수 있습니다.
또한 관리자는 해당 작업물들을 검토하고 데이터 형식에 맞게 수정해야 하는 목표가 있습니다.
주요 성과
주요 서비스(정산, 데이터 구축, 어드민 페이지, 배치) 설계, 개발, 운영 참여
Jenkins를 통한 서버리스 방식으로 약 80% 운영비 절감
정산 자동화 시스템 개발을 통한 업무 효율성 증대
어드민 페이지 쿼리 리팩토링을 통한 성능 개선( 2초 -> 50ms)
Jenkins를 통한 서버 가동 시간 제어로 운영비 절감
기존 되었던 배치 작업은 상시 서버가 가동되었고 일별로 6개의 배치 작업이(한 작업당 약 30분~40분) 실행되고 있었습니다. 그렇기에 서버 비용으로는 매달 약 20만 원이 발생하고 있었습니다.
이를 해결하기 여러 가지 방안이 나왔습니다
1. 기존에 사용하던 어드민 서버에 배치 코드 추가
2. AWS Batch를 이용하여 서버리스 컨테이너 방식으로 처리
3. 기존에 사용하던 Jenkins를 이용하여 서버를 켜고 끄는 방식
1번의 경우에는 개발 당시에는 공수가 덜 들어가 가장 편한 방법이었지만 추후 유지 보수가 어렵다고 판단하였습니다.
2번의 경우에는 완전 관리형 서버리스 서비스이기에 관리가 용이하고 비용적인 측면에서 확실한 이득이 있지만 러닝 커브가 발생하며 바로 적용하기에는 적합하지 않았습니다.
그렇기에 기존에 사용하고 있어 익숙하고 빌드 배포 실행을 하나의 프로세스로 관리 할 수 있는 3번 방법을 도입하기로 하였습니다.
3번 방식을 채택하면서 배치 서버에 관해서만 파이프라인을 수정하였습니다. 서버가 켜지는 시간을 고려하여 서버의 시작 시각과 종료 시각을 설정하였고 모든 작업이 완료되면 자동으로 서버가 꺼지도록 하였습니다.
이를 통해 기존에 월 20만 원의 서버 비용을 월 약 4만 원으로 줄였습니다.
어드민 페이지 성능 개선
실시간으로 작업물의 진행률과 완료된 작업물의 결과를 확인하는 어드민 페이지가 있었습니다.
그런데 작업물이 점차 늘어나면서 페이지 로딩 속도가 느려졌고 이에 따라 관리자들의 업무 효율이 떨어지고 있었습니다.
이를 해결하기 위해 어디서 병목이 발생하는지 파악했고 조사 결과 쿼리 실행 부분이 가장 큰 원인이었습니다.
이에 쿼리를 분석하여 다음과 같은 쿼리 튜닝 계획을 수립했습니다.
1. 불필요한 LEFT JOIN은 INNER JOIN으로 변경
2. JOIN으로 해결할 수 있는 데이터를 굳이 서브쿼리로 가져오지 않도록 수정
3. Mybatis 동적 쿼리 적용
일반적으로 LEFT JOIN은 기준 테이블에 대해 풀 스캔이 발생하여 성능 병목이 생기기 쉽습니다.
그래서 INNER JOIN으로 바꾸면 성능상 이점이 있지만 우리의 경우 조건 값에 따라 A 테이블에는 데이터가 있지만 B 테이블에는 없을 수도 있었습니다.
이를 해결하기 위해 MyBatis의 동적 쿼리(if문)를 활용하여 조건에 따라 INNER JOIN 또는 LEFT JOIN을 선택하도록 쿼리를 수정했습니다.
이 작업만으로도 약 2초 걸리던 쿼리가 1초 미만으로 단축되었습니다.
그리고 INNER JOIN만으로도 충분히 가져올 수 있는 정보를 불필요하게 서브쿼리로 작성한 경우가 있었는데, 이 부분을 모두 INNER JOIN으로 변경함으로써 쿼리 실행 시간을 더욱 단축할 수 있었습니다.
쿼리 실행 순서를 조정했습니다. JOIN 한 테이블에 대한 조건을 WHERE 절에서만 체크하고 있었는데, 이는 SQL 실행 순서상 더 많은 데이터를 먼저 가져온 뒤에 조건으로 걸러내야 하므로 병목 현상의 원인이 될 수 있습니다. 그래서 JOIN 문 자체에서 필요한 조건을 걸어 불필요한 데이터를 미리 걸러내도록 수정했습니다.
이러한 최적화를 통해 최종적으로 2초가 걸리던 쿼리를 300ms 수준으로 크게 단축할 수 있었습니다.
마지막으로 해당 데이터들은 자주 사용되기 때문에 캐시로 저장하여 응답 속도를 약 20ms 수준으로 한번더 단축하였습니다.
포트폴리오
기술 스택
Java, Spring, Spring Boot, MySQL, Redis, Git, Spring Batch, rabbitmq, Jenkins, Docker, mybatis, JPA
교육
서울디지털대학교
대학교(학사) | AI소프트웨어공학과
2026.02. ~ 현재 | 재학 중
메가스터디it아카데미
사설 교육
2021.03. ~ 2021.09. | 졸업
자기소개
[1. 소통하는 개발자]
저는 개발자가 단독 작업보다는 팀 내 협업을 통해 성장한다고 믿습니다. 팀 프로젝트에서는 각자의 요구 사항과 아이디어가 다를 수 있기 때문에, 자신의 의견만을 고집하기보다는 상대방의 의견을 경청하는 태도가 매우 중요하다고 생각합니다.
예를 들어, 제가 팀장으로 참여한 GlowGrow 프로젝트에서는 헤어 디자이너 인턴과 고객을 연결해 주는 프로젝트였습니다. 저는 팀장으로 프로젝트를 기획하고 핵심 기능을 정리하여 팀원분들께 전달하였습니다. 이때 한 팀원은 결제 기능을 1순위로 추가해야 한다는 의견을 냈습니다. 하지만 진행한 프로젝트의 취지에 완벽하게 부합하는 기능이 아니고 핵심 기능을 완성한 후 결제 기능을 개발해도 늦지 않다고 판단하였습니다. 이에 팀원의 의견을 먼저 충분히 듣고, 핵심 기능 완성 후 결제 기능을 개발하는 이유를 논리적으로 설명하여 합의를 끌어냈습니다.
반면 채팅 기능의 경우, 처음에는 2순위로 생각했으나 다른 팀원들은 사용자 편의성과 프로젝트의 취지에 적합하다는 의견을 근거로 MVP에 반드시 포함되어야 한다고 주장했습니다. 여러 의견을 종합한 결과, 팀원들의 의견을 수용하여 채팅 기능을 핵심 기능에 포함하기로 하였습니다.
또한, 업무 외 시간에도 식사하거나 개인적인 얘기를 하고 취미 생활이 같은 동료분들과 취미 생활을 즐기는 등 동료들과 꾸준히 소통하며 친밀감과 신뢰를 쌓는 노력을 기울였습니다. 이러한 소통은 단순한 의견 전달을 넘어서 원활한 협업과 팀워크 강화에 큰 역할을 한다고 믿습니다.
[2. 항상 의문을 갖는 개발자]
좋은 개발자가 되기 위해 저는 항상 "왜?"라는 질문을 스스로에게 던지는 자세를 유지합니다. 이 질문은 단순히 문제를 해결하는 것을 넘어서 문제의 근본 원인을 파악하여 보다 견고하고 확장 가능한 코드를 작성하는 데 큰 도움이 됩니다.
예를 들어, 서비스 리팩토링 프로젝트에서 팀장님께서 유튜브 연동 기능의 도입을 제안하셨을 때 저는 곧바로 개발에 착수하기보다 먼저 "왜 이 기능이 필요한가?"라는 질문을 던졌습니다. 처음에는 해당 서비스를 주로 자신의 영상을 자막과 번역 목적으로 사용하는 사용자만 있다고 생각했지만 스스로에게 던진 "왜?"라는 질문을 통해 일반 사용자들도 유튜브 콘텐츠를 다양한 언어로 즐길 수 있다는 가능성을 발견했습니다. 이 과정을 통해 기능 도입의 필요성을 명확히 인지한 후 주도적으로 여러 기능을 반영하여 개발을 진행할 수 있었습니다.
이처럼 "왜?"라는 질문은 문제의 본질을 깊이 이해하고 실무에서 예기치 못한 버그나 오류를 미연에 방지하며 프로젝트 전반의 품질과 안정성을 높이는 핵심 도구라고 믿습니다.