최종 프로젝트 시작했다.
반도체 도메인인데 갑자기 뭔 제조 데이터가,,
반도체 테스트 소켓 제조 데이터가 반도체 데이터는 아니잖소
암튼 오늘 한 거 지피티가 정리해줬다.
TIL — IPQC/AOI 데이터 시간축 정렬과 SN 기반 사출 후보 묶음 검증
오늘 한 일
오늘은 월별 IPQC/AOI 원본 데이터를 바로 모델링하지 않고, 먼저 시간축과 사출 후보 단위가 분석에 사용할 수 있는 구조인지 확인했다.
초기 데이터 감사에서는 2025년 7월부터 2026년 2월까지 총 8개 CSV, 237,039행을 대상으로 파일 구조, 결측, 중복, 이상값, 누수 위험 컬럼을 점검했다. 이 과정에서 2026년 1월과 2월의 FAIL 비율이 높아지는 현상은 확인했지만, 공정 문제라고 단정하지 않고 검사 기준, 데이터 수집 방식, 설비·품번 구성 변화 가능성을 남겨두었다.
이후 Injection_Time을 기준으로 전체 데이터를 정렬해 시간 흐름을 확인했다. Injection_Time은 전체 행에서 100% 파싱됐고, source_month와 실제 calendar month의 불일치도 없었다. 다만 동일한 타임스탬프에 여러 행이 몰려 있는 구조가 매우 강했다. 중복 타임스탬프가 62,406개였고, 전체 행의 대부분이 동일 시각 중복에 포함됐다. 이 결과만 보면 행 단위 시간 정렬만으로는 실제 사출 단위를 안정적으로 구분하기 어렵다고 판단했다.
그래서 SN 구조를 이용해 사출 후보 묶음을 만들었다. SN에서 prefix, serial, 설비·품번 토큰, cavity 번호를 파싱했고, sn_serial - sn_cavity를 이용해 sn_batch_key를 만들었다. 이를 바탕으로 shot_candidate_id를 정의했다. 이 방식으로 전체 237,039행이 모두 SN 파싱에 성공했고, 58,119개의 사출 후보 묶음이 생성됐다.
처음 만든 v1 정렬에서는 Injection_Time_parsed를 첫 번째 정렬 기준으로 사용했다. 그런데 동일한 shot_candidate_id 안의 4개 cavity가 서로 다른 timestamp를 가지면, 같은 묶음의 행들이 전체 데이터 중간중간에 흩어지는 문제가 생겼다. 처음 검증 로직은 이 문제를 제대로 잡지 못했다. cavity 순서 검증이 동일 timestamp 안에서만 이뤄졌고, 그룹 연속성 검증도 실제 계산이 아니라 통과 처리에 가까웠기 때문이다.
이를 수정하기 위해 v2에서는 각 shot_candidate_id별 최소 Injection_Time을 group_anchor_time으로 계산하고, 이 값을 첫 번째 정렬 기준으로 사용했다. 그 결과 v1에서 발생했던 비연속 그룹 6,482개와 cavity 순서 위반 34,197행이 모두 0건으로 줄었다. 행 수 237,039행도 그대로 유지됐고, raw 파일과 v1 출력 파일도 덮어쓰지 않았다.
오늘 배운 점
데이터를 시간순으로 정렬한다고 해서 항상 분석 가능한 순서가 되는 것은 아니었다. 특히 이번 데이터처럼 한 시각에 여러 검사 행이 몰려 있고, 한 번의 사출 후보가 여러 cavity 행으로 나뉘어 있는 경우에는 행 단위 timestamp보다 그룹 단위 기준이 더 중요했다.
처음에는 Injection_Time을 기준으로 정렬하면 자연스럽게 생산 흐름이 보일 것이라고 생각했다. 하지만 실제로는 동일 시각 중복이 많았고, 한 후보 묶음 안에서도 timestamp가 조금씩 달라지는 경우가 많았다. 이 때문에 단순 시간 정렬은 전체 흐름을 보는 데는 유효하지만, 사출 단위 분석이나 cavity 순서 분석에는 충분하지 않았다.
또 하나 배운 점은 검증 로직 자체도 검증해야 한다는 것이다. v1에서는 정렬 검증 결과가 통과로 나왔지만, 실제로는 같은 후보 묶음의 행들이 연속되지 않는 문제가 있었다. 겉으로는 검증을 통과했지만, 검증 조건이 문제를 제대로 잡지 못하면 잘못된 결과를 정상으로 받아들일 수 있다. 이번에 v2에서 비연속 그룹, cavity 순서 위반, 행 동일성, raw 파일 보존 여부까지 다시 확인한 이유도 이 때문이다.
오늘의 판단
v1 출력 파일은 후속 분석에 사용하지 않는 것이 맞다. v1은 행 수는 보존했지만, 같은 shot_candidate_id의 행들이 흩어질 수 있는 구조였기 때문에 그룹 단위 분석에는 부적합하다.
반면 v2는 group_anchor_time을 사용해 그룹 연속성과 cavity 순서를 확보했다. 다만 v2도 완전히 확정된 실제 사출 단위라고 보기는 어렵다. shot_candidate_id는 SN 규칙으로 만든 후보 묶음일 뿐이고, 실제 설비 로그나 공정 기록과 교차 확인된 것은 아니다. 따라서 현재 단계에서는 “실제 1회 사출”이 아니라 “SN 구조 기반 사출 후보 묶음”으로 표현하는 것이 맞다.
또한 v2는 그룹 연속성을 확보하는 대신 행 단위 Injection_Time의 전역 단조성을 포기한다. 실제로 행 단위 시간 역행이 40,746건 보고됐다. 하지만 이것은 v2 정렬 설계의 예상 결과이며, 실패 조건은 아니다. 이번 분석에서는 행 하나하나의 시간순보다 같은 후보 묶음을 연속된 단위로 유지하는 것이 더 중요했다.
남은 문제
아직 해결하지 못한 부분도 많다.
첫째, shot_candidate_id가 실제 1회 사출을 의미하는지는 확인하지 못했다. 지금은 SN 구조를 이용해 만든 후보일 뿐이다.
둘째, duplicate_sn 그룹이 1,938개 존재한다. 이 중복이 재검사인지, 재투입인지, 데이터 중복인지 알 수 없다. 중복을 제거할지 유지할지 결정하려면 더 확인이 필요하다.
셋째, incomplete 그룹이 1,645개 있다. 일부 cavity가 누락된 이유가 실제 미검사인지, 불량으로 인한 제외인지, 데이터 수집 누락인지 확인되지 않았다.
넷째, rule_mismatch 행이 152개 존재한다. SN 연번 규칙의 예외인지, 데이터 오류인지, 특정 작업 조건에서 발생한 정상 케이스인지는 아직 확인되지 않았다.
다음에 할 일
다음 단계에서는 v2 정렬 결과를 기준으로 분석을 이어갈지 먼저 결정해야 한다. 내 판단으로는 v1은 사용하지 않고, v2를 기준 데이터로 삼는 방향이 타당하다. 다만 duplicate_sn, incomplete, rule_mismatch 그룹은 별도 플래그를 유지한 채 분석해야 한다.
바로 모델링으로 넘어가기보다는 먼저 그룹 단위 요약 테이블을 만드는 것이 좋다. complete_4 그룹을 중심으로 4개 cavity의 사출 조건, AOI 결과, PASS/FAIL 분포를 한 묶음으로 압축해볼 수 있다. 이때 duplicate_sn과 rule_mismatch는 섞지 않고 따로 분리해야 한다.
오늘 작업의 결론은 단순히 데이터를 정렬한 것이 아니라, “이 데이터에서 무엇을 한 단위로 볼 것인가”를 정하는 과정이었다. 처음에는 행 단위 시간 흐름을 보려고 했지만, 실제 분석에는 SN 기반 후보 묶음이 더 적절하다는 방향으로 정리됐다.