검증
고친 사람 github-actions[bot]
검증은 손에 든 것이 믿을 만한지 기준에 대어 보고 받아들일지 정하는 일입니다. 맞으면 받아들이고 어긋나면 거절합니다. 캐시에서는 보관해 둔 사본이 아직 원본과 같은지 묻는 일을 가리킵니다. 보안에서는 상대가 내민 주장이 참인지 증거로 따지는 일을 가리킵니다.
쉽고 빠른 이해
검증은 받은 것을 그냥 믿지 않고 기준과 맞춰 보는 일입니다. 로그인할 때 서버가 비밀번호를 저장된 값과 맞춰 보는 것이 검증입니다.
믿고 쓰면 곤란한 것이 있어서 합니다. 오래 묵은 사본은 원본이 바뀐 뒤에도 옛 값을 내줍니다. 남의 이름을 대는 요청은 겉으로는 진짜 요청과 구별되지 않습니다.
어떻게 도는가:
- 확인할 대상을 받습니다
- 믿을 수 있는 기준과 맞춰 봅니다
- 맞으면 받아들이고 어긋나면 거절합니다
믿을 수 있는 영역 밖에서 들어온 값이나 오래 묵은 사본에 씁니다. 이미 확인을 거친 안쪽 값에는 다시 하지 않습니다.
대가가 있습니다. 맞춰 보는 데 시간이 듭니다. 기준을 따로 들고 있어야 합니다. 기준이 보지 않는 것은 통과해도 모릅니다.
상세
편의점에서 술을 사면 점원이 신분증을 보여 달라고 합니다. 손님이 성인이라고 말해도 신분증의 생년월일을 보기 전에는 팔지 않습니다.
검증은 대상을 기준과 맞춰 본 결과로 받아들일지 거절할지 정하는 일입니다. 대상은 바깥에서 들어왔거나 시간이 지나 믿기 어려워진 것입니다. 사용자가 보낸 요청 값, 캐시에 오래 보관한 응답, 로그인할 때 내민 비밀번호가 모두 대상이 됩니다.
검증을 이루는 셋
검증은 어느 분야에서 쓰든 대상 · 기준 · 결과 세 가지로 이루어집니다. 이 소절은 그 뼈대를 세웁니다. 분야마다 그 셋에 무엇이 들어가는지는 뒤 소절들이 봅니다.
기준은 검증하는 쪽이 이미 믿고 있는 값이나 규칙입니다. 기준이 없으면 맞춰 볼 상대가 없으니 검증이 성립하지 않습니다. 가입할 때 저장해 둔 비밀번호, 요청 값이 따라야 할 형식 규칙이 기준의 예입니다.
결과는 받아들임과 거절 둘로 끝납니다. 중간값이 없어야 다음 단계가 무엇을 할지 정할 수 있습니다.
flowchart TD
A["대상 · 들어온 것"] --> B["기준과 맞춰 본다"]
C["기준 · 이미 믿는 값이나 규칙"] --> B
B -->|맞는다| D["받아들인다"]
B -->|어긋난다| E["거절한다"]
그림에서 기준은 대상과 다른 곳에서 옵니다. 대상이 스스로 들고 온 값을 기준으로 삼으면 맞춰 보는 의미가 없어지기 때문입니다.
검증이 없으면 생기는 일
검증은 믿을 수 있는 영역의 경계에 섭니다. 경계 안의 값은 이미 확인을 거쳤다고 봅니다. 확인하는 것은 경계 밖에서 들어온 값뿐입니다. 이 경계를 신뢰 경계라고 부릅니다.
경계에서 확인하지 않으면 틀린 값이 안쪽까지 들어갑니다. 형식이 어긋난 주문 번호가 데이터베이스까지 내려가 저장됩니다. 나중에 그 값을 읽는 코드가 전부 망가집니다. 들어오는 곳에서 막으면 안쪽 코드는 값을 믿고 씁니다.
캐시에서의 검증
캐시는 원본 응답의 사본을 보관했다가 다음 요청에 내줍니다. 문제는 원본이 바뀌어도 사본은 모른다는 점입니다. 그래서 사본을 내주기 전에 원본에게 「이 사본이 아직 맞나」를 묻습니다. 이 물음이 캐시에서 말하는 검증입니다.
물을 때는 사본을 받았을 때 함께 받은 표식을 보냅니다. 표식은 원본이 지금 어느 판인지 가리키는 짧은 값입니다. 판은 버전을 뜻합니다. 원본이 고쳐지면 판이 바뀌고 표식도 따라 바뀝니다.
HTTP(HyperText Transfer Protocol, 하이퍼텍스트 전송 프로토콜)는 표식으로 두 가지를 씁니다. 하나는 원본을 마지막으로 고친 시각입니다. 다른 하나는 ETag(entity tag, 엔티티 태그)로, 원본 서버가 판마다 붙이는 식별 문자열입니다. 이처럼 맞춰 보는 데 쓰는 표식을 검증자라고 합니다.
원본은 표식을 자기 현재 판과 맞춰 봅니다. 같으면 본문 없이 「안 바뀌었다」는 짧은 응답만 돌려줍니다. 캐시는 보관한 사본을 계속 씁니다. 다르면 새 응답을 통째로 보냅니다. 여기서 대상은 사본의 표식이고, 기준은 원본의 현재 판입니다.
sequenceDiagram
participant 캐시
participant 원본 as 원본 서버
캐시->>원본: 이 표식의 사본이 아직 맞나
Note over 원본: 표식을 현재 판과 맞춰 본다
alt 판이 같다
원본-->>캐시: 안 바뀌었다 · 본문 없음
else 판이 다르다
원본-->>캐시: 새 응답 · 본문 전체
end
이 방식의 이점은 본문을 다시 받지 않는다는 것입니다. 큰 응답일수록 오가는 양이 크게 줄어듭니다. 대신 원본까지 다녀오는 시간은 듭니다.
무효화는 이 검증과 이어집니다. 무효화는 사본을 지우거나, 지우지 않고 「다음에 내주기 전에 검증을 거쳐라」라고 표시해 둡니다. 뒤쪽을 고르면 사본이 남아 있어도 원본에게 물은 뒤에야 쓰입니다.
인증에서의 검증
인증은 상대가 「나는 누구다」라고 내세운 주장이 참인지 가리는 일입니다. 요청에는 주장만 실려 옵니다. 서버는 상대의 얼굴을 볼 수 없습니다. 그래서 주장과 함께 증거를 받아 맞춰 봅니다. 이 맞춰 보는 단계가 인증에서 말하는 검증입니다.
인증은 두 단계로 나뉩니다. 먼저 사용자 이름 같은 식별자를 내밀어 「누구라고 주장하는지」를 밝힙니다. 다음에 비밀번호나 전자 서명 같은 증거를 내밉니다. 서버는 그 증거가 그 식별자에 묶인 것인지 확인합니다. 두 번째 단계가 검증입니다.
검증하는 쪽은 증거 원본을 들고 있지 않아도 됩니다. 비밀번호라면 해시만 저장해 둡니다. 해시는 입력을 되돌릴 수 없게 뒤섞어 만든 짧은 값입니다. 받은 비밀번호를 같은 방식으로 해시해 저장한 값과 맞춰 봅니다. 여기서 대상은 받은 비밀번호이고, 기준은 저장한 해시입니다.
서명이라면 키가 한 쌍 필요합니다. 개인 키는 서명하는 사람만 가진 비밀 키입니다. 서명은 이 개인 키로 만듭니다.
확인에는 그 짝인 공개 키를 씁니다. 공개 키는 누구에게나 나눠 준 키입니다. 짝이 맞는 개인 키로 만든 서명만 이 키로 확인이 통과합니다. 그래서 검증하는 쪽은 개인 키를 몰라도 서명이 진짜인지 가릴 수 있습니다.
검증이 끝나면 「이 요청은 그 사람이 보냈다」는 것까지만 정해집니다. 그 사람이 이 작업을 해도 되는지는 인가가 따로 정합니다.
여러 분야에서 쓰는 검증
같은 뼈대가 다른 분야에서도 쓰입니다. 아래 표는 분야마다 대상과 기준에 무엇이 들어가는지만 보입니다. 각각이 어떻게 도는지는 그 항목이 따로 다룹니다.
| 이름 | 대상 | 기준 |
|---|---|---|
| 입력 검증 | 요청으로 들어온 값 | 형식 · 길이 · 허용 범위 규칙 |
| 스키마 검증 | JSON(JavaScript Object Notation) 같은 문서 | 스키마가 정한 구조 |
| 서명 검증 | 메시지와 붙어 온 서명 | 보낸 쪽의 공개 키 |
| 바이트코드 검증 | 불러온 클래스 파일 | 가상 머신이 정한 안전 규칙 |
표를 보면 대상과 기준만 바뀌고 「맞춰 보고 받아들이거나 거절한다」는 줄기는 같습니다. 그래서 분야가 달라도 같은 낱말로 부릅니다.
validation 과 verification
문서에서 「검증」을 만나면 원어를 확인하는 편이 안전합니다. 한국어 「검증」에는 영어 낱말 둘이 함께 옮겨지고, 분야마다 뜻이 갈리기 때문입니다. 두 낱말은 validation 과 verification 입니다.
앞의 캐시 소절이 다룬 검증은 validation 을 옮긴 것입니다. 인증 소절이 다룬 검증은 verification 을 옮긴 것입니다. 이 두 분야에서는 두 낱말이 이름만 다를 뿐, 둘 다 대상을 기준과 맞춰 보는 일입니다.
소프트웨어 품질 보증은 이와 다른 갈래로 둘을 가릅니다. verification 은 정해 둔 요구대로 만들었는지 확인하는 일입니다. validation 은 만든 것이 쓰려는 목적에 맞는지 확인하는 일입니다. 캐시·인증의 쓰임과 짝지어 읽으면 헷갈리니, 품질 보증 문서에서만 이 구분으로 읽습니다.
검증이 지는 대가
첫째, 시간이 듭니다. 캐시 검증은 원본까지 다녀옵니다. 인증 검증은 해시나 서명을 계산합니다. 비밀번호에는 일부러 느리게 만든 해시 함수를 쓰기도 합니다. 저장한 해시를 빼앗겼을 때 비밀번호를 하나씩 넣어 보는 공격을 늦추려는 것입니다. 이때는 로그인할 때의 비용도 함께 커집니다.
둘째, 기준을 들고 있어야 합니다. 저장한 해시, 공개 키, 스키마를 누군가 관리해야 합니다. 기준이 틀리면 검증도 틀린 답을 냅니다.
셋째, 기준이 보지 않는 것은 통과해도 모릅니다. 형식 검증을 통과한 주문 번호가 실제로 있는 주문인지는 형식 규칙이 알려 주지 않습니다.
넷째, 확인한 때와 쓰는 때 사이에 대상이 바뀔 수 있습니다. 파일을 확인한 직후 다른 프로세스가 그 파일을 바꾸면 확인 결과는 이미 낡은 것입니다. 이 틈을 노리는 문제를 TOCTOU(time-of-check to time-of-use, 확인 시점과 사용 시점의 틈)라고 부릅니다.
관련 항목
검증을 요구하는 상위 절차
인증 · 무효화 · 캐싱 · 신선도 · 조건부 요청 · 접근 제어 · 인증과 인가
검증에 쓰이는 기준값과 증거
검증자 · ETag · Last-Modified · 해시 · 전자 서명 · 공개 키 · 인증 수단 · 자격증명
분야마다 갈라진 검증의 하위 종류
입력 검증 · 스키마 검증 · 서명 검증 · 바이트코드 검증 · 재검증 · 인증서 검증
검증 뒤에 이어지는 단계
인가 · 304 Not Modified · 세션 · 액세스 토큰
검증에서 자주 나는 문제
TOCTOU · 재전송 공격 · SQL 인젝션 · 교차 사이트 스크립팅 · 낡은 데이터
검증과 헷갈리는 이웃 개념
검증과 확인 · 품질 보증 · 테스트 · 신뢰 경계
다른 이름: validation · verification