김준영 - 6년차 백엔드 개발자

Contact

My Working Style


Skills

Work Experience

더존비즈온 협업플랫폼개발2센터 (6년차)

2021.09 ~ 재직중

Projects

전자세금계산서 서비스 운영 및 유지보수 2021.09 ~ 현재

API Latency 개선 9초 → 350ms
문제
  • 월 초(1~10일) 전체 트래픽 40% 집중되는 패턴
  • 세금계산서 생성 API 응답시간이 최대 9초 이상으로 치솟는 현상 발생
해결 과정

1) APM 분석

  • 애플리케이션 내부에서 소모되는 시간이 전체 소요 시간의 90% 이상
  • 시스템의 CPU·메모리 5%, 30%로 정상 범위
  • 애플리케이션 내부 스레드 병목 의심

2) Thread 분석

  • Thread Dump 분석 과정에서 BLOCKED 스레드 대량 포착
  • Stack Trace 확인 결과 특정 메서드가 synchronized에 의해 직렬 처리되고 있음을 발견
  • 코드 분석 후 synchronized 제거

3) 부하 테스트 수행

  • 락 제거 후 성능 측정
  • synchronized 유무만 다른 두 버전 비교
  • AS-IS: 동시 요청 증가시 직렬처리로 인한 TPS 12 고정
  • TO-BE: 동시성에 비례해 처리량 상승 → TPS 최대 70로 개선

4) 추가 병목 검증

  • 락 제거 후 부하를 높이자 병목이 애플리케이션에서 DB로 이동하여, 커밋 시 redo 로그 flush 대기와 로그 전환 지연이 관측됨
  • 락 제거로 늘어난 DB 부하가 운영에서도 같은 병목을 만드는지 판단 필요
  • 개발 환경은 운영 대비 redo 로그 그룹 수가 적고(5개 / 10개) 사양도 낮아, 운영 반영 후 최대 피크 모니터링 수행
  • 피크 시간대에도 동일 현상이 나타나지 않아, 운영 DB 설정은 현행 유지로 결정
성과
  • 직렬 처리 병목 제거로 단일 인스턴스 처리량 개선 TPS 12 → 70
  • 운영 반영 후 latency 9초 → 350ms 안정화
보상 트랜잭션 재처리 프로세스 구축
문제
  • 포인트 차감 → 세금계산서 발행 → (발행 실패 시) 포인트 차감 취소 프로세스
  • 네트워크 오류, 포인트 시스템 문제로 보상 트랜잭션(포인트 차감 취소) 실패 케이스 존재
  • 포인트만 차감되고 문서는 발행되지 않은 채 남으며, 이를 회복할 메커니즘 부재
해결 과정

1) 보상 트랜잭션 결과 케이스 분석

  • 보상 트랜잭션 결과를 성공 / 실패 / 응답 미수신으로 구분
  • 실패와 응답 미수신은 포인트가 차감된 채 남아 있을 수 있어 재처리 대상으로 분류

2) 보상 결과 영속화

  • 보상 트랜잭션 실패·응답 미수신 건을 관리하는 테이블 생성
  • 취소 호출에 필요한 식별 정보, 재처리 상태, 재처리 횟수, 사용자 고유 번호로 구성

3) 자동 재처리 구현

  • 스케줄러로 미처리 건을 인입 시간 순으로 조회해 취소 API 재호출
  • 성공 시 SUCCESS, 실패 시 재시도 횟수 증가

4) 최종 실패 대응

  • 최대 재시도 횟수 초과 시 FAIL 처리
  • 자사 메신저 알림 발송 및 백오피스 수동 복구 기능 제공
성과
  • 시스템이 보상 실패를 자동으로 인지하고 재처리하는 프로세스 구축
  • 고객 불편 감소 및 수동 복구 업무 감소
멱등성 개선
문제
  • 클라이언트 오동작으로 문서 생성 요청이 중복 전송되어 중복 생성되는 문제 발생
해결 과정

1) 원인 분석

  • 기존에 세금계산서 문서 관리 테이블에 클라이언트가 전달한 멱등키(연동사 문서 번호)를 조회해 이미 존재하면 거부하는 방어 로직 존재
  • 조회와 문서 생성 시점 차이가 있어 동시 요청은 조회 시점에 미존재로 판단해 통과
  • 조회 후 판단하는 방식으로는 동시 요청을 막을 수 없어, 이를 보완할 수 있는 구조 필요

2) 유니크 제약 기반 중복 차단 구조 설계

  • 동시 요청까지 막으려면 DB 유니크 제약이 가장 확실하나, 기존 세금계산서 테이블에 직접 적용의 제약이 존재
  • 이미 생성된 중복 문서가 있어 삭제로 정리할 수 없었고, 약 500GB 규모 테이블이라 유니크 인덱스 추가(DDL) 부담 존재
  • 대안으로 멱등키 관리 테이블을 별도로 추가해 고객 정보와 문서 번호 저장
  • 유니크 제약 조건으로 동시 요청 중 하나만 저장 성공
  • 멱등키 저장과 문서 저장을 같은 트랜잭션으로 처리해 문서 저장 실패 시 멱등키도 함께 롤백

3) 중복 요청 응답

  • 동일 문서 번호 재요청 시 중복 요청임을 응답하고 기존 문서 번호 전달
성과
  • 중복 문서 생성 제거
쿠폰 사용 동시성 제어
문제
  • 채권 서비스 출시 프로모션으로 회사별 무료 쿠폰 제공
  • 쿠폰은 회사 단위로 발급되고, 여러 직원이 쿠폰을 함께 사용하는 구조
  • 쿠폰에 무료 채권 발행 횟수를 기록하는 횟수형 쿠폰이었고, 잔여 횟수를 SELECT 후 UPDATE로 차감하는 구조에서 쿠폰 초과 사용 우려
해결 과정

1) 동시성 재현

  • ExecutorService, CountDownLatch로 동시 요청을 재현해 초과 사용 확인

2) 원자적 UPDATE로 개선

  • 잔여 횟수 확인(잔여 > 0)을 WHERE 조건절로 옮겨 차감과 한 문장으로 합치고, 확인과 차감 사이 다른 트랜잭션 개입 방지
  • 기존에는 잔여 횟수를 조회해 잔여·차감 횟수를 이력으로 남겼으나, 차감 횟수만 남겨도 잔여를 역산할 수 있어 조회 없이 이력을 남기도록 변경
  • 영향 행이 0건일 때만 쿠폰 상태를 조회해 케이스(만료·소진·없음)별 응답
성과
  • 확인과 차감을 단일 쿼리로 합쳐, 동시 요청에서도 쿠폰 초과 사용 차단
인덱스 생성 + 쿼리 수정, 조회 성능 개선 (6,800ms → 9.412ms)
문제
  • 국세청 수집 세금계산서 조회 API에서 지연 발생
  • 쿼리 실행이 전체 응답시간의 99% 이상
해결 과정

1) 실행계획 분석

  • cost 약 250만 / 실행시간 6,800ms
  • 실행 계획 상 Index Scan임에도 비용이 높아 인덱스 점검

2) 인덱스 분석

  • 조회 조건은 사업자번호 + 작성일자
  • 두 조건을 효율적으로 탐색할 복합 인덱스 부재
  • 사업자번호로 Index Scan이 수행됐지만, 사용된 인덱스에서 사업자번호가 비선행 컬럼이라 결과적으로 Index Full Scan으로 동작

3) 인덱스 설계

  • 조건 기반 복합 인덱스 생성
  • 컬럼 순서: 등치(사업자번호) 선행 + 범위(작성일자) 후행

4) 쿼리 수정

  • 작성일자 조건에 to_timestamp 함수로 감싸져 있어 인덱스 스캔 불가
  • 검토 후 to_timestamp 제거
성과
항목 개선 전 개선 후
cost 250만 5,000
시간 6,800ms 9.412ms

뉴스 데이터 수집 시스템 개선 2024.03

데이터 모델 재설계(1:N → N:M) 및 확장 가능한 수집 구조 설계
문제
  • 기존 뉴스 서비스는 단일 언론사만 고려한 설계
  • 언론사가 제공하는 카테고리(paper_categories)에 뉴스 데이터가 1:N으로 매핑되는 구조
  • 서비스 고도화로 다수 언론사의 데이터를 수집할 필요성 대두
  • 언론사별 카테고리를 플랫폼 기준(예: 정치·IT)으로 통합해 제공해야 하는 요구사항 발생
해결 과정

1) N:M 매핑 구조의 데이터 모델 재설계

  • platform_categories 테이블 신설: 자사 서비스 플랫폼별 표준 카테고리 관리
  • categories_mapping 테이블 추가: N:M 관계 구현으로 하나의 언론사 카테고리가 여러 플랫폼 카테고리에 매핑 가능하도록 설계

2) 전략 패턴 기반 수집 로직 공통화

  • 언론사마다 수집 API와 응답 데이터 구조가 상이한 문제 발생
  • 전략 패턴을 도입하여 전체 수집 흐름은 유지하면서 데이터 수집 및 가공 부분을 전략 클래스로 분리
  • 신규 언론사 추가 시 전략 클래스만 추가하여 확장 가능한 구조로 설계(개방 폐쇄 원칙 준수)
성과
  • N:M 매핑 구조로 전환해 코드 변경 없이 데이터 추가만으로 언론사 2곳 추가 연동
  • 전략 패턴으로 수집·가공 로직을 분리해, 신규 언론사는 전략 클래스 1개 추가만으로 확장(OCP 준수)

이커머스 토이 프로젝트

상품 조회 캐싱
문제
  • 상품 데이터는 조회 비중이 높고 변경 빈도는 낮음
  • 트래픽 증가에 따른 DB 부하와 응답 지연 우려
해결 과정

1) 캐시 조회 및 갱신 전략

  • 캐시 조회 전략 : 캐시 Hit 시 캐싱 데이터 반환, 캐시 Miss 시 DB 조회 → 데이터 캐싱 후 반환
  • 캐시 갱신 전략 : 캐시 저장소 ↔ DB 정합성 보장을 위한 DB 수정 트랜잭션 commit 완료 후 TransactionEventListener로 삭제

2) 상품 다건 조회 캐싱

  • 상품 다건 조회 시 자주 조회되는 1페이지 상품만 캐싱하여 캐시 저장소 효율적 사용
  • 이중 캐시 구조로(상품 목록 id + 상세 정보) 캐싱 데이터 갱신 시 목록 캐시 전체 갱신 방지

3) Cache Stampede 방지

  • 캐시 만료 시 집중적인 조회 트래픽 유입으로 인한 DB 부하 증가를 우려하여 로컬 락 기반 stampede 현상 방지
  • 상품 정보 일괄 캐시 만료를 방지하기 위해 Jitter를 활용한 만료 시간 분산
성과
  • 상품 조회 트래픽을 캐시 레이어로 흡수해 DB 부하 감소 및 응답 속도 개선
  • 상품 다건 조회 시 상품 ID 캐시 구조로 단건 상품 데이터 갱신만으로 다건 조회 응답까지 반영한 효율적 전략 구성
  • 로컬 락 + Jitter로 Cache Stampede 방지
이벤트 기반 상품 정보 집계(Kafka)
문제
  • 이벤트 기반 사용자 상품 구매 정보 집계
  • 이벤트 유실 및 유령 이벤트 발생 가능
  • 메시지 중복 발행 시 이벤트 중복 처리
해결 과정

1) Outbox 패턴 적용

  • 비즈니스 로직과 발행할 이벤트를 동일한 트랜잭션으로 묶고 발행할 메시지를 outbox 테이블에 적재
  • 스케줄러로 outbox를 읽어 메시지 발행, 발행 완료 시 완료 처리
  • 발행 실패 시 retryCount 증가 → 최대 재시도 횟수 초과 시 DLQ로 관리 → 운영자가 수동 분석·복구

2) 메시지 소비 멱등 구조 설계

  • 메시지 소비 시 비즈니스 로직과 동일한 트랜잭션으로 묶어 소비된 메시지를 event_handled에 저장(eventId)
  • 중복 메시지 수신 시 eventId를 DB 레벨에서 유니크 제약으로 멱등성 보장
  • 지속된 소비 실패 시 소비 불가능한 메시지 DLT로 관리
성과
  • 비즈니스 트랜잭션과 Outbox 적재를 묶어 이벤트 유실·유령 이벤트 동시 차단, Kafka 장애 시에도 비즈니스 흐름 보장
  • eventId + DB 유니크 제약 이중 안전망으로 at-least-once 환경에서 컨슈머 중복 처리 차단
  • 재시도 한계 초과 메시지는 DLQ/DLT로 격리해 정상 메시지 흐름 유지, 운영자 수동 분석·복구 경로 확보

Certifications

정보처리기사 2023.09
SQLD 2022.06
네트워크 관리사 2급 2022.04