01

회사 업무

Profile

2020년부터 쥬비스다이어트에서 전국 53개 지점이 쓰는 CRM·ERP를 개발하고 운영하고 있습니다.

Java/Spring으로 API와 배치를 주로 만들고, 느린 쿼리나 외부 연동 장애가 생기면 실행계획과 운영 실측으로 원인을 확인한 뒤 고칩니다.

최근에는 사내 파일서버를 S3로 옮기고 있고, 그 전에는 EC2 서비스를 EKS로 전환하면서 CI/CD를 새로 구성했습니다.

Professional Experience

쥬비스 다이어트 | 시스템 개발팀 | 파트장 개발자

2020.10 ~ 현재

전국 53개 지점이 사용하는 CRM · ERP · 상담 시스템 · 고객앱 · 배치 · 홈페이지 담당

주요 프로젝트

CRM 장애 분석 및 쿼리 성능 개선

2026.04 ~ 현재
JavaSpring BootMyBatisMySQLGrafana
쿼리·프로시저 수정은 운영 reader(복제본)에서 수정 전후 EXPLAIN 실행계획과 실행 시간을 대조하고, 결과 건수가 같은지까지 확인한 뒤 반영했습니다. 아래 수치는 모두 그 실측값입니다.

회원 검색 API 504 — OR 분기가 만든 DEPENDENT SUBQUERY

  • 처음에는 COUNT(43초)와 LIST(16.6초)가 각각 60초 미만이라 단일 쿼리 임계값에는 걸리지 않고, 순차 실행 합계로 게이트웨이 타임아웃에 닿는 구조를 확인. 월초 쿠폰 일괄발행으로 결과셋이 커지는 월초에 재발하는 패턴까지 찾아 COUNT 재최적화를 별건으로 분리
  • 이후 단일 요청이 DB 커넥션을 60초 넘게 잡아 HikariCP 누수 경고 뒤 504가 나는 건이 이어짐. 커넥션 누수가 아니라 쿼리가 끝나지 않은 것으로 판단
  • EXPLAIN ANALYZE 결과, 신규 추가된 쿠폰 조건 OR 분기가 DEPENDENT SUBQUERY로 후보 행마다 재평가되어 수십만 회 반복 실행, 전체 24.5초 중 약 22초를 차지. 쿠폰 주문이 0건인 지점도 똑같이 22초가 걸려, 비용이 결과 건수가 아니라 후보 행 수로 정해진다는 걸 확인
  • 쿠폰 조건을 비상관 UNION 집합의 단일 IN 술어로 바꿔 COUNT·LIST에 같이 적용. 운영 DB에서 같은 파라미터로 A/B 실행해 결과 건수 동일을 확인했고, 지점별 약 22초 → 1~1.4초, COUNT+LIST 최악 합계 43.9초 → 2.4초
  • LIST가 1페이지에서만 빨랐던 이유가 LIMIT 조기 종료였다는 점도 확인 (마지막 페이지 21.9초 → 1.5초, 검색어 입력 시 22초 → 1초)

목록 조회 API 504 — 209초 → 16.6초

  • 지점 조건이 파생테이블 바깥에 있어 행마다 상관 서브쿼리가 재평가되던 구조. 필터를 서브쿼리 안으로 옮기고, 조회 주체별 패턴에 맞춰 복합 인덱스 3건을 설계. 일반 사용자용 (삭제여부, 발행일, 등록일), 계약별 윈도우 값 조회용 (삭제여부, 계약ID, 발행일), 삭제여부 필터가 없는 관리자용 (발행일, 등록일)

승인 처리 timeout · 알림 최대 6회 중복 발송

  • 외부 푸시 API가 지연될 때 HttpsURLConnection에 타임아웃이 없고 catch가 예외를 삼켜, @Transactional이 발송 실패를 모른 채 DB를 커밋하던 구조. 직원은 실패로 보고 재시도해서 같은 알림이 최대 6회 나감
  • connect 3초·read 5초 타임아웃과 예외 전파로 바꾸고, 화면에서 승인 성공과 알림 실패를 따로 보여주도록 수정

파일서버 → S3 이관 및 접근 방식 전환

2026.07 ~ 현재
AWS S3IRSAEKSJavaDockerGitHub Actions
  • 사내 파일서버(개인정보 포함, 수천만 건 규모)를 참조하는 코드를 전수 조사해 이관 범위 산정. FTP로 붙던 레거시 배치까지 확인했고, 배치 서버의 유일한 쓰기 경로였던 이전 검사 업체 연동은 업체 변경으로 이미 죽은 코드임을 확인해 이관이 아닌 제거 대상으로 판단
  • 설계 판단 — 개인정보가 섞여 있어 URL만 알면 접근되는 구조를 둘 수 없었음. CloudFront도 검토했지만 트래픽 대비 캐싱 실익이 적고 개인정보 캐싱이 부적절하다는 보안 검토 의견에 따라 철회하고 presigned URL을 채택. 서명 발급은 통합 API 서버 한 곳으로 모아 자격증명이 서비스마다 흩어지지 않게 함
  • IRSA 적용 중 기본 Credential Chain이 환경변수를 IRSA보다 먼저 확인해서, WebIdentityTokenCredentialsProvider를 명시하지 않으면 IRSA가 조용히 무시되는 함정을 발견해 수정
  • DB에 저장된 파일서버 URL은 마이그레이션 없이 조회 시점에 치환하도록 설계 (12개 테이블 컬럼, 적용 진행 중)
  • CRM presigned 전환 완료 (백엔드 13곳·프론트 64개 파일). presigned는 파일 단위 서명이라 서버가 접두어만 내려주던 구조로는 처리할 수 없어, URL 조립을 프론트에서 서버로 옮김

결과

  • 파드에서 액세스 키 제거, 파일 접근이 EC2 파일서버 의존에서 벗어남
  • 잔여 레거시(EC2 파일서버, PHP 다운로드 스크립트) 정리 진행 중

Notification 메시징 통합 및 Redis 장애 대응

2026.07 ~ 2026.09
NestJSBullMQRedisMySQLSMS API
  • 서비스별로 흩어져 있던 문자·알림톡 발송을 notification 서비스로 통합. MMS 첨부, 광고성(AD) 발송, 080 수신거부 연동
  • Redis 장애 때 문자는 이미 나갔는데 이력 큐 적재를 await하느라 호출자에게 실패로 응답되던 문제. 직원이 재발송하면서 문자가 중복 발송됨
  • ioredis 재접속 동작을 실측해 보니 적재 1회에 237초, 요청당 약 11분 커넥션을 점유. 적재를 응답 경로에서 분리하고, 시도 상한을 ioredis가 대기 명령을 버리는 경계(240초)에 맞춰 그 안에 복구되면 이력이 유실되지 않게 함
  • health가 비정상 판정에도 HTTP 200을 돌려줘 k8s probe가 파드를 재시작하지 못하던 문제를 503으로 수정

쿠폰 판매·환불 기능 개발

2026.07 ~ 2026.09
JavaSpring BootMyBatisMySQL
  • 설계 판단 — 기존 계약 환불 테이블은 15개 레포·420여 줄에서 참조되고 있어, 같은 테이블을 쓰면 계약/쿠폰 분기를 전부 추가해야 했음. 전용 테이블로 분리하는 대신 기존 환불 통계에 쿠폰이 자동 집계되지 않는 점을 감수했고, 통계 요구가 생기면 UNION으로 붙일 수 있도록 원장 구조(원결제 참조 음수행)를 맞춰 둠
  • 운영 중 환불금이 입금 확인 전 결제까지 합산돼 과다 계산되는 오류를 발견해 정정하고, 과거 이력을 전수 스캔해 같은 유형 2건을 추가로 찾아 산정 기준을 통일
  • 환불금·정산금 계산, 신청서 등록·상태 변경 API, 현금영수증 발행, 캐시 지급 취소 연동

AI 코딩 도구 기반 팀 개발 생산성 체계 구축

2026.03 ~ 2026.06
Claude Code (SkillsMCP)PythonSlack APINotion API
  • 팀 공용 스킬 레포를 만들고 운영. 브랜치 생성 → PR → 릴리즈까지 개발 흐름을 스킬로 만들어 상시 사용
  • 스킬 15개 작성 (VOC 처리 10, 개발 워크플로 3, 검증·분석 2). 반복 VOC마다 확인 위치와 조치 절차를 스킬에 적어 담당자별 처리 편차를 없앰
  • 이후 팀 자산으로 넓어져 2026년 9월 기준 51개 운영 중

결과 (스킬 도입 전후 담당 VOC 비교 — 이전 3개월 57건 / 이후 4개월 65건)

  • VOC 평균 처리 4.6일 → 1.8일, 당일 처리 12% → 46%, 7일 초과 지연 12건 → 2건
  • 외부 검사 연동 처리 15일 → 당일, 중간상담 통계 4.2일 → 1일

맞춤형 프로그램 기기 스케줄링 시스템

2026.03 ~ 2026.04
JavaSpring BootMySQLMyBatis
  • 고객 유형 판정 결과로 기기 구성을 추천하는 로직과 기기 자산 단위 매칭 설계 (신형 우선 배치, 동시 진행 기기, 오픈형 스케줄)
  • 이력 로그 테이블에는 변경 이력을 쌓기만 하고, 스케줄 테이블은 체크인 같은 특정 시점에만 로그에서 값을 가져와 갱신하는 캐시로 역할을 나눔
  • 모드 결정 시점 변경 — 오픈형은 스케줄 시점에 자산이 정해지지 않아 기기 종류 기준으로 모드를 미리 저장했는데, 체크인에서 신형 자산이 배정되면 구형 모드값이 선택지에 없어 불일치가 생김. 모드 결정을 자산이 확정되는 체크인·체중 트리거 시점으로 미루고, 룸형은 기존 흐름 유지

결과

  • 3월 31일 배포, 4월 예정대로 정식 오픈. 오픈 이후 데일리 이슈 없이 운영
  • 수기로 정하던 기기 배치를 고객 유형 기반 추천으로 전환, 기기별 사용 현황 집계 가능

Java → NestJS CRM 마이그레이션

2025.11 ~ 2026.03
NestJSPrismaMySQLGitHub ActionsArgoCDHelm
  • 로그인·권한 영역 설계 담당 — 프로세스 정의, ERD 문서화, 메뉴·메뉴 권한 유형 테이블 설계, 권한 변경 로그 설계
  • 메뉴/메뉴별 권한 API 20건 (권한 그룹·소속·직급·직책·사용자 단위 부여 및 차단), 사용자별 커스텀 메뉴, 매출 통계 대시보드 API

결과

  • 담당 범위 계획 대비 100% 완료, 운영 전환 후 prod 500 에러 월 평균 1건 미만 (서비스 자체 결함 0건)

AWS EKS 기반 전사 서비스 전환

2025.06 ~ 2025.10
AWS EKSKubernetesDockerHelmGitHub ActionsArgoCD
  • Spring Boot 서비스 컨테이너화, Helm Chart로 환경별 배포 매니페스트 구성
  • Health Check 엔드포인트 구현, ConfigMap/Secret 기반 설정 관리로 전환
  • GitHub Actions(빌드 → 테스트 → 이미지 푸시) + ArgoCD(Git 변경 감지 자동 배포)

결과

  • 환경 구성부터 prod 배포까지 1.5개월 (8/11 → 9/14), ERP 제외 전 시스템 전환
  • 배포 소요 시간 수십 분 → 수 분, 배포 절차 통일

Slack 기반 PR 리뷰·장애 알럿 자동화 봇 — 팀 공동 개발

2026.08 ~ 현재
TypeScriptNode.jsClaude Agent SDKSlack BoltJira API

팀장님이 만든 봇을 바탕으로, 팀원들과 함께 팀 PR 코드리뷰와 장애 알럿 처리에 쓸 수 있게 확장했습니다.

  • 리뷰 채널에 PR이 올라오면 자동 리뷰 후 GitHub 인라인 코멘트 게시. 승인은 GitHub에 실제 APPROVED가 남았는지 확인한 뒤에만 보고
  • 팀원마다 봇을 띄워도 같은 PR을 중복 리뷰하지 않도록 Slack 리액션 순서로 선착순 판정
  • Grafana 500 알럿이 오면 로그를 확인해 Jira 티켓을 만들거나, 기존 티켓에 로그를 코멘트로 추가하고 스레드에 링크 회신
  • 외부에서 들어오는 연결 없이 동작하도록 Socket Mode(아웃바운드 연결)로 Slack 연동

상세 경력

CRM 운영·유지보수 (2026.03 ~ 현재)

운영 지표 (사내 평가 기준)

업무 도구 로그인 — AWS Cognito (2025.03 ~ 2025.05)

홈페이지·플랫폼 런타임 리소스 조정 (2024.10 ~ 2024.12)

모니터링 계측 — DataDog RUM / APM (2024.08 ~ 2025.09)

DB 운영 자동화 도구 — AWS Lambda (2024.07 ~ 2025.05)

배포 파이프라인 구성 및 운영 (2025.08 ~ 2026.09)

외부 검사 연동 시스템 (2021.03 ~ 2021.08 / 2025.08 ~ 2025.10)

ERP 배치 시스템 재개발 (2025.03 ~ 2025.06)

GA + CRM 고객 여정 데이터 분석 (2022.05 ~ 2023.12)

MongoDB Data API 자체 구현 (2024)

기술 문서화 및 팀 표준 (2024.10 ~ 2026.09)

그 밖에