구버전 API 로 들어온 식별자를 신버전 마스터로 이어야 했다. 치환 지점은 OpenAPIProductForceRoute 미들웨어 하나였다.
Table of contents
Open Table of contents
증상 — 치환이 안 됐다
치환하는 자리는 이랬다.
// OpenAPIProductForceRoute.php
$product = Product::findByOptimusId($id);
if (!$product->is_master) {
$id = $product->parent->opaque_id; // 부모로 치환
}
is_master 가 아니면 parent 를 따라가 마스터의 식별자로 바꾼다.
그런데 일부 opaque_id 는 치환이 안 됐다. 그 상품들을 조회했다.
SELECT id, version, is_master, parent_product_id
FROM products WHERE opaque_id = ?;
version v1-migrated
is_master 0
parent_product_id NULL
is_master 도 0이고 parent_product_id 도 비어 있었다.
원인 — 원본이 남아 있었다
version 에 찍힌 v1-migrated 가 무엇인지 봤다.
[예상] 마이그레이션 = 원본을 신버전으로 변환
[실제] 원본은 남기고 별도로 신버전 생성
마이그레이션이 원본을 지우지 않고 version 만 바꿔 둔 것이었다.
새 행을 만들고 옛 행을 지우지 않았으니 두 행이 모두 살아 있는 상태다. 없어서 못 잇는 것이 아니라 있는데도 안 이어지고 있었다.
제약 — 없는 부모 관계
v1-migrated 행과 마스터 사이에 관계가 없었다.
[신버전 마스터] ← 하위 상품들이 parent 로 연결
[마이그레이션 원본] ← 아무 관계 없음
parent_product_id 가 비어 있으니 치환 로직이 탈 수가 없다.
일반 하위 상품은 부모 관계로 마스터를 찾지만 마이그레이션 원본에는 그 길이 아예 없었다. 부모 관계만 보면 원본은 영원히 안 이어진다.
판단 기준 — 매핑은 별도 표에
그러면 원본과 마스터를 잇는 정보가 어디 있는지를 찾아야 했다.
마이그레이션 로그
원본 상품 id → 신버전 마스터 id
마이그레이션 로그 표에만 원본 id 와 마스터 id 의 대응이 있었다.
관계가 자료 구조에 없고 이관 기록에만 있는 상태였다. 그 로그를 읽는 것 말고는 두 쪽을 잇는 방법이 없었다.
주의 — 플래그가 아니라 권한
어떤 업체가 신버전 대상이 되는지도 함께 확인했다.
[예상] 플래그 컬럼
[실제] 특정 권한 보유 여부로 판정
권한 체계에 붙어 있어서 products 스키마를 뒤졌으면 못 찾았을 것이다.
부모 관계와 마찬가지로 직관과 다른 자리에 있었다. 자료의 실제 값에서 시작해 그 값을 쓰는 코드 분기를 따라가는 순서가 답을 냈다.
결과 — 단일 진입점과 확인 순서
구조와 별개로 다행인 것이 하나 있었다.
OpenAPI 요청
↓
OpenAPIProductForceRoute ← 여기
↓
컨트롤러들
OpenAPIProductForceRoute 하나라 거기만 고치면 모든 요청 종류에 적용된다.
등록과 조회와 수정이 각각 치환하는 구조였으면 세 곳을 고치고 하나를 빠뜨렸을 것이다.
이번에 확인한 순서도 함께 적어 뒀다.
① 안 되는 케이스의 실제 컬럼 값을 봄
② 그 값으로 코드에서 분기를 찾음
③ 분기가 안 타는 이유를 확인 (parent NULL)
④ 그럼 어디에 매핑이 있는지 스키마에서 찾음
코드에서 시작하지 않고 데이터에서 시작해 코드로 가는 순서였다.
기록에는 신뢰도를 갈라 적었다. 구조는 확정이지만 권한 식별자와 로그 표의 정확한 이름은 쓸 때 다시 확인한다고 명시했다. 이름은 바뀔 수 있고 잘못 적으면 다음 사람이 그대로 쓰다가 틀린다.
정리
- 마이그레이션이 원본을 삭제하지 않고 남길 수 있다
- 원본은 마스터도 부모도 아니다
- 부모 관계로 치환하는 로직이 안 탄다
- 원본과 마스터의 대응이 별도 로그 표에만 있을 수 있다
- 대상 여부가 플래그가 아니라 권한일 수 있다
- 치환 진입점이 하나면 거기만 고치면 된다
- 실제 컬럼 값에서 시작해 코드 분기로 간다
- 기록에는 구조와 식별자의 신뢰도를 다르게 적는다