-
도메인 정책 레이어로 비즈니스 규칙 산포 방지
역할·시점·필드마다 수정 권한이 달라서 조건 분기가 UseCase 곳곳에 흩어질 게 뻔했음.문제 권한 정책 변경 시 수정 지점을 Policy 클래스 1개로 한정, 인프라 의존 없는 순수 함수라 단위 테스트도 DI 없이 가능한 구조로 개선.성과 - 도메인별 Policy 클래스 6종(Vacancy·Building·Snapshot·Memo·File 등) 으로 규칙을 모아 단일 파일 수정으로 변경 범위 한정
- 클라이언트가 전체 필드를 재전송해도 저장값과 실제로 달라진 필드만 계산(changedKeys) 해 역할·마감상태별 필드 마스크를 적용 — 클라이언트 구현 방식과 무관하게 정책 일관성 보장
- PolicyCtx 타입을 진입 시 1회 구성해 재사용함으로써 반복 DB 조회 제거
- 인프라 의존 없는 순수 함수라 DI 없이 단위 테스트 가능
-
스트리밍 기반 대용량 엑셀 Export로 메모리 리스크 차단
수천 건을 한꺼번에 메모리에 올려 Export하면 요청이 겹칠 때 메모리가 튈 수 있었음.문제 0.5GiB 메모리 제한 컨테이너에서 건수와 무관하게 메모리 점유가 일정 수준으로 수렴, 동시 Export가 몰려도 OOM(컨테이너 강제 종료) 없이 안정적으로 동작.성과 - ExcelJS 스트리밍 Writer로 임시 파일에 즉시 기록 후 HTTP 스트림 응답 — 완료/오류/연결 끊김 모두에서 임시 파일 정리로 안전한 생명주기 관리
- 청킹 조회 + ORM Identity Map 즉시 해제로 힙 점유를 청크 1개 분량으로 바운딩하고, 처리 루프에 setImmediate 삽입으로 이벤트 루프 블로킹 방지
- 동시 Export 세마포어(2슬롯) 초과 요청은 대기 없이 429 fail-fast 응답해 서버 전체 OOM 리스크 원천 차단
-
레거시 데이터 정제와 스키마 재설계로 DB 용량 및 조회 성능 동시 개선
약 135개 컬럼의 단일 테이블에 매월 전체 상태를 통째로 복제하고 인덱스를 남발하는 레거시 스키마가 그대로 올라오면, DB 용량도 조회 속도도 나쁠 수밖에 없는 상태였음.문제 공실 이력 원천 약 460만 행을 유효 데이터 12만여 행으로 정제 이관(16년 치 월별 이력 재구성), 레거시 대비 DB 용량 65% 이상 절감, 주요 조회 쿼리 평균 응답속도 70% 이상 개선.성과 - 이관 전 레거시 Oracle 프로시저(PL/SQL) 전체를 역설계해 각 테이블의 업무적 의미와 이관 리스크를 문서로 확정한 뒤 스키마 재설계 착수
- 신규 서비스 요구사항을 기준으로 불필요한 레거시 데이터를 폐기하고 필요한 데이터만 정제 및 이관, 정규화 수준을 높여 데이터 일관성 확보
- 실제 조회 패턴을 분석해 불필요한 인덱스를 최소화함으로써 쓰기 비용과 저장 공간 절감
- 시계열 데이터를 현재 상태(라이브) 테이블과 월별 스냅샷 테이블로 분리해 자주 조회되는 최신 데이터 접근 효율을 높이고 과거 이력은 별도 관리
-
변경·조회·반출 전 과정을 추적하는 감사 로그 체계 구축
회사 핵심 자산인 리서치 데이터를 다루는 시스템이라, '누가 언제 무엇을 바꾸고, 조회하고, 반출했는가'를 사후에 증명할 수 있어야 했음.문제 데이터 변경·접근·반출 이력이 각각의 로그로 남아, 이슈 발생 시 원인 추적과 책임 소재 규명이 가능한 구조 확보.성과 - 변경 로그: 수정 전/후 값을 JSON diff로 기록하고 Revision 버전과 연결해 어떤 변경 신호가 어떤 수정에서 발생했는지 추적 가능
- 접근 로그: 커스텀 데코레이터 + Interceptor + Extractor 패턴의 AOP 설계로 비즈니스 로직 오염 없이 데이터 접근 기록
- 반출 로그: 엑셀 Export 시 반출 사유와 범위를 기록해 데이터 유출 리스크에 대응
-
재실행 안전성과 전수 추적으로 운영 데이터 이관의 신뢰성을 직접 책임
일회성 작업이 아닌 회사 핵심 자산(운영 데이터) 이관이었기 때문에, 중간 실패 시 재실행해도 데이터가 중복 및 유실되지 않아야 했고, 이관이 끝난 뒤에도 '정말 빠짐없이, 정확하게 옮겨졌는가'를 스스로 증명할 수 있어야 했음.문제 이관 완료 기준을 '스크립트가 에러 없이 끝났다'가 아니라 '원천의 모든 행이 적재 또는 사유 있는 폐기로 설명된다'로 정의하고, 이를 실행마다 수치로 증명.성과 - 데이터가 '현재 상태' / '변경 이력' / '특정 시점 스냅샷' 중 무엇을 표현하는지에 따라 멱등 전략을 다르게 설계 — UPSERT(`xmax` 기반 삽입/갱신 판별), 전 컬럼 `IS DISTINCT FROM` 변경 감지, 스코프 한정 DELETE-before-INSERT로 몇 번을 재실행해도 동일한 결과 보장
- 이상 데이터를 '변환 불가로 폐기한 것'(12종 사유 분류)과 '적재했지만 값이 비정상적이라 후속 검토가 필요한 것'(anomaly)으로 분리 추적해, 실행 성공 여부와 데이터 품질 이슈를 별개 축으로 관리
- 원천 스캔 행수 ↔ 적재 건수 ↔ 사유별 폐기 건수가 완전히 맞아떨어지는 전수 회계 리포트를 실행마다 자동 산출해 모든 미적재 데이터가 '의도된 폐기'임을 증명
- 수백만 행 처리 중 V8 문자열 한도로 실패하던 로딩·로깅을 AsyncGenerator·NDJSON 스트리밍으로 재설계해 메모리 사용량을 입력 크기와 분리