수집 목록에서 같은 제목을 발견하면 중복을 지우고 싶어진다. 코드를 다시 읽으며, 제목을 정리하는 편리한 규칙이 글의 동일성을 어디까지 설명할 수 있는지 살펴봤다. 모르는 관계는 검토 후보로 남기는 예제도 직접 만들었다.
목록의 한 줄이 실제로는 무엇을 뜻할까
같은 제목의 글 두 개가 목록에 보이면 중복을 지우고 싶어진다. 운영자에게는 깔끔한 목록이 편하고 개발자에게는 자료를 덜 처리하는 이점이 있다. 하지만 한 줄을 없애는 순간 글 하나를 잃거나 서로 다른 관측을 같은 사실로 만들 수도 있다. 자료를 수집하는 홈페이지라면 이 기준을 화면의 편의보다 먼저 정해야 한다.
이번에 다시 읽은 작업 기록은 지정한 글만 받아 달라는 요청이었다. 그 대화에는 제목 충돌 때문에 실제 글을 잃었다는 사건이 없다. 나는 수집 코드의 식별·병합 함수를 읽으며 어떤 조건에서는 구분을 지키고, 어떤 예외에서는 제목에 기대는지 살펴봤다. 과거 손실을 발견한 이야기로 꾸미는 대신 현재 코드에서 확인한 선택과 그로부터 만든 새 예제를 설명하려 한다.
정상 경로는 게시자와 글 번호를 먼저 보았다
원래 코드에는 주소에서 게시자 ID와 글 번호를 꺼내는 함수가 있다. 확인한 웹·모바일 검색 후보 파서는 이 식별자를 얻지 못한 항목을 건너뛴다. 병합 함수도 두 값이 있으면 게시자 ID를 소문자로 정리한 값과 글 번호를 키로 쓴다. 같은 제목이지만 글 번호가 다른 정상 후보를 제목만으로 합치지 않는 구조다.
반대로 같은 식별자로 연결된 두 후보는 웹 위치와 모바일 위치, 각각의 제목과 출처 조각을 나눠 갖는다. 화면에 보여 줄 제목은 모바일 쪽을 우선하는 분기가 있지만 그것을 같은 글인지 결정하는 기준과 혼동하지 않았다. 표시 제목을 고르는 정책과 자료의 동일성을 정하는 정책은 다른 자리에서 읽어야 했다.
예외의 제목 키는 편리하지만 정보를 줄였다
식별자 일부가 없는 예외에는 다른 분기가 있다. 게시자 ID와 정규화한 제목으로 보조 키를 만든다. 정규화는 공백과 구두점 등을 없애고 영문·숫자·한글 음절만 남긴다. 설명용 제목 A-B와 AB는 같은 키가 될 수 있다. 남기는 문자가 없는 제목끼리는 빈 키에 모일 가능성도 코드에서 읽을 수 있다.
이것은 확인한 예외 분기의 위험이지, 정상 검색 파서가 실제로 그런 행을 보냈다는 증거는 아니다. 또 원래 보조 키는 완전 식별자의 키와 종류가 달라, 제목이 같은 미확인 행을 기존 정본에 자동으로 연결해 주는 구조도 아니었다. 제목 보조 키를 보완했다고 말하려면 어느 호출 경로에서 어떤 불완전한 입력이 들어오는지부터 확인해야 한다.
자동 정리 대신 검토 후보를 남기는 쪽을 만들었다
나는 새 독립 예제에서 불완전한 행을 각각 남기고 제목이 비슷한 그룹을 별도 후보로 돌려주었다. 같은 ID 두 행은 같은 그룹 아래 보관하지만 어느 행도 삭제하지 않는다. 같은 제목의 ID 두 개가 있으면 둘 다 남는다. ID가 없는 행이 그 사이에 들어와도 먼저 나온 정본에 붙이지 않는다. 이 코드는 원래 수집기에 설치한 수정이 아니라 공개를 위해 새로 만든 합성 구현이다.
여기서 일부러 감수한 비용이 있다. 미확인 행이 많으면 목록이 덜 깔끔하고 검토해야 할 후보가 늘 수 있다. 자료 손실을 자동 정리로 감추는 것보다, 모르는 관계를 화면과 원장에 남기는 편을 골랐다. 실제 운영에서는 허용한 식별 규칙·검토 담당자·선택 이유·정정 이력을 추가해야 한다. 현재 함수가 그 절차까지 수행하지는 않는다.
한 번 합친 뒤에는 다른 통계까지 달라질 수 있다
글의 동일성을 잘못 정하면 그 뒤의 검색 위치·좋아요·댓글 같은 값도 엉뚱한 글에 붙을 수 있다. 그러므로 가장 좋은 위치 하나를 고르기 전에 어떤 관측들이 같은 대상을 가리키는지 읽을 수 있어야 한다. 이번 예제에는 순위나 성과 집계가 없다. 기존 검색 관측 모듈은 조사 여부와 관측 상태를 표현하는 별도의 구현으로 연결했다.
출처별로 조사하지 않음·확인 불가·범위 내 미검출을 나누는 판단과, 두 행이 같은 글인지 검토하는 판단은 서로 대신하지 못한다. 같은 식별자를 선언했다는 것만으로 실제 서비스의 정본임이 인증되는 것도 아니다. 그래서 예제 출력에는 식별 확인과 병합 승인, 외부 쓰기를 수행하지 않았다는 값도 함께 남겼다.
시험은 정리하기 쉬운 경우보다 애매한 경우를 중심에 뒀다
새 예제의 시험은 같은 ID의 제목 변경, 같은 제목의 다른 ID, 두 정본 후보와 ID 없는 행을 각각 다룬다. 마지막 사례를 입력하는 순서를 여섯 가지로 바꿔도 결과가 같아야 한다. 웹 행을 먼저 줬다는 이유로 미확인 행의 짝이 정해지는 구조를 피하려 했다. 앞자리 0과 자료 집합의 차이, 빈 제목 키, 입력을 바꾸지 않는지도 확인했다.
패키지의 27개 시험 메서드를 로컬에서 실행하고 ZIP으로 묶은 뒤 추출해 다시 검사한다. 다섯 저장 기록은 그 합성 함수를 실제로 실행한 출력이다. 이 수를 원래 수집기의 시험이나 실제 사이트 검수로 바꾸어 쓰지 않는다. 공개 화면은 저장된 기록을 읽는 선택기이며 원래 글·사진·계정·브라우저·수집 작업을 사용하지 않았다.
목록을 간결하게 만드는 순서를 바꾸고 싶었다
수집 기능을 홈페이지에 넣을 때는 중복 제거 버튼부터 만들기보다, 한 줄의 식별 근거와 남은 관측을 먼저 보여 주는 편이 낫다고 생각했다. 예를 들어 ‘중복 정리 완료’보다 ‘같은 제목의 검토 후보 · 자동 병합 안 함’이라는 표시가 현재 예제의 행동에 맞는다. 이것은 새로 제안하는 운영 문구이며 원래 고객 화면에서 쓰고 있다고 주장하는 문장은 아니다.
아래 모듈에는 전체 코드·시험·기록·사용법을 함께 남겼다. 완전 식별자의 기준은 업무에 맞춰 바꾸고, 제목 후보의 범위도 다국어 자료에 맞게 다시 정해야 한다. 어떤 행을 남겼는지부터 설명할 수 있으면 나중에 정리 방식을 고칠 때도 원장을 잃지 않는다. 그런 자료 수집 기능이나 운영 화면을 함께 설계할 필요가 있을 때는 사이트 하단의 이메일 문의로 이야기할 수 있다.