반도체 팹(FAB)에서 오랫동안 데이터 및 데이터베이스 개발 업무를 하다 보면, 업계 외부에는 널리 알려지지 않았거나(혹은 아무도 공유하려고 하지 않는) 실용적인 통찰이 의외로 많다는 사실을 깨닫게 됩니다.
특히 오라클 기반 ETL을 사용하여 MES(제조 실행 시스템), 데이터 웨어하우스, 다양한 분석 시스템을 통합하는 경우, 정보를 찾아보려 해도 한국 내에는 포괄적인 글이 거의 없습니다.
솔루션 벤더의 문서는 구할 수 있지만, “현장에서 실제로 어떤 문제가 발생하고 어떻게 해결되었는지”를 다루는 글은 극히 드뭅니다.
이번 글에서는 FAB 현장에서 MES, MDW(데이터 마트/데이터 웨어하우스), RMS, MOS와 같은 시스템을 다루며 제가 실제로 겪었던 문제들과, 이를 오라클 ETL을 활용해 어떻게 해결했는지를 정리해 보겠습니다. 특정 솔루션과 회사명은 가능한 한 일반화하여 기술했지만, FAB 환경에서 데이터 파이프라인을 다뤄본 분이라면 “아, 나도 그런 경험 있어”라고 생각하게 될 순간이 꽤 많을 것이라고 믿습니다.
사실, 겉으로만 보면 이런 종류의 업무는 마치 단순히 “DB 개발자가 배치 스크립트를 작성하는 것”인 양 가볍게 여겨지곤 합니다. 하지만 세부 사항에 깊이 들어가 보면, 제조 현장의 물리적 제약 조건, 장비 간 통신 특성, 조직 간 협업 문제 등이 모두 복합적으로 작용하여 SQL 기술만으로는 해결할 수 없는 수많은 문제가 발생한다는 사실을 알게 될 것입니다. 이 글에서 다룬 사례들은 특정 기업이나 생산 라인에 국한된 것이 아니라, FAB 환경 자체에 내재된 공통적인 특성에서 비롯된 것이므로 다른 현장에서도 유용한 참고 자료가 될 것이라고 생각합니다.

MES와 데이터 웨어하우스 간의 통합 구조: 생각보다 훨씬 복잡하다
이 직책을 처음 맡았을 때, 저는 한 가지 큰 오해를 하고 있었습니다. “그냥 MES에서 데이터를 추출해서 데이터 웨어하우스에 로드하는 것뿐 아닌가?”라고 생각했죠. 하지만 현실은 전혀 달랐습니다.
FAB의 MES는 장비 운영 로그, 로트 이력, 측정 데이터, 경보 이벤트 등 다양한 유형의 데이터를 거의 실시간으로 끊임없이 생성합니다. 문제는 이 데이터가 단일하고 정돈된 테이블에서 나오는 것이 아니라, 장비 그룹과 공정 단계에 따라 스키마가 미묘하게 다른 여러 소스에서 유입된다는 점입니다. 게다가 MDW는 분석을 위해 데이터를 정규화된 형식으로 저장해야 하는 반면, RMS나 MOS와 같은 시스템은 각 시스템 고유의 특정 타이밍과 형식에 맞는 데이터를 필요로 합니다.
우리가 처음 직면한 문제는 “언제 데이터를 가져와야 하는가?”였습니다. FAB는 1년 365일 24시간 가동되기 때문에, 일반적인 배치 시스템에서 볼 수 있는 새벽 2시부터 4시까지의 유지보수 시간대와 같이 마음 편히 작업할 수 있는 시간대는 사실상 존재하지 않습니다. 장비는 계속 가동되고, 로트는 끊임없이 유입되며, MES 트랜잭션은 쉬지 않고 누적됩니다. 한편, 분석 팀은 “실시간 데이터는 필요 없지만, 5분 이내의 지연 시간으로 데이터를 확인하고 싶다”고 요청합니다.
이 문제를 해결하기 위해 당초에는 간단한 전체 로드 일괄 처리 방식을 채택했습니다. 이는 매시간 소스 테이블 전체를 스캔하여 데이터를 데이터 웨어하우스 스테이징 테이블로 전송하는 방식이었습니다. 데이터 양이 적을 때는 잘 작동했지만, 장비와 측정 항목의 수가 증가함에 따라 금세 한계에 도달했습니다. 매일 누적되는 행 수가 수천만 개에 달하면서 전체 스캔 작업 자체가 부담이 되었고, 배치 처리 시간도 점차 늘어 결국 한 배치 작업이 다음 배치와 겹치는 지경에 이르렀습니다.
결국, 우리는 인터페이스 테이블을 사용하는 구조로 전환했는데, 이 구조에서는 MES 측에서 변경된 내용만 전송합니다(변경 기반 CDC와 유사한 방식). 하지만 여기에도 함정이 있었습니다. MES 시스템 팀은 “운영에 필요한 이벤트만 기록한다”는 원칙을 고수했기 때문에, 분석 팀이 필요로 하는 타임스탬프나 상태 값이 인터페이스 테이블에 아예 없는 경우가 빈번했습니다. 이러한 경우, MES 팀과의 지속적인 논의를 통해 인터페이스 사양을 점진적으로 확장해야 했으나, 이 협상 과정 자체가 기술적 문제를 해결하는 데 걸린 시간보다 훨씬 더 오래 걸렸습니다.
오라클 ETL 설계 시 실제로 겪은 문제들 (주제: 이른 아침 배치 작업 실패)
기본 구조를 구축하고 나면, 오라클 측에서 발생하는 온갖 세부적인 문제들과 씨름하게 될 것입니다. 다음은 기억에 남는 몇 가지 사례입니다.
1) 이른 아침 배치 작업이 갑자기 중단되는 문제.
어느 날 이른 아침, 알람 소리에 잠에서 깼더니 MERGE 문을 사용하는 로드 배치 작업이 몇 시간 동안 데드락 상태에 빠져 있는 것을 발견했습니다. 원인을 조사해 보니, 동일한 대상 테이블 내의 서로 다른 장비 그룹을 처리하던 두 개의 병렬 세션이 파티션 경계를 넘나들며 동일한 인덱스 블록을 놓고 경쟁하고 있었던 것이었습니다. 이 문제는 정상적인 상황에서는 발생하지 않고, 특정 장비 그룹에 이벤트가 집중되는 특정 시간대(예: 야간 교대 직후 측정 데이터가 한꺼번에 쏟아져 들어올 때)에만 발생했기 때문에 재현하기가 상당히 어려웠습니다. 결국, 장비 그룹 대신 파티션 키를 기준으로 MERGE 범위를 재정의하고, 중복을 방지하기 위해 장비 그룹 해시 값을 기준으로 병렬 세션 간의 처리 순서를 정렬함으로써 문제를 해결했습니다.
2) 문자 집합 문제로 인한 장비 ID 손상.
특정 레거시 시스템에서 유입되는 데이터의 NLS_LANG 설정이 다른 시스템과 약간 달라, 로딩 과정에서 장비 ID의 특정 문자가 깨지는 현상이 발생했습니다. 문제는 이 현상이 일관되게 나타나지 않고 특정 문자 조합에서만 발생했다는 점입니다. 처음에는 데이터 자체가 손상된 것으로 추정하고 MES 측의 문제로 돌렸으나, 나중에 ETL 서버와 DB 세션 간의 문자 집합 설정 차이 때문임을 파악했습니다. 이러한 유형의 문제는 로그만으로는 감지할 수 없으며, 각 세션 매개변수를 하나씩 수동으로 덤프해야만 원인을 파악할 수 있어 디버깅에 상당히 오랜 시간이 소요되었습니다.
3) NULL 키로 인한 중복 MERGE 로드.
Oracle MERGE 문은 ON 절의 조인 키가 NULL인 경우 매칭에 실패하여 매번 INSERT 분기로 넘어가게 됩니다. 그러나 특정 장비의 특정 조건 하에서는 원본 키 열이 NULL로 전달되는 경우가 있었습니다. 저희는 이 점을 간과했고, 그 결과 배치 실행 시마다 동일한 이벤트가 계속 재로드되는 사고가 발생했습니다. 데이터 일관성 검사 중 비정상적으로 많은 행 수가 발견된 후에야 비로소 이 사실을 파악할 수 있었습니다. 그 이후로, 키 열에 NULL 값이 포함될 가능성이 있는 모든 소스에 대해서는 항상 NVL 처리를 적용하거나 대체 키를 생성하는 원칙을 채택하고, 이에 따라 방어적 로직을 반영하고 있습니다.
4) 비정상 이벤트(이탈) 발생 시 배치 작업이 타임아웃되는 문제.
장비에 이상 현상이 발생하거나 특정 측정값이 사양을 초과하는 경우(“이탈” 상황), 평소보다 몇 배나 많은 이벤트 및 경보 데이터가 단시간 내에 쏟아집니다. 정상 상태를 기준으로 설정된 배치 타임아웃 값은 이러한 피크 상황을 전혀 감당하지 못했고, 아이러니하게도 이상 현상이 발생한 바로 그 순간에 데이터가 분석 시스템에 도달하지 못하는 상황이 발생했습니다. 단순히 타임아웃 값을 늘리는 대신, 피크 데이터를 별도의 큐로 분리하여 우선적으로 처리함으로써 이 문제를 해결했습니다.
5) 파티션 프루닝이 갑자기 작동하지 않아 배치 처리가 느려진 문제.
한때 원활하게 실행되던 배치 작업이 갑자기 원래 속도의 몇 분의 일 수준으로 느려진 적이 있었습니다. 실행 계획을 확인해 보니, 조건이 분명히 파티션 키를 기반으로 하고 있음에도 불구하고 모든 파티션을 스캔하고 있는 것을 발견했습니다. 원인을 조사해 본 결과, ETL 로직 중간에 날짜 열을 비교하기 위해 TO_CHAR로 변환하는 부분이 있다는 것을 알게 되었습니다. 데이터 양이 증가함에 따라 최적화기가 통계를 재계산하면서 실행 계획이 변경되었고, 이로 인해 프루닝이 실패하게 되었습니다. 이는 WHERE 절에 암시적 형 변환이나 함수 호출이 포함되면 이와 같은 문제가 필연적으로 발생할 수 있다는 것을 깨닫게 해준 고통스러운 교훈이었습니다. 그 이후로 우리는 ‘파티션 키 조건에 함수나 형 변환을 절대 적용하지 않는다’는 규칙을 코드 검토 체크리스트에 확고히 반영했습니다.
고통스러운 경험을 통해 얻은 교훈 — 안정적인 FAB 데이터 파이프라인을 위한 체크리스트
이와 같은 사고를 몇 차례 겪은 후, 저희는 내부 팀 원칙을 몇 가지 수립했습니다. 비슷한 환경에서 일하는 분들에게 도움이 되기를 바라며, 여기에서 그 내용을 공유합니다.
배치는 항상 항등성을 갖도록 설계하십시오. 배치가 도중에 실패하여 재실행되더라도 동일한 결과를 산출해야 합니다. 처음부터 이를 원칙으로 정하지 않으면, 장애 복구 과정에서 “이 배치를 다시 실행해도 되는지” 결정하는 데만 모든 시간을 소비하게 될 것입니다. 우리는 모든 로드 배치에 대해 배치 실행 ID와 처리 범위(윈도우)를 명시적으로 기록하여, 동일한 윈도우가 다시 실행되더라도 중복 없이 재처리되도록 보장합니다.
기본값으로 워터마크 기반 증분 로딩을 사용하십시오. 단순한 시간 기반 증분 대신, 소스 시스템의 시퀀스 번호나 변경 이력 번호를 워터마크로 사용하여 늦게 도착한 데이터도 누락 없이 처리되도록 해야 합니다. FAB 환경에서는 장비 통신 지연으로 인해 이벤트가 몇 분, 심지어 몇 시간이나 늦게 도착할 수 있습니다. 시간 기반 증분에만 의존하면 데이터 손실이 발생합니다.
모니터링 및 알림은 단순히 “성공/실패”를 추적하는 것을 넘어, 로드량이 정상 범위 내에 있는지 여부도 확인해야 합니다. 배치 작업이 오류 없이 성공했다고 해서 데이터의 유효성이 보장되는 것은 아닙니다. 우리는 배치당 로드된 행 수의 평균과 표준 편차를 추적합니다. 특정 배치에서 정상 범위에 비해 비정상적으로 적은 수나 많은 수의 행이 로드되면 별도의 알림이 발동됩니다. 실제로 이러한 점검 덕분에 앞서 언급한 중복 NULL 키 로드 문제를 초기 단계에서 발견할 수 있었습니다.
MES 팀과 정기적인 소통 채널을 구축하십시오. 기술적인 관점에서 파이프라인을 아무리 견고하게 설계하더라도, MES 팀이 사전 통보 없이 스키마나 코드 값 체계를 변경하면 하룻밤 사이에 파이프라인이 무너질 수 있습니다. 저희는 MES 팀과 분기별 회의를 일정으로 잡아, 계획된 장비 확장이나 코드 시스템 변경에 대한 사전 통보를 받는 프로세스를 마련했습니다. 사소해 보일 수 있지만, 이는 실제로 상당한 수의 시스템 장애를 예방하는 데 가장 효과적인 방법임이 입증되었습니다.
변경 이력을 문서화하는 습관을 기르십시오. ETL 로직이 왜 그런 방식으로 구성되었는지, 어떤 문제가 발생했는지, 그리고 어떤 방어적 로직이 추가되었는지를 코드 주석과 별도의 문서에 모두 기록하는 것이 매우 중요합니다. 사람은 오고 가지만 시스템은 계속 운영되기 때문에, 이러한 기록은 다음 담당자가 같은 실수를 반복하지 않도록 하는 데 필수적입니다.
돌이켜보면, FAB 데이터 파이프라인의 어려움은 종종 기술 자체에서 비롯된 것이 아니라 “연중무휴 24시간 가동되는 생산 현장”이라는 제약에서 비롯되었습니다. 일반적인 IT 서비스에서는 예정된 유지보수 시간 동안 충분한 시간을 들여 처리할 수 있는 문제들도, FAB 환경에서는 데이터 손실 없이 실시간으로 처리되어야 합니다. 이 글이 유사한 환경에서 Oracle ETL과 MES 통합을 고려 중인 분들에게 유용한 참고 자료가 되기를 바랍니다. 다음 글에서는 여기서 언급한 워터마크 기반 증분 로딩을 실제 PL/SQL 코드를 사용하여 어떻게 구현했는지 더 자세히 설명하겠습니다.