공연장 필드에 FRI가 들어 있었다. K-POP PULSE의 10월 1일 기록에서 자동으로 만든 일정은 TOUR였고, 제목은 공연 영상 제목에서 왔으며 날짜는 신곡 공지와 연결됐다. 금요일을 뜻하는 표기가 장소가 되어 그럴듯한 일정 한 줄을 만들었다.

나는 이 경우를 단어 하나를 잘못 읽은 실수로만 보지 않는다. 서로 다른 문맥에서 제목과 날짜를 가져온 뒤 같은 행에 넣으면 모든 값이 채워져도 틀린 정보가 된다. 잘못 만든 행을 내리고 올바른 유형으로 다시 등록한 결과까지 따라가며 무엇을 확인했는지 남긴다.

값이 채워졌다는 사실은 관계가 맞다는 뜻이 아니다

당시 DB 읽기 출력에는 일정63번의 공연장 FRI, 유형 TOUR와 공연 영상 제목이 남아 있다. 설명은 시작 시간이 공지되지 않았다고 적었다. 공식 자료에서 가져온 낱말이라도 다른 필드에 들어가면 독자가 읽는 정보는 달라진다.

날짜 뒤의 요일과 장소, 영상 제목과 앞으로 열릴 행사 제목은 구별해야 했다. 날짜 형식이 맞는 검사만으로는 이 관계 오류를 잡을 수 없다. 나는 자동 추출 결과에서 어느 문단이 어떤 필드를 뒷받침하는지 확인하고 관계가 불분명하면 등록을 보류하는 쪽으로 기준을 가져가려 한다.

처음 정정 시도가 실패한 이유도 남긴다

첫 복구 시도에는 필요한 라이브러리를 찾지 못한 오류가 남아 있고 공개 피드도 아직 이전 값이었다. 프로젝트의 가상환경 대신 다른 Python으로 DB 확인을 시도한 것이 원인이었다. 정정 작업을 시작했다는 사실만으로 수정이 끝난 상태를 보고할 수 없었다.

후속 기록은 맞는 실행 환경에서 이전 행을 철회하고 올바른 SINGLE 일정64번을 등록한 응답을 보여 준다. 나는 실패한 실행과 실제 저장 응답을 구별한다. 다른 홈페이지에서도 사용하는 실행기와 환경을 먼저 확인하고 수정 후 저장된 필드를 읽어야 같은 실수를 반복하지 않는다.

피드에 남아 있다는 것만 보고 실패라고 판단하지 않는다

정정 뒤의 첫 피드 읽기에는 이전 일정이 여전히 나타났다. 이어서 상태 필드를 직접 읽은 결과는 WITHDRAWN이었다. 당시 공연 목록 페이지에서 이전 제목은 나오지 않았고, ICS에는 그 행의 취소 상태가 전달됐다. 데이터의 존재와 현재 공개 목록의 유효한 항목은 다른 질문이었다.

오늘 다시 읽은 이벤트 JSON과 ICS에서도 해당 행의 철회 상태와 캘린더 상태를 대조했다. 이는 현재 피드의 읽기 결과이며 공연 목록의 현재 화면까지 새로 검수했다는 뜻은 아니다. 구독자에게 변경을 전달하려고 이전 행을 남기는 구조에서는 개수나 문자열 존재만으로 정정 성공을 판정하면 오해할 수 있다.

내 데이터의 철회와 실제 공연의 취소를 구별한다

이번 행은 잘못 추출한 일정이다. 아티스트가 실제 행사를 취소한 공식 발표로 이야기하면 안 된다. 당시 ICS의 CANCELLED는 이 데이터 행의 상태를 내보낸 결과다. 피드와 글에서 독자가 왜 항목이 내려갔는지 이해할 설명을 별도로 제공할 필요가 있다.

중복을 내려야 하는 경우도 같은 문제가 생긴다. 멀쩡한 실제 행사의 중복 행을 철회로 보내면 캘린더에서는 행사 취소처럼 읽힐 수 있다. 정정 이유와 상태의 의미를 먼저 정하고 각 출력이 무엇을 전달하는지 확인해야 한다. 화면에서만 숨겼다고 모든 구독 경로가 같은 뜻을 받는 것은 아니다.

새 조건은 실패한 입력과 함께 검사한다

이 사례를 다른 프로그램에 적용한다면 요일 토큰이 장소 후보로 들어갔을 때 검토하도록 하고, 제목·날짜·행사 유형의 근거 구간을 함께 본다. 낱말 하나를 금지하는 것으로 모든 자동 추출 오류를 막았다고 말하지 않는다. 실제 장소명이나 다른 언어의 표기는 별도의 확인이 필요하다.

아래는 수정 작업의 순서를 남기는 새 설명용 장부다. 원본 관리 API나 이미 구현된 새 감지기는 아니다. 잘못된 행의 이유와 대체 행, 저장과 공개 출력에서 비교할 항목을 묶는다. 실패 입력을 검사 자료로 보존하면 다음 규칙을 추가할 때 이전 오류가 다시 생기는지 확인할 수 있다.

코드와 구현 살펴보기

새 설명용 정정 장부. 실제 API 호출이나 공연 취소 공지가 아니다.

{
  "old_record": {"status": "withdrawn", "reason": "incorrect extraction"},
  "replacement_record": {"type": "release", "date": "source-supported day"},
  "verify": ["saved fields", "public feed status", "active page", "calendar mapping"]
}
// New explanatory review record; not an original API payload or real cancellation.

성공 응답 다음에 독자에게 전달된 상태를 읽는다

이번 복구를 설명할 때 필요한 결과는 등록 성공 한 줄보다 많았다. 이전 행의 상태, 새 행의 유형, 공개 목록과 JSON, 캘린더가 각자 전달하는 의미를 읽어야 했다. 홈페이지는 여러 경로에서 같은 자료를 사용하므로 한 화면의 해결이 전체 전달의 해결과 같지 않았다.

나는 이 정정 경험을 완벽한 감지기를 만들었다는 성과로 남기지 않는다. 확인한 입력에서 오류를 발견하고 실패한 환경을 바로잡아 정정했으며 출력별 상태를 비교한 기록이다. 자동화를 더할 때도 잘못된 정보를 어떻게 회수하고 왜 바뀌었는지 설명할지가 함께 필요했다.