검색 뒤 주소에 원하는 단어가 들어 있다는 이유로 성공을 판정하면 비슷한 호스트와 다른 경로도 통과할 수 있다. 반대로 추적 매개변수가 하나 붙었다고 정상 검색을 실패로 볼 수도 있다. 나는 정확한 주소와 경로 조건을 별도 기대 종류로 나눴다.
url은 전체 주소의 의미를 유지한다
url 기대는 양쪽 값을 URL로 파싱한 href가 같은지 본다. 주소 문자열 일부를 포함하는지 확인하는 기능이 아니다. 경로와 쿼리, fragment를 포함한 정규화된 전체 주소가 비교 대상이 된다. 정확한 목적지가 필요한 작업에 이 의미를 유지했다.
URL 파서의 정규화와 호출자의 기대도 구별한다. 어떤 표현이 같은 주소가 되는지는 파서 규칙의 범위이며 페이지의 실제 내용과 계정이 같다는 뜻은 아니다. 같은 URL에 다른 로그인 화면이 뜰 수도 있으므로 주소 일치만으로 모든 업무 성공을 확인하지 않는다.
urlRoute는 origin과 pathname을 먼저 묶는다
경로 기대는 실제 주소와 요구 주소의 origin과 pathname이 같아야 한다. 호스트 이름에 원하는 문자열이 들어 있다고 다른 호스트를 허용하지 않는다. search와 searching처럼 경로 일부가 비슷해도 같지 않다.
이 선택은 정상 검색의 추가 쿼리를 허용하면서도 목적 서비스와 경로의 의미를 유지하려는 것이다. origin은 호스트 글자만이 아니라 프로토콜과 포트 관계도 포함한다. 원래 기대 주소가 잘못됐다면 정교한 비교도 잘못된 목적지를 확인한다. 호출자는 올바른 절대 주소를 업무에서 정해야 하고 도구는 그 계약을 일관되게 적용한다.
반복 쿼리 값은 집합이 아닌 개수로 본다
요구한 쿼리 key·value마다 실제 쿼리에서 한 쌍을 찾아 제거한다. 같은 q=a가 두 번 필요하면 실제에도 두 개가 있어야 한다. 단순한 딕셔너리로 바꾸면 반복 값이 사라지므로 요구 개수까지 확인할 수 없다.
실제 주소에 요구하지 않은 추가 매개변수가 있어도 urlRoute는 허용한다. 요구 쿼리가 없는 경로 기대는 그 경로의 다른 검색도 통과할 수 있다는 뜻이므로 필요한 조건을 빼서는 안 된다. fragment는 이 경로 비교의 성공 조건이 아니다. 어떤 차이를 무시하는지까지 알아야 기대 종류를 정확히 고를 수 있다.
상대 문자열은 전달 전에 거절한다
q=검색어나 search 같은 문자열을 URL 기대에 넣으면 호출자의 의도는 이해할 수 있어도 정확한 목적지가 아니다. 편의 API는 URL 생성이 가능한 절대 값인지 전달 전에 확인한다. 계약 검사에서도 상대 기대를 거절하는 시험이 있다.
오류를 고칠 때는 이 값을 urlRoute의 올바른 절대 주소로 바꾸거나 필요한 다른 기대를 정한다. 브라우저 문제로 단정하고 Enter를 반복하지 않는다. 이전 비교 기록에도 호출자의 기대 표현 오류와 실제 입력 경로의 수정은 구별돼 있다. 실패의 계층을 나눠야 맞는 곳을 고칠 수 있다.
검사 표본은 닮은 주소의 거절도 포함한다
단위 시험은 추가 추적 값이 있는 같은 검색 경로는 통과시키고 닮은 호스트와 다른 경로, 다른 검색어는 거절한다. 정확한 url은 추가 값 때문에 같지 않다는 것도 확인한다. 반복 쿼리가 부족한 사례 역시 실패해야 한다.
이 글은 실제 비교 함수와 관련 단위·보안 시험, page API의 전달 전 검사를 읽었다. 새 외부 사이트 탐색을 수행한 보고서는 아니다. URL 파싱과 쿼리 비교가 모든 리다이렉트의 업무 의미나 서비스 인증 상태를 확인한다는 주장도 하지 않는다. 이동 결과와 이후 작업의 결과는 별도로 본다.
비슷하다는 표현을 코드 계약으로 바꾼다
회사 프로그램에서 어떤 화면이 맞는지 판단할 때도 “이 정도면 비슷하다”는 표현을 구체화해야 한다. 주소 전체가 같아야 하는지, 같은 경로와 요구 조건이면 되는지에 따라 구현이 달라진다. 편하게 통과하는 비교가 항상 정확한 비교는 아니다.
나는 두 기대를 나눠 호출자가 무시할 차이를 의식적으로 선택하게 했다. 느슨함과 엄격함 중 하나만 고르는 문제가 아니라 업무에 필요한 동등성의 기준을 정하는 일이다. 그 기준이 있어야 정상 결과를 불필요하게 실패시키지 않으면서 다른 목적지를 성공으로 세지 않을 수 있다.