Skip to content
isdnetworks
Go back

양쪽에 똑같이 적용해 대칭으로 맞췄다

(수정됨)

sku 문자열을 저장할 때는 정리해서 넣고 찾을 때는 정리하지 않고 찾고 있었다. 저장 시점에 strtoupper() 와 trim() 을 거치는데 조회는 입력 그대로 하니 방금 넣은 값도 못 찾았다.

Table of contents

Open Table of contents

해결 — 한 함수로 묶은 양쪽

두 가지 방법이 있었는데 조회 쪽에도 같은 strtoupper() 와 trim() 을 적어 넣는 것과 SkuNormalizer::normalize() 하나를 만들어 저장과 조회 양쪽에서 부르게 하는 것이다. 뒤쪽을 골랐다. 이유는 규칙이 바뀌더라도 양쪽이 언제나 같이 바뀌어서다. 대신 한 줄짜리 처리를 위해 클래스 하나가 늘어나는 것을 감수했다.

양쪽에 같은 함수를 쓰는 것이 대칭을 지키는 방법이었다. 각자 같은 처리를 적어 두면 한쪽만 고쳐지는 것은 시간문제다.

검증 — 다른 대칭 쌍의 점검

같은 성격의 쌍이 더 있는지를 저장소 전체에서 훑었다. 암호화와 복호화와 인코딩과 디코딩과 직렬화와 역직렬화와 압축과 해제가 나왔다.

각각 양쪽이 맞는지 확인하다가 인코딩에서 하나가 걸렸다. 한 자리에서 json_encode() 에 JSON_NUMERIC_CHECK 를 쓰고 있어서 PHP 매뉴얼대로 숫자처럼 보이는 문자열이 숫자로 인코딩돼 앞자리 0 이 사라졌고 받는 쪽은 문자열을 기대하고 있었다.

왕복 시험과 경계 값

넣은 것을 다시 꺼내면 같은 값이 나오는지를 assertSame() 으로 확인하는 시험을 만들었다. 정규화와 암호화 양쪽에 같은 형태의 시험을 넣었다.

경계 값도 함께 넣었는데 빈 문자열과 아주 긴 것과 특수문자와 여러 언어를 섞어서 돌렸다. 그중 빈 문자열에서 하나가 걸렸다.

조치 — 이미 저장된 것의 정리

정규화를 나중에 넣었으므로 그 전에 저장된 것은 규칙에 안 맞을 수 있었다. WHERE sku != UPPER(TRIM(sku)) 로 세어 보니 수백 건이 그런 상태였다.

일괄로 맞추기 전에 정규화하면 서로 같아지는 것이 생기는지를 GROUP BY UPPER(TRIM(sku)) HAVING COUNT(*) > 1 로 먼저 확인했고 셋이 겹쳤다. 정규화하면 같아지는 다른 상품이라 따로 처리했다. 맞추는 작업이 유일성을 깨뜨릴 수 있으므로 겹침 확인이 먼저다.

어디까지 정규화할지도 적었다. 앞뒤 공백과 대소문자는 하고 가운데 공백과 하이픈과 특수문자는 안 하는데 가운데 공백을 없애면 다른 코드가 같아질 수 있기 때문이다. 안 적으면 나중에 누가 더 넣는다.

들어오는 자리로 옮긴 정규화

정규화를 양쪽에 넣고도 여전히 안 맞는 자리가 하나 있었다. 비교하는 코드에 한쪽만 정규화된 값이 들어오고 있었고 그것은 외부에서 받은 값이었다.

비교하는 자리마다 양쪽을 정규화하는 대신 값이 들어오는 ProductRequest 에서 한 번 정규화하게 바꿨다. 생성 시점에 정규화하니 그 뒤로는 어디서 비교해도 맞았다. 들어오는 자리에서 한 번 하는 것이 쓰는 자리마다 하는 것보다 확실하다.

비슷한 정규화를 하는 자리가 넷 더 있었고 조금씩 달라서 전부 한 함수를 쓰게 바꿨다. 여러 개면 또 갈린다.

정리


Share this post on:

Previous Post
고치기 전의 실패 로그
Next Post
앞 단계에서 이미 받아 둔 것