CATEGORY_NOT_MAPPED 오류가 수백 건 났고 전부 같은 분류에 속한 것들이었다. category_mappings 를 category_id 로 확인하니 없는데 이름으로 검색하니 같은 이름의 매핑이 나왔다.
Table of contents
Open Table of contents
원인 — 같은 이름의 두 트리
categories 를 name 으로 조회하니 id 가 다른 두 행이 나왔고 parent_id 를 따라가 보니 완전히 다른 트리였다. 세 단계 위까지 이름이 같은데 식별자는 전부 달랐다.
옛 트리와 새 트리가 병존하고 있었고 이관 중이거나 이관하다 만 상태로 보였다. 이름만 보면 하나로 보이지만 시스템 안에서는 서로 다른 두 대상이었다.
배경 — 매핑이 한쪽에만 있던 이유
외부 분류 매핑은 새 트리에만 걸려 있었고 오류가 난 대상들은 옛 트리에 붙어 있었다. 그래서 매핑이 없다는 결과가 나온 것이었다.
여기까지 보면 새 트리의 매핑을 옛 트리에도 복사하는 것이 자연스러운 해결로 보인다. 이름이 같으니 같은 값이 맞을 것이라는 전제가 그 판단의 바탕이었다.
검증 — 복사하기 전에 본 매핑값
복사하려던 channel_category_code 가 실제로 무엇을 가리키는지 확인해 봤더니 침구 계열이었다. 그런데 옛 트리에 붙어 있는 상품들은 문구류와 매트와 보관함 같은 잡화였다.
새 트리의 매핑 자체가 부정확했고 그것을 복사했으면 잡화를 침구로 내보냈을 것이다. 이름이 같다는 것이 내용이 같다는 뜻은 아니었다.
주의 — 어느 테이블이 정본인가
조사하면서 상품과 분류의 연결을 어디서 봐야 하는지도 확인해야 했다. products.category_id 도 있고 별도 product_categories 도 있었다.
product_categories 가 정본이었고 products.category_id 는 옛것이거나 다른 용도였다. 어느 쪽이 정본인지 확인하지 않으면 조사 자체가 틀린 데이터 위에서 시작된다.
조치 — 대량 변경 대신 최소 추가
두 가지 방법이 있었는데 대상을 새 트리로 옮기는 것과 옛 트리에 매핑을 하나 추가하는 것이다. 앞쪽은 수백 건의 product_categories 를 바꾸는 대량 변경이고 다른 영향이 어디까지인지 알 수 없었다. 뒤쪽은 INSERT 한 행이면 끝난다.
뒤쪽을 골랐다. 이유는 영향 범위를 한 행으로 닫을 수 있어서다. 대신 옛 트리가 정리될 때까지 두 트리에 매핑이 따로 사는 것을 감수했고 값은 새 트리 것을 복사하지 않고 실제 상품 구성에 맞는 것을 골랐다. 이후로 동일성 판단에 이름을 쓰지 않고 식별자와 조상 트리를 함께 조회하는 것을 조회 규칙으로 삼았다.
정리
- 같은 이름의 항목이 서로 다른 트리에 병존할 수 있다
- 이름만 보면 하나로 보이지만 시스템에서는 다른 대상이다
- 이름으로 동일성을 판단하지 않고 식별자와 조상으로 확인한다
- 이름이 같다고 다른 쪽 설정을 복사하면 엉뚱한 곳으로 간다
- 복사 전에 그 설정값이 실제 내용과 맞는지 본다
- 연결을 볼 때 어느 테이블이 정본인지 먼저 확인한다
- 정본을 안 정하면 조사가 틀린 데이터에서 시작된다
- 대량 변경보다 최소 추가를 택한다