ICS → Discourse 가져오기 도구

ics_to_discourse.py 테스트를 통한 동작 노트

이 스크립트(--time-only-dedupe 옵션이 있는 경우와 없는 경우)에 대해 일련의 테스트를 수행했으며, 업데이트/채택(Adoption) 흐름을 자세히 문서화하는 것이 유용할 것 같아 정리했습니다.


1. 고유성(Uniqueness) 결정 방식

  • 기본 모드: 채택(Adoption)을 위해서는 시작 시간 + 종료 시간 + 위치이 정확히 일치해야 합니다.
  • --time-only-dedupe 사용 시: 채택을 위해서는 시작 시간 + 종료 시간만 일치하면 됩니다. 위치는 "충분히 가까움"으로 처리됩니다.

기존 토픽이 이러한 규칙과 일치하지 않으면 새 토픽이 생성됩니다.


2. UID 마커의 역할

  • 모든 이벤트 토픽에는 첫 번째 게시물에 숨겨진 HTML 마커가 삽입됩니다:
  <!-- ICSUID:xxxxxxxxxxxxxxxx -->
  • 이후 실행 시 스크립트는 먼저 해당 마커를 검색합니다.
  • 마커가 발견되면 해당 토픽은 UID 일치로 간주되며, DESCRIPTION 텍스트가 얼마나 노이즈가 많거나 구식이든 관계없이 직접 업데이트됩니다.
  • 이는 UID가 **진정한 식별 키(identity key)**임을 의미합니다. 가시적인 설명 필드는 매칭에 영향을 주지 않습니다.

3. UID 일치 시 업데이트 흐름

  1. 스크립트가 첫 번째 게시물을 가져오고 마커를 제거합니다:
old_clean = strip_marker(old_raw)
fresh_clean = strip_marker(fresh_raw)
  1. old_clean == fresh_clean인 경우: 업데이트하지 않음 (불필요한 변경 방지).
  2. 서로 다른 경우: 변경 사항이 "의미 있는(meaningful)"지 여부를 확인합니다:
meaningful = (
    _norm_time(old_attrs.get("start")) != _norm_time(new_attrs.get("start"))
    or _norm_time(old_attrs.get("end")) != _norm_time(new_attrs.get("end"))
    or _norm_loc(old_attrs.get("location")) != _norm_loc(new_attrs.get("location"))
)
  • meaningful = True인 경우 → bump와 함께 업데이트 (토픽이 ‘최근’ 목록에서 위로 올라감).

  • meaningful = False인 경우 → 조용히 업데이트 (bypass_bump=True → 리비전만 생성, bump 없음).

    1. 태그가 병합됩니다 (정적/기본 태그가 존재하도록 보장하며, 관리자나 수동으로 추가된 태그는 절대 제거하지 않음).
    2. 업데이트 시 제목과 카테고리는 절대 변경되지 않습니다.

  1. UID 일치 없이 업데이트 흐름
    1. 스크립트가 채택을 시도합니다:
      • 시작/종료/위치(또는 --time-only-dedupe 사용 시 시작/종료만) 후보 3원조를 구성합니다.
      /search.json/latest.json에서 속성이 일치하는 기존 이벤트를 검색합니다.
      • 발견되면 → 해당 토픽을 채택하고 UID 마커 + 태그를 후속 적용합니다 (이 단계에서는 본문은 변경되지 않음).
      • 발견되지 않으면 → 마커와 태그가 포함된 완전히 새로운 토픽을 생성합니다.
    2. 채택 또는 생성이 완료되면, 모든 향후 동기화는 UID를 통해 직접 해결됩니다.

  1. 실질적 결과
    • 시간 변경
    • 기본: 채택 실패 (시간이 다름) → 새 토픽 생성.
    --time-only-dedupe 사용 시: 채택이 동일한 방식으로 실패함. 새 토픽 생성.
    • 위치 변경
    • 기본: 채택 실패 (위치가 다름) → 새 토픽 생성.
    --time-only-dedupe 사용 시: 채택 성공 (시간 일치), 하지만 위치 차이는 “의미 있는” 것으로 플래그가 지정되어 → bump와 함께 업데이트.
    • 설명(Description) 변경
    • DESCRIPTION 텍스트가 변경되었지만 시작/종료/위치는 변경되지 않은 경우:
    • 본문을 조용히 업데이트 (bypass_bump=True).
    • 토픽 리비전이 생성되지만 ‘최근’ 목록에서 bump는 발생하지 않음.
    • DESCRIPTION이 변경되지 않았거나 (또는 Last Updated:와 같이 정규화되어 사라지는 노이즈만 있는 경우) 업데이트가 전혀 발생하지 않음.
    • UID 마커
    • 향후 동기화 시 신뢰할 수 있는 매칭을 보장합니다.
    • 노이즈가 많은 DESCRIPTION 필드가 올바른 토픽이 발견되는지에 영향을 주지 않음을 의미합니다.

  1. DESCRIPTION이 때로는 “변경되지 않은 것처럼” 보이는 이유

스크립트는 UID 마커를 제외한 전체 본문을 비교합니다.
Last Updated:와 같이 변동성이 큰 줄만 다르고, 이것이 정규화되어 사라지는 경우(예: 공백, 줄바꿈, 유니코드) old_cleanfresh_clean이 동일하게 보임 → 업데이트가 수행되지 않음.
이는 피드 노이즈로 인한 불필요한 변경을 방지하기 위한 의도적인 설계입니다.


요약

  • 시간은 고유성을 정의합니다 (시간이 변경되면 항상 새 토픽이 생성됨).
  • 위치 변경 → 가시적인 bump 발생 (사용자가 장소 업데이트를 인지할 수 있도록).
  • 설명 변경 → 조용한 업데이트 (리비전은 생성되지만 bump 없음).
  • UID 마커 = 신뢰할 수 있는 식별 키, DESCRIPTION이 구식이거나 노이즈가 많아도 항상 올바른 토픽이 발견되도록 보장.

이는 좋은 균형을 맞춥니다: 중요한 변경 사항은 ‘최근’ 목록에 노출되고, 중요하지 않은 불필요한 변경은 보이지 않게 유지됩니다.