목차
소개
안녕하세요.
올리브영 온라인몰에서 교환·반품 서비스를 담당하고 있는 클레임 스쿼드 현앙입니다.
이번 글에서는 수천 줄짜리 PL/SQL 프로시저에 얽혀 있던 교환·반품 로직을 Java로 이관하며, 기능별로 분리하고 유지보수성을 높였던 경험을 공유하려 합니다.
우리가 마주한 수천 줄 짜리 프로시저라는 문제는 단순한 기술 부채에 그치지 않았습니다. 그 영향은 곧바로 고객 경험으로 이어졌죠.
"환불이 왜 지연되나요?" = 고객님 죄송합니다.. 오류가났네요..
"반품신청했는데 회수를 안해가요" = 고객님 죄송합니다.. 반품접수가 안됐어요..
"교환이 접수된 건 맞나요?" = 고객님 죄송합니다...
이런 문의들의 대부분은 개발자가 디버깅하기 어려운 구조와 모든 로직이 한데 엉켜있는 레거시 프로시저에서 비롯된 경우가 많았습니다.
"개발자도 프로시저 내에서 발생한 오류를 추적하는 것이 불가능했고, 블랙박스와도 같은 느낌이었기에...."
"프로시저 디버그는 왜이렇게 어려운걸까요.. 수정과 컴파일은.. 왜.. 또.. 복잡하고... 어렵...고..난리야..."
거대한 프로시저의 그림자
우리 시스템에는 커머스에서 가장 중요한 모든 흐름이 하나의 프로시저 안에 들어 있었습니다.
- 주문 완료
- 주문 취소
- 교환 접수/철회/완료
- 반품 접수/철회/완료
- 옵션 변경
이 모든 것이 7,000줄이 넘는 PL/SQL 코드로 구성된 단일 프로시저 안에 뒤섞여있었습니다.
문제는 단순히 코드가 길다는게 아니라 비즈니스 로직 경계가 무너져 반품 절차 하나만 수정하려 해도 주문, 교환 로직에까지 영향을 미치는 구조였습니다. 이로 인해 작은 수정이 전사적인 서비스 리스크로 이어졌고, 결국 누구도 건드릴 수 없는 **기술 부채의 핵심(Core Tech Debt)**으로 남게 되었습니다.
이 구조는 모두가 기술 부채임을 알고 있었지만, 어디서부터 손대야 할지 모르는 상태로 오랜시간 유지되었습니다. 프로시저 안에는 수년간의 패치, 신규 정책이 누적되어 있었고, 문서화 되지 않은 수많은 분기 처리가 있었기 때문입니다. 결국 누구도 쉽게 들어가서 수정할 수 없는 ... 건드리면 터져버리는 폭탄이 되어버린거죠. 그로인해 아무도 고치고싶어하지않는, 고치지않는 코드가 되어버렸습니다.
| 문제 영역 | 상세 설명 |
|---|---|
| 디버깅 난이도 | DB 내부에서의 함수 호출, 로그성 데이터 부재 |
| 인력 의존성 | 소스를 이해하는 인력이 극소수라, 변경 자체가 리스크 |
| 우회 로직 남발 | 프로시저 수정을 피하기 위해 호출 앞뒤에 로직을 붙여 임시 대응 발생 |
"난 반품로직만 수정하고 싶은데.. 왜 주문이 안되는거야^.ㅠ...."와 같은 작은 변경이 곧 전사적 리스크가 되는 상황, 바로 이것이 우리가 탈출하고자 했던 현실이었습니다.
바로 이 상황에서 "이제는 프로시저와 이별하자!"라는 결심이 시작되었습니다.
레거시 탈출을 결심하다
우리가 내린 해법은 단순했습니다.
“프로시저를 쪼개고, 기능별 로직을 Java에서 다루자.”
하지만 실행은 쉽지 않았습니다.
PL/SQL은 데이터베이스 내에서 실행되므로 네트워크 오버헤드가 없고 DB 내부에서 최적화된다는 장점 때문에, Java로 변경시 성능 저하 우려가 있었으며 7,000줄짜리 코드에는 지뢰같은 예외 케이스도 숨어 있었습니다.
또한 올리브영은 MSA를 목표로 하고 있기 때문에 각 모듈별 중요 로직들을 신규 API로 이관을 해야하는지에 대한 고민이 있었습니다.
다만 프로시저 로직에 대한 이해도가 낮았고, 커머스에 가장 중요한 로직이기 때문에 완벽히 신규로 만드는 것에 대한 부담이 있었습니다.
따라서 우리는 무중단 점진적 이관 전략을 택했습니다.
올리브영 온라인몰은 24시간 많은 고객님들이 들어오는 시스템기에 무중단 점진적 전환이 매우 중요했습니다. 저희 클레임 스쿼드는 문제 해결 방법으로 레거시 전환의 모범 사례로 알려진 Strangler Pattern을 적용했습니다. 이는 기존 레거시 시스템을 새로운 시스템으로 점진적으로 대체하는 전략이자 올리브영 개발 조직의 개발 철학 중 하나라, 저희는 이 전략을 택하였습니다.
- 설계: 주문·교환·반품·옵션 변경 기능별 경계를 재정의
- 도입: 프로시저 호출 구간 앞단에 Java 모듈을 두어, 기존 프로시저는 유지한 채 점진적으로 전환
- 실행: 기능 단위로 이관하면서 장애 발생 시 [Fallback] 모드로 즉시 원복 가능하도록 설계
- 검증: 단위 및 통합 테스트 강화, 주요 지표 모니터링 체계화
점진적 이관 : Step-by-Step
🧩 Phase 0. 사전 준비 (Preparation)
목표 : 리스크 최소화와 빠른 의사결정을 위한 기능 분석 및 구조 파악
- 모듈별 기능 분석 : 미사용 분기처리, 예외처리 등 중요로직 파악을 위한 모듈별 흐름도 작성
- 트랜잭션 경계 맵핑 : COMMIT/ROLLBACK 지점, 격리수준, 재시도·보상 로직 정리
- 데이터 계약 정리 : 입력/출력 스키마, 에러 계약, 신·구 모듈 간 호환 규칙 정의
🧭 Phase 1. 도메인 모델링 (Domain Modeling)
목표 : 레거시 의존을 줄이고, 기능별 경계를 명확히 정의
- 모듈간 경계 분석 : 주문·교환·반품·옵션 변경 기능별 도메인 경계 재정의
- 도메인 엔티티/Value Object 설계 : 도메인 경계별 필요 엔티티 정의
- Fallback 로직 설계 : 문제 발생시 프로시저 버전으로 원복될 수 있도록 로직 설계
🚀 Phase 2. 모듈 이관 (Migration)
목표 : 기능 단위로 점진적 전환 및 안정성 확보
- Java 모듈 구현 및 테스트 : 단위 테스트, 통합 테스트 진행
- Shadow 트래픽 검증 : 신규 모듈과 구 레거시를 병행 처리하여 결과 비교
- 모니터링 강화 : 주요 지표가 기준선을 유지하는지 실시간 검증
🧹 Phase 3. 레거시 해체 (Decommission)
목표 : 완전 전환 후 불필요한 복잡도 제거
- 나머지 모듈 Phase0 ~ 2까지 계속 진행
- 미사용 분기 제거 및 신규 모듈로의 완전 전환
A[기존 PL/SQL 프로시저]
A -->|분리| B[주문 모듈(Java)]
A -->|분리| C[교환 모듈(Java)]
A -->|분리| D[반품 모듈(Java)]
A -->|분리| E[옵션 변경 모듈(Java)]마주한 시행착오
1년간의 이관 과정에서 다양한 시행착오를 겪었습니다.
-
트랜잭션 문제
기존에는 프로시저에서 암묵적으로 처리되던 부분이 Java로 옮겨지며 데이터 반영이 끊기는 문제가 발생했습니다.
→ 트랜잭션 익셉션을 재설계해 안정성을 확보했습니다. -
로직 중복
PL/SQL과Java가 병존하면서 소스 이원화 문제가 있었습니다.
→ Feature Toggle 관리로 혼선을 줄였습니다.
교훈
- 모든 걸 한 번에 옮기려 하지 말 것.
- 모니터링은 철저하게 할 것!
- 작은 단위로 쪼개어 옮기고, 실패 시 안전하게 되돌릴 수 있어야 한다.
우리가 얻은 것
이관 이후 예상보다 큰 효과를 얻을 수 있었습니다.
-
유지보수성
기능별 모듈화 변경 범위가 명확해지고, 영향도 예측이 가능해졌습니다. 또한 반품접수 로직을 쉽게 고칠 수 있어 고객에게 편리한 기능도 쉽게 제공할 수 있게 되었습니다. -
디버깅 가능, 모니터링 강화
Java 전환 이후 로그와 예외 추적이 가능해지면서 장애 원인 파악 속도가 획기적으로 빨라졌습니다. 이 변화는 단순한 기술 개선이 아니라, 우리가 업무 병목을 ‘보이게 만든’ 결정적 진전이었습니다. 그전까지는 반품 접수에서 완료까지 걸리는 리드타임을 정확히 알 수 없었습니다. 어느 구간에서 지연이 발생하는지, 환불이 왜 늦어지는지조차 추적이 불가능했죠. 하지만 이제는 로그를 통해 반품 완료 단계의 오류를 실시간으로 식별할 수 있고, 이를 기반으로 병목 구간을 명확히 찾아내어 개선할 수 있게 되었습니다. 결과적으로 그동안 “언제부턴가 해결이 어려워진 문제들”까지도 이제는 근본 원인을 추적하고, 데이터 기반으로 해결해나갈 수 있는 환경이 만들어졌습니다. -
확장성 확보
주문/반품/교환 등 모듈별 기능확장이 자유롭게 가능해졌습니다. 예를들어 반품접수 단계에서 고객에게 환불 예정금액이나, 반품 배송비를 사전에 안내하는 기능도 쉽게 도입이 가능해졌습니다. 이러한 개선 사례는 다음 포스팅에서 자세히 다룰 예정입니다.
마치며
이번 레거시 탈출은 단순한 기술 전환이 아니라, 도메인 중심의 로직 재설계 과정이었습니다. 또한, 기술 부채 해결 과정이 고객 신뢰와 비즈니스 성장으로 직결됨을 깨닫게 된 중요한 작업이었습니다.
앞으로는 고객의 불만이 더 깊어지지않고 신뢰받을 수 있는 올리브영이 되도록 교환/반품 모듈의 개선은 계속될 예정입니다. 저희의 경험이 비슷한 고민을 하는 분들께 도움이 되기를 바랍니다.

