Skip to content
isdnetworks
Go back

인코딩된 식별자의 복원

한 채널에서 속성값 오류가 나는 건이 아홉 개 있었다. 우리 쪽 이력에 매핑 기록이 없어서 어느 옵션을 가리키는지 알 수 없었다.

Table of contents

Open Table of contents

변환값으로 보인 코드

마켓 API로 상품 정보를 조회하니 특정 접두어로 시작하는 코드가 들어 있었다. 우리 데이터베이스에는 그런 값이 없었다.

접두어를 떼고 남는 숫자의 범위가 32비트 정수였고 우리 식별자를 무언가로 변환한 값으로 보였다. 연동 코드를 뒤져 인코딩 함수를 찾으니 곱셈과 모듈러와 배타적 논리합을 조합한 형태였다.

역함수로 되돌린 식별자

그 조합은 가역이므로 역함수를 만들 수 있었다. 곱셈을 되돌리려면 모듈러 역원이 필요해서 그것을 구해 넣었다.

def decode(encoded):
    return ((encoded ^ RANDOM) * INVERSE) % (2**31)

되돌린 값으로 옵션 테이블을 조회하니 해당 행이 나왔다. 매핑 이력이 없어도 코드 자체가 매핑을 담고 있으므로 밖에 등록된 값과 우리 행을 직접 대조할 수 있었다.

네 갈래의 출처

아홉 건을 하나씩 되돌려 어느 행인지 봤더니 성격이 갈렸다. 같은 상품의 소프트 삭제된 옵션과 상위 상품의 옵션과 현재 활성 옵션과 이관 전 원본 넷이었다.

어느 쪽이냐에 따라 대응이 다르므로 이 분류가 필요했다. 문제의 아홉 건은 전부 첫 번째였는데 옵션을 갈아엎으면서 옛것을 소프트 삭제했는데 마켓에는 여전히 그 코드가 등록돼 있는 상태였다.

복원 로직이 봐야 할 범위

이것을 알고 나니 복원 로직 설계가 달라졌다. 처음 생각한 것은 마이그레이션 이력으로 옛 식별자를 찾는 것이었는데 삭제된 옵션은 그 이력에 안 남는다.

소프트 삭제된 행까지 조회해야 후보가 나온다. 삭제된 것도 후보라는 것을 알아야 그 조건을 쿼리에 넣게 되므로 출처 분류가 곧 조회 범위를 정했다.

한 스크립트 안의 조사

이 조사를 컨테이너 안에서 실제 연동 클라이언트를 그대로 써서 한 번에 돌렸다. API를 호출해 응답에서 코드를 뽑고 되돌린 뒤 데이터베이스를 조회해 출처까지 분류한다.

호출과 조회를 따로 하면 응답을 복사해 옮겨야 하고 그 과정에서 틀린다. 기존 클라이언트를 쓰면 인증과 헤더와 형식을 다시 만들 필요가 없다는 것도 컸다. 이번에는 인코딩이 가역이라 운이 좋았는데 해시였으면 후보 식별자를 전부 정방향으로 인코딩해 일치하는 것을 찾는 방법밖에 없고 그것은 범위를 좁힐 수 있을 때만 가능하다.

정리


Share this post on:

Previous Post
읽을 때 맞출지 쓸 때 갈릴지 정했다
Next Post
완료를 되읽는 세 가지