Visual BASIC 6.0 Developer

DB Key를 URI나 파라미터로 노출하는 것은 위험할까?

TL;DR
Auto‑Increment ID를 그대로 URI에 노출하면 예측 가능성 때문에 brute‑force·IDOR 등 여러 공격에 당할 수 있는 취약점이 발생한다. 대안은 식별자를 암·복호화처리하거나, 처음부터 예측 불가능한 식별자를 쓰는 것이다. 후자가 훨씬 단순하고 실용적이다.

계기가 된 논쟁

“URL 에서 id 가 보이는 건 안티패턴이다.”

당시 그 동료는 /products/1 같은 요청을 문제 삼으며, 문자 단위 1:1 매핑으로 /products/iksd → 내부적으로 1234 로 처리하도록 구현해 두었다. 나는 REST 관련 문서를 찾아가며 “왜 그렇게 해요? 일반적인 REST API 경로 잖아요”라고 맞섰다.

실제로 대표적인 REST 참고 문서에서도 id가 포함된 URI를 예시로 쓰고 있다.

그런데 시간이 지나 생각해 보니, 그 동료가 걱정한 건 auto increment id(이하 aid) 가 갖는 특유의 보안·운영 리스크였다. (읽으면서 눈치챈 사람이 이미 있겠지만 저런 1:1 매핑은 공격을 당할 때 10분의 시간도 못벌어줄 가능성이 크다.)

Auto‑Increment ID가 노출될 때 발생하는 보안 취약점

  1. 예측 가능한 식별자
    1, 2, 3 … 처럼 순차 증가하니 공격자가 손쉽게 다음·이전 레코드를 시도할 수 있다.
  2. 데이터 규모 유추
    /posts/123456 → “대략 12만 건쯤 있겠군.”
  3. IDOR(인증·인가 우회)
    다른 사용자의 ID 를 추측해 접근을 시도할 여지가 커진다.
  4. 브루트포스 자동화
    ID 범위를 스크립트로 훑어보며 데이터 수집·파괴 가능.
  5. 경쟁사·외부 분석
    주문·가입 속도 등 내부 지표가 간접적으로 노출된다.
  6. 다른 취약점과 결합
    SQL 인젝션, 캐시 조작 등 2차 공격의 열쇠가 될 수 있다.

운영 측면에서 aid가 안고 있는 기술적 부담

# 위험 요소 이유
1 키 충돌 마이크로서비스별 DB 분리 시 같은 123 이 여러 곳에서 생성될 수 있음
2 전역 고유성 부재 시스템 간 통합 추적이 어려움
3 Hotspot 문제 순차 증가 키는 특정 샤드·파티션에 쓰기 집중
4 백업·복원 충돌 복제/마이그레이션 시 중복 키 충돌 가능
5 비즈니스 로직 의존 많은 코드·캐시가 aid 를 전제하면 변경 난이도 급증
6 테스트 ID 재사용 로컬·CI 환경에서 aid 중복으로 테스트 충돌

두 가지 대응 전략

A — 식별자 암·복호화(E2EE)

금융권 등 일부 영역에서는 TLS에 더해서 HTTP 등 통신 페이로드를 한 번 더 암호화 하기도 한다. 구현 예시는 다음과 같다.

1. 클라이언트는 서버의 공개키(Public Key)를 보유
2. 클라이언트가 AES 세션 키 생성
3. 세션 키를 서버 공개키로 암호화 → 전송
4. 서버는 개인키로 복호화하여 세션 키 획득
5. 이후 AES‑256 으로 Payload 암·복호화

문제는 복잡도다. 키 교환, 키 보관, JS 메모리 상 키 노출, 디버깅 난이도… aid 가 가진 문제를 근본적으로 해결하지 못한 채 난이도만 올릴 수 있다.

B — 예측 불가능한 전역 고유 식별자 사용

  • UUID v7, ULID, KSUID, NanoId, Snowflake, Sonyflake
    대체 식별자는 시간 정보 + 무작위 비트 를 섞어 정렬 성능예측 불가능성 을 동시에 확보한다.
  • 주요 DB 인덱스(B‑tree 등)에서 무작위성으로 인한 성능 저하를 줄이려면 상위 비트에 타임스탬프를 배치 하는 설계가 일반적이다.
  • 의존성도 낮다. 서버·클라이언트 어느 한쪽에서 생성해도 충돌 확률이 무시할 만하다.
  • 일반적으로 uuid의 생성 조차도 DB 부하의 여지가 있고, 서버측에서 생성하는 경우에, SELECT 쿼리 날리는 비용조차 아껴서 트랜잭션 내에서 더 자유롭게 처리할 수 있어 서버에서 처리한다.

개인적으로는 B 가 ‘보안·운영·개발 생산성’ 세 마리 토끼를 모두 잡는 현실적 해법이라 본다.

JWT·URI 파라미터에 memberId 를 넣어도 될까?

최근 사이드 프로젝트에서 “JWT 안에 memberId(aid) 를 그대로 넣어도 되나?” 라는 대화를 나누는 것이 봤다. 바로 거기에서 이 포스팅이 출발했다. 내 결론은 아래와 같다.

  • aid 그대로라면 → URI·JWT·로그 그 어디든 노출을 최소화해야 한다. 앞서 본 모든 리스크가 적용된다.
  • UUID v7 등 opaque ID 라면 → 평문 노출만으로는 특별한 보안 위협이 없다. -> 아직 이게 위험하다고 생각한다면 A의 방법으로 가서 종단간 암호화 말고는 방법이 없다. 어떤 정보도 기준에 따라 민감정보일 수 있고, TLS로 이미 암호화 통신을 하여 패킷을 감청해도 복호화할 수 없다고 보는 것인데, 평문 노출이 문제가 된다면 모든 평문을 없애야 하는 것이다.

맺으며

“DB Key를 URI에 노출해도 될까?” 라는 질문의 핵심은 식별자의 예측 가능성 이다. 만약 여러분이 아직 aid 를 URI·파라미터·토큰에 노출하고 있다면, 다음 스프린트에서 전역 고유 식별자 로의 전환을 검토해 보자. 종단간 암호화 E2EE 같은 복잡한 로직을 적용하기 전에 말이다.

다른 사람들의 의견

GetMapping시 URI에 PK 식별자가 노출되는 문제: 대체키를 사용한 해결 [키설계] UUID와 increment PK는 언제 사용해야할까?

Written on July 6, 2025
Scroll to top