같은 일정이 두 행으로 들어오면 하나만 숨기면 될 것 같았다. 그런데 철회 상태를 사용하는 출력은 구독 달력에 CANCELLED를 전달했다. K-POP PULSE의 최적화 기록은 이 방식으로 중복을 내리면 정상 일정까지 취소처럼 읽힐 수 있다는 부채를 남겼다.

나는 중복을 없애는 일이 실제 행사를 취소하는 결정과 다르다는 점부터 풀고 싶다. 8월의 미해결 기록 다음에는 별도 중복 처리 코드와 검사, 첫 실행의 일부 실패, 후속 정리 결과가 있다. 그 순서를 나누어 읽어야 과거의 보류와 이후의 구현을 같은 현재 상태로 설명하지 않는다.

내리는 이유를 상태의 뜻과 연결한다

중복 행은 실제 사건이 하나인데 데이터가 둘인 경우다. 취소는 실제 사건의 상태가 바뀌었다는 다른 정보다. 화면에서 둘 다 안 보인다고 같은 저장 상태를 사용하면 구독 경로에서 독자가 읽는 의미가 달라진다.

당시 기록의 대응은 중복 상태를 별도로 두고 피드에서 그 중복 행을 제외하는 방식이었다. 철회 상태가 캘린더의 취소 값으로 나가는 규칙과 구별했다. 나는 이 설계를 모든 달력 앱의 기존 항목까지 자동으로 제거한 결과로 소개하지 않는다. 이미 가져간 데이터를 소비자가 어떻게 처리하는지는 따로 확인해야 한다.

유일한 행을 숨기지 않도록 살아 있는 짝을 확인했다

8월 8일 수정 코드는 같은 대상과 시작 시각, 유형을 가진 다른 유효한 행이 있어야 중복 처리하도록 했다. 그런 짝이 없으면 거부하고 남겨 둔 행의 식별자를 결과에 돌려준다. 같은 제목을 찾았다는 이유만으로 유일한 일정을 내리지 않으려는 조건이다.

그 키가 모든 이벤트의 동일성을 완벽하게 판정하는 것은 아니다. 같은 날의 여러 행사나 유형이 잘못 들어간 행은 추가 검토가 필요하다. 운영 안내도 필요한 필드를 먼저 정정해야 할 경우를 남겼다. 나는 자동 비교의 기준과 실제 같은 사건인지 판단한 이유를 함께 기록하려 한다.

항상 통과하는 단언을 실제 비교로 바꾸었다

첫 회귀 검사에는 or True가 붙은 단언이 있었다. 앞의 비교가 틀려도 전체 조건이 참이 되므로, 취소 상태가 늘지 않았다는 사실을 그 검사로 확인할 수 없었다. 후속 작업은 캘린더의 취소 값 개수를 정리 전후로 비교하고 피드의 집합과 캘린더 항목 수를 대조하도록 고쳤다.

그 뒤 당시 검사 묶음 128개가 통과한 출력이 남아 있다. 나는 최초의 녹색 결과를 그대로 신뢰했다고 쓰지 않는다. 이름이 중복 검사여도 실제 어떤 실패를 잡는지 읽어야 했다. 이 기록은 현재 원본 서비스의 모든 중복과 모든 소비자 동작을 검증한 숫자는 아니다.

첫 운영 실행은 세 항목이 모두 끝난 상태가 아니었다

첫 정리 출력에서는 한 항목이 일반 확인 상태를 돌려주고, 다른 항목은 서버 오류로 끝났으며, 나머지 한 항목만 중복 상태였다. 요청을 보냈다는 사실과 내가 기대한 상태가 저장됐다는 결과가 달랐다. 중간 결과를 지우면 이 작업을 한 번에 해결한 것으로 오해할 수 있다.

후속 실행은 남은 두 항목의 중복 상태와 남겨 둔 식별자를 반환했다. 그 회차의 공개 피드는 정의한 비교 키에서 중복이 없음을 확인했다. 9월 기록에도 다른 중복과 정본을 읽은 결과가 있다. 해당 회차와 키의 확인을 현재 전건 검수나 등록 자체의 중복 예방 기능으로 넓히지 않는다.

정리 의도와 확인할 출력을 작은 장부에 남긴다

아래는 이번 경험을 다른 홈페이지에 가져가기 위한 새 설명용 장부다. 원본 API를 호출하는 입력이나 실제 행사 취소 공지가 아니다. 무엇을 정리하려는지, 남겨 둘 행이 있는지, 독자에게 어떤 상태를 전달할지 분리해 놓는 방식이다.

다른 사이트라면 관리자 화면에서 중복 정리와 실제 취소에 다른 이유를 받도록 정할 수 있다. 저장 상태를 읽고 공개 피드의 식별자와 캘린더 상태를 비교한다. 보기에서 한 줄이 사라졌다는 결과만으로 완료하지 않는다. 기존 구독을 유지한 실제 소비자의 변화도 필요한 범위에서 확인한다.

코드와 구현 살펴보기

새 설명용 중복 정리 장부. 실제 관리 API나 취소 발표가 아니다.

{
  "intent": "remove a duplicate data row",
  "surviving_record": "inspect an active equivalent record",
  "candidate_state": "duplicate",
  "real_event_cancelled": "not established by this operation",
  "verify": ["saved status", "feed identifiers", "calendar cancellation count"]
}
// New explanatory review ledger; not an original API payload.

깨끗한 목록과 믿을 수 있는 변경은 함께 필요했다

중복을 줄이면 화면은 간결해질 수 있다. 하지만 독자가 그 변화를 실제 행사 취소로 읽으면 정리의 목적을 잃는다. 홈페이지의 관리 기능은 버튼을 누른 사람뿐 아니라 그 데이터를 받아 보는 사람의 언어까지 생각해야 했다.

나는 잘못된 행을 처리할 전용 통로와 실패 결과, 남겨 둔 정본을 함께 공개하려 한다. 같은 작업을 이어가는 제작자가 왜 삭제나 철회 한 가지로 모든 문제를 처리하지 않았는지 알 수 있게 한다. 상태의 의미를 남기는 것이 목록을 정돈하는 일의 일부였다.