URL의 식별자를 '복호화'한다는 착각
평문 합성 식별자 — 역파싱 대신 정방향 매칭
난이도: ★★★☆☆ 연관 노트: URL을 진실의 원천으로
핵심 요약
- URL에 심은 식별자가 **암호화된 게 아니라 그냥 값들을 이어붙인 조합(평문)**이면, 되짚는 건 “복호화”가 아니다 — 그냥 **역참조(lookup)**다.
- 그 값을 거꾸로 파싱해서(예: 숫자 부분만 떼어 id로) 주체를 찾으려 하면 위험하다 — 식별자 종류가 여럿이고 형태가 겹치면(둘 다 숫자면) 어느 쪽인지 구분이 안 된다.
- 정답은 정방향 매칭: 내보내는 순간
(식별자 ↔ 내부 PK)를 쌍으로 로그에 기록해두고, 나중엔 그 로그에서 식별자로 행을 찾아 짝지어진 PK를 읽는다. 파싱 없음 → 종류 구분 없이 한 컬럼으로 균일하게 매칭.
왜 헷갈렸나
- URL의
?key=...값을 보고 **“복호화해서 누군지 알아낸다”**고 표현 → 애초에 암호화한 적이 없으니 틀린 프레임. - “식별자에서 내부 id를 떼어내서 조회하면 되지” → 역파싱 발상. 근데 식별자가 두 종류였다:
- 비회원:
key = 내부 리드 PK(그냥 숫자) - 회원:
key = 이름 앞 몇 글자 + 유저 id를 이어붙인 합성값 앞 몇 글자가 우연히 전부 숫자면 회원 합성값도 순수 숫자로 보여서 → 비회원 PK와 형태가 구분 안 됨 → 역파싱하면 오귀속.
- 비회원:
메커니즘
로그를 남길 때 key에 넣은 값(uid)과 내부 PK를 같은 행에 쌍으로 저장한다. 그러면 되짚기가 단 한 번의 매칭으로 끝난다.
send_log
uid | pk(lead_id)
─────────────┼────────────
ab1298765 | 123 ← 회원: uid=합성값, pk는 별도 컬럼
124861 | 124861 ← 비회원: uid=pk (같은 값이 두 컬럼에)
되짚기 (분기 없음, 한 방):
분석 이벤트의 key → WHERE uid = key → 그 행의 pk 를 읽음
핵심: 매칭 시점엔 이 key가 회원 합성값인지 비회원 PK인지 알 필요가 없다. uid 컬럼 하나에 뭘 넣었든 그대로 들어있으니, key = uid로 매칭하면 종류 불문하고 짝 PK가 딸려 나온다. “숫자면 PK로 취급” 같은 분기를 하는 순간 형태 충돌에 당한다.
해결 패턴
// 내보낼 때: uid와 내부 PK를 쌍으로 기록
await log.insert({ uid, lead_id, sent_at });
// 되짚을 때: 파싱하지 말고 매칭
// 이벤트.key = log.uid → 같은 행의 lead_id 획득 (단일 조인)
SELECT e.key, l.lead_id
FROM events e JOIN send_log l ON l.uid = e.key
주의: 링크에 넣을 때
encodeURIComponent를 거쳤다면, 되짚기 전에 디코딩해서 raw uid로 매칭해야 한다(로그엔 raw로 저장돼 있으므로).
다음에 이 상황을 만나면
“URL/토큰에서 주체를 알아내야 한다” → 먼저 물어라: 이건 암호화된 건가, 평문 조합인가?
- 평문이면 “복호화”가 아니라 lookup — 역파싱 유혹을 경계
- 발행 시점에
(공개식별자 ↔ 내부키)쌍을 기록해뒀나? → 있으면 정방향 매칭 - 식별자 종류가 여럿인가? 형태가 겹칠 수 있나(둘 다 숫자)? → 파싱 분기 금지, 기록된 컬럼에 균일 매칭
커넥팅 닷
← 선행 개념 (이걸 알아야 이해된다)
- URL을 진실의 원천으로 — 식별자를 URL 파라미터로 실어 나른다는 발상의 토대.
- 암호화 vs 인코딩 vs 해싱 — “복호화”라는 단어를 쓰기 전에 셋을 구분해야. 조합은 셋 중 아무것도 아님.
→ 확장 개념 (여기서 더 나아가면)
- 불투명(opaque) 식별자 설계 — 종류를 타입 접두어(
u_,l_)로 명시하면 형태 충돌 자체가 사라진다. 여기선 안 했기에 정방향 매칭으로 우회. - surrogate key vs natural key — 왜 PK를 URL에 직접 노출하는 게 위험/애매한지.
↔ 같은 원리가 적용되는 곳
- 로그를 “발생 시점 사실의 불변 기록”으로 쓰기 — 나중에 재계산·역추론하지 말고, 그 순간의 정답을 남겨 조회. (이벤트 소싱의 축소판)
- 어트리뷰션 조인 — 광고/CRM에서 클릭↔전환을 잇는 것도 “발행 시 심은 식별자 ↔ 기록” 매칭.
참고
- Wikipedia — Opaque pointer / identifier — 불투명 식별자 개념