본문 바로가기
카테고리 없음

반도체 FAB 데이터 실무자가 겪은 오라클 ETL과 MES 연동 삽질기

by catfamily 2026. 9. 4.

반도체 FAB에서 데이터/DB 개발 업무를 오래 하다 보면, 밖에서는 잘 안 알려주는(혹은 굳이 알려줄 사람이 없는) 실무 이야기가 은근히 많습니다.

특히 MES(제조실행시스템)와 데이터웨어하우스, 그리고 각종 분석 시스템을 오라클 기반 ETL로 엮는 작업은 자료를 찾으려 해도 국내에 정리된 글이 거의 없습니다.

관련 솔루션 벤더 문서는 있어도 "현장에서 실제로 어떤 문제가 터지고 어떻게 풀었는지"를 다루는 글은 손에 꼽습니다.

이 글에서는 제가 FAB 현장에서 MES, MDW(데이터마트/데이터웨어하우스), RMS, MOS 같은 시스템 사이를 오가며 겪었던 실제 문제들과, 그걸 오라클 ETL로 어떻게 풀어냈는지를 정리해보려고 합니다. 특정 솔루션이나 회사 이름은 최대한 일반화해서 썼지만, FAB 환경에서 데이터 파이프라인을 다뤄본 분이라면 "아 이거 나도 겪었는데" 싶은 대목이 꽤 있을 거라고 생각합니다.

사실 이런 업무는 겉으로 보면 그냥 "DB 개발자가 배치 짜는 일" 정도로 가볍게 취급되기 쉽습니다. 하지만 실제로 들어가 보면 제조 현장의 물리적 제약, 설비 통신 특성, 조직 간 협업 이슈까지 얽혀 있어서 순수 SQL 실력만으로는 절대 풀리지 않는 문제들이 훨씬 많았습니다. 이 글에서 다루는 사례들은 특정 회사나 라인에 한정된 이야기가 아니라, FAB이라는 환경 자체가 가진 공통적인 특성에서 비롯된 문제들이라 다른 현장에서도 충분히 참고가 될 거라고 생각합니다.

반도체 FAB 데이터 실무자가 겪은 오라클 ETL과 MES 연동

 


MES와 데이터웨어하우스 사이, 생각보다 복잡한 연동 구조

처음 이 업무를 맡았을 때 가장 크게 오해했던 부분이 있습니다. "MES에서 데이터를 뽑아서 데이터웨어하우스에 적재하면 끝 아닌가?" 라는 생각이었는데, 실제로는 전혀 그렇지 않았습니다.

FAB의 MES는 설비 가동 로그, 랏(LOT) 이력, 계측 데이터, 알람 이벤트 등 다양한 종류의 데이터를 실시간에 가깝게 쏟아냅니다. 문제는 이 데이터가 하나의 깔끔한 테이블에서 나오는 게 아니라, 설비군별로, 공정 단계별로 스키마가 미묘하게 다른 여러 소스에서 흘러나온다는 점입니다. 여기에 MDW는 분석을 위해 정규화된 형태로 데이터를 쌓아야 하고, RMS나 MOS 같은 시스템은 또 자기들만의 타이밍과 포맷으로 데이터를 요구합니다.

가장 먼저 부딪힌 문제는 "언제 데이터를 가져올 것인가"였습니다. FAB은 24시간 365일 돌아가기 때문에 일반적인 배치 시스템처럼 새벽 2시부터 4시까지 점검 시간이라며 마음 편히 작업할 수 있는 창이 사실상 없습니다. 설비는 계속 돌고, 랏은 계속 흐르고, MES 트랜잭션은 끊임없이 쌓입니다. 그런데 분석 시스템 쪽에서는 "실시간까지는 필요 없지만 최소 5분 이내 지연으로 데이터를 보고 싶다"는 요구가 들어옵니다.

이걸 해결하려고 초반에 시도했던 방식은 단순 풀(Full) 적재 배치였습니다. 매 시간마다 원본 테이블 전체를 훑어서 데이터웨어하우스 스테이징 테이블에 밀어넣는 방식이었는데, 데이터량이 적을 때는 문제가 없었지만 설비가 늘어나고 계측 항목이 늘어나면서 이 방식은 금방 한계에 부딪혔습니다. 하루에 쌓이는 로우 수가 수천만 건 단위로 늘어나니, 풀 스캔 자체가 부하였고, 배치 시간이 점점 늘어나서 다음 배치와 겹치는 상황까지 벌어졌습니다.

결국 인터페이스 테이블을 두고, MES 쪽에서 변경분만 밀어주는 구조(변경 이력 기반 CDC와 유사한 방식)로 전환했습니다. 다만 여기서도 함정이 있었는데, MES 시스템 담당팀 입장에서는 "우리는 우리 업무에 필요한 만큼만 이벤트를 기록한다"는 원칙이 있어서, 분석 쪽에서 필요로 하는 타임스탬프나 상태값이 인터페이스 테이블에 아예 없는 경우가 종종 있었습니다. 이런 경우엔 MES 담당자와 계속 협의하면서 인터페이스 스펙을 조금씩 넓혀가야 했는데, 이 협의 과정 자체가 기술적인 문제보다 훨씬 오래 걸리는 작업이었습니다.

오라클 ETL 설계에서 만난 진짜 문제들 (feat. 새벽 배치 장애)

구조를 어느 정도 잡고 나면 그다음부터는 오라클 단에서 온갖 디테일한 문제들과 씨름하게 됩니다. 몇 가지 기억에 남는 사례를 공유해봅니다.

1) 새벽 배치가 갑자기 멈추는 문제.

어느 날 새벽에 알람을 받고 일어나서 확인해보니, MERGE 문을 활용한 적재 배치가 데드락에 걸려서 몇 시간째 멈춰 있었습니다. 원인을 추적해보니, 같은 대상 테이블에 대해 서로 다른 설비군을 처리하는 병렬 세션 두 개가 파티션 경계를 넘나들며 같은 인덱스 블록을 두고 경합하고 있었습니다. 평소엔 문제가 없다가 특정 설비군에서 이벤트가 몰리는 시간대(예: 야간 교대 직후 계측 데이터가 한꺼번에 쏟아지는 타이밍)에만 터지는 문제라서 재현하는 데도 꽤 애를 먹었습니다. 결국 MERGE 대상 범위를 설비군 단위가 아니라 파티션 키 단위로 다시 쪼개고, 병렬 세션 간 처리 순서를 설비군 해시값 기준으로 정렬해서 겹치지 않게 만드는 방식으로 해결했습니다.

2) 캐릭터셋 문제로 설비 ID가 깨지는 문제.

특정 legacy 설비에서 넘어오는 데이터의 NLS_LANG 설정이 다른 시스템들과 미묘하게 달라서, 설비 ID에 포함된 특정 기호가 적재 과정에서 깨지는 문제가 있었습니다. 문제는 이게 항상 깨지는 게 아니라 특정 코드 조합에서만 깨져서, 처음엔 데이터 자체가 이상한 줄 알고 MES 쪽에 원인을 돌렸다가, 나중에서야 ETL 서버와 DB 세션의 캐릭터셋 설정 차이라는 걸 알게 됐습니다. 이런 문제는 로그만 봐서는 절대 안 잡히고, 실제로 세션 파라미터를 하나하나 덤프해봐야 원인이 보이는 경우라 디버깅 시간이 꽤 오래 걸렸습니다.

3) NULL 키 때문에 MERGE가 중복 적재되는 문제.

오라클 MERGE 문은 ON 절의 조인 키가 NULL이면 매칭이 실패해서 매번 INSERT 분기로 빠지는데, 특정 설비의 특정 상태에서는 원래 키 컬럼이 NULL로 넘어오는 케이스가 있었습니다. 이걸 놓쳐서 같은 이벤트가 배치를 돌 때마다 계속 새로 쌓이는 사고가 있었고, 데이터 정합성 체크를 하다가 로우 수가 이상하게 많다는 걸 발견하고서야 알아챘습니다. 이후로는 키 컬럼에 NULL이 들어올 수 있는 소스는 반드시 NVL 처리나 대체키를 만들어서 방어 로직을 넣는 걸 원칙으로 삼게 됐습니다.

4) 이상 이벤트(엑스커전) 발생 시 배치가 타임아웃 나는 문제.

설비에 이상이 생기거나 특정 계측값이 스펙을 벗어나는 엑스커전 상황이 발생하면, 평소보다 몇 배 많은 이벤트와 알람 데이터가 짧은 시간에 몰려서 들어옵니다. 평상시 기준으로 잡아둔 배치 타임아웃 값이 이런 피크 상황을 전혀 감당하지 못해서, 정작 이상 상황이 터졌을 때 분석 시스템에 데이터가 안 들어오는 아이러니한 상황이 벌어졌습니다. 이 문제는 타임아웃 값을 무작정 늘리는 대신, 피크 구간을 별도 큐로 분리해서 우선순위 처리하는 방식으로 개선했습니다.

5) 파티션 프루닝이 갑자기 안 먹혀서 배치가 느려지는 문제.

잘 돌던 배치가 어느 날부터 갑자기 몇 배씩 느려진 적이 있었습니다. 실행계획을 뽑아보니 분명히 파티션 키로 조건을 걸었는데도 전체 파티션을 다 스캔하고 있었습니다. 원인을 파보니, ETL 로직 중간에 날짜 컬럼을 TO_CHAR로 변환해서 비교하는 부분이 있었는데, 데이터량이 늘면서 옵티마이저가 통계 정보를 다시 계산하는 시점에 실행계획이 바뀌면서 프루닝이 깨진 것이었습니다. 암묵적 형변환이나 함수 처리가 조건절에 들어가면 언젠가 이런 식으로 터질 수 있다는 걸 뼈저리게 배운 사례였습니다. 이후로는 파티션 키 조건에는 절대 함수나 형변환을 걸지 않는다는 규칙을 코드 리뷰 체크리스트에 아예 박아넣었습니다.

삽질 끝에 얻은 노하우 — 안정적인 FAB 데이터 파이프라인을 위한 체크리스트
이런 사고들을 몇 번 겪고 나서 팀 내부적으로 정리한 원칙들이 있습니다. 비슷한 환경에서 일하시는 분들께 도움이 될 것 같아 정리해봅니다.

배치는 반드시 멱등성(idempotent)을 갖도록 설계한다. 배치가 중간에 실패해서 재실행되더라도 같은 결과가 나와야 합니다. 이걸 처음부터 원칙으로 잡지 않으면, 장애 복구 시점에 "이 배치를 다시 돌려도 되는지" 판단하는 데만 시간을 다 쓰게 됩니다. 저희는 모든 적재 배치에 배치 실행 ID와 처리 범위(윈도우)를 명시적으로 기록해서, 같은 윈도우를 다시 돌려도 중복 없이 재처리되도록 만들었습니다.

워터마크 기반 증분 적재를 기본값으로 삼는다. 단순 시간 기준 증분이 아니라, 소스 시스템의 시퀀스나 변경 이력 번호를 워터마크로 삼아야 늦게 들어오는 데이터(Late Arriving Data)도 놓치지 않고 처리할 수 있습니다. FAB 환경에서는 설비 통신 지연으로 인해 이벤트가 몇 분, 심하면 몇 시간 늦게 도착하는 경우도 있어서, 시간 기준만 믿으면 데이터 누락이 생깁니다.

모니터링과 알림은 "성공/실패"가 아니라 "적재량 이상 여부"까지 봐야 한다. 배치가 에러 없이 성공했다고 해서 데이터가 정상이라는 보장은 없습니다. 저희는 배치별로 평소 적재 로우 수의 평균과 표준편차를 관리해서, 특정 배치가 평소보다 지나치게 적거나 많은 로우를 적재하면 별도로 알림이 오도록 만들었습니다. 실제로 이 체크 덕분에 위에서 언급한 NULL 키 중복 적재 문제를 조기에 발견할 수 있었습니다.

MES 담당팀과의 커뮤니케이션 채널을 정례화한다. 기술적으로 아무리 견고하게 파이프라인을 짜도, MES 쪽에서 스키마나 코드값 체계를 예고 없이 바꾸면 하루아침에 무너집니다. 저희는 분기별로 MES 담당팀과 정기 미팅을 잡아서, 예정된 설비 증설이나 코드 체계 변경 사항을 미리 공유받는 프로세스를 만들었습니다. 이게 별거 아닌 것 같아도 실제 장애의 상당수를 예방하는 데 가장 효과적이었습니다.

변경 이력을 남기는 문서화 습관을 들인다. ETL 로직이 왜 이렇게 짜여 있는지, 어떤 사고를 겪고 어떤 방어 로직이 추가됐는지를 코드 주석과 별도 문서에 함께 남겨두는 게 중요합니다. 사람은 바뀌지만 시스템은 계속 운영되기 때문에, 다음 담당자가 같은 삽질을 반복하지 않으려면 이런 기록이 꼭 필요합니다.

돌아보면 결국 FAB 데이터 파이프라인의 어려움은 기술 자체보다 "24시간 멈추지 않는 현장"이라는 제약 조건에서 나오는 경우가 많았습니다. 일반적인 IT 서비스라면 점검 시간을 잡고 여유 있게 처리할 수 있는 문제도, FAB에서는 실시간으로, 그것도 데이터 유실 없이 처리해야 한다는 전제가 붙습니다. 이 글이 비슷한 환경에서 오라클 ETL과 MES 연동을 고민하시는 분들께 조금이나마 참고가 되었으면 합니다. 다음 글에서는 이번에 언급한 워터마크 기반 증분 적재를 실제 PL/SQL 코드로 어떻게 구현했는지 좀 더 구체적으로 다뤄보겠습니다.