단언
단언은 참이라고 미리 적어 둔 진술입니다. 어떤 자리에서는 그 진술을 돌려서 참인지 판정합니다. 다른 자리에서는 그 진술에 서명해 다른 시스템으로 실어 보냅니다. 그래서 한쪽 뜻으로 꺼낸 말을 다른 쪽 뜻으로 알아듣는 일이 생깁니다.
상세
여러 정의가 나눠 갖는 뼈대는 하나입니다. 참이어야 할 조건을 사람이 미리 적어 둔다는 것입니다. 갈리는 자리는 적어 둔 그 진술을 무엇에 쓰느냐입니다.
한쪽에서 단언(assertion)은 돌려서 판정하는 검사입니다. Java 언어 명세는 단언을 불리언 식을 담은 assert 문이라고 적습니다. 단언은 활성이거나 비활성입니다. 활성이면 실행할 때 불리언 식을 평가합니다. 식이 거짓이면 오류를 보고합니다. 비활성이면 실행해도 아무 효과가 없습니다. POSIX(Portable Operating System Interface) 도 같은 자리에 섭니다. POSIX.1-2024 의 assert() 매크로는 프로그램에 진단을 끼워 넣습니다. 실행될 때 식이 거짓이면 실패한 호출에 대한 정보를 표준 오류로 씁니다. 그리고 abort() 를 부릅니다.
다른 쪽에서 단언은 실어 보내는 진술 묶음입니다. 아무것도 실행하지 않습니다. SAML(Security Assertion Markup Language, 보안 단언 마크업 언어) 2.0 기술 개요는 보안 정보가 이식 가능한 SAML 단언의 형태로 표현된다고 적습니다. 그 단언은 보안 도메인 경계를 넘어 일하는 애플리케이션이 신뢰할 수 있는 것입니다. 인증 정보와 속성 정보와 인가 정보를 기술하는 XML(Extensible Markup Language, 확장 가능 마크업 언어) 부호화 단언의 문법과 의미는 따로 정의되어 있습니다. RFC 7521 은 그 묶음에 서명이 붙는다고 적습니다. 발급자는 단언을 발급한 실체의 고유 식별자입니다. 대체로 단언에 서명하거나 무결성을 보호하는 데 쓰는 키 재료를 가진 쪽입니다.
flowchart TD
A["단언 — 참이라고 적어 둔 진술"] --> B["돌려서 판정한다"]
A --> C["서명해서 실어 보낸다"]
B --> D["테스트 러너가 실패로 기록"]
B --> E["프로그램이 abort · AssertionError"]
C --> F["다른 보안 도메인이 받아서 씀"]
같은 이름이 붙은 두 물건은 놓이는 자리가 다릅니다. 하나는 돌아가는 코드 안에 놓여 그 자리에서 판정됩니다. 다른 하나는 발급되어 다른 시스템으로 건너갑니다. 맥락 이름을 먼저 대야 어느 쪽 이야기인지 정해집니다.
맥락별 뜻
| 맥락 | 뜻 | 출처 |
|---|---|---|
| 자동화 테스트 | 기대한 값과 실제 값을 견주는 호출. 어긋나면 그 테스트가 실패로 기록됩니다 | Python 표준 라이브러리 unittest 문서 · JUnit 사용자 가이드 6.1.3 「Assertions」 |
| 프로그램 실행시간 검사 | 그 지점에서 참이어야 할 불리언 식. 거짓이면 오류를 알리고 프로그램을 멈춥니다 | Python 언어 참조 「The assert statement」 · POSIX.1-2024 assert() · Java 언어 명세 14.10 |
| 연합 신원 · 보안 | 발급자가 주체에 대해 적어 서명해서 다른 보안 도메인으로 보내는 진술 묶음 | SAML 2.0 Technical Overview · RFC 7521 |
자동화 테스트
Python 표준 라이브러리 문서는 무언가를 테스트하려면 TestCase 기반 클래스가 주는 assert 계열 메서드 중 하나를 쓴다고 적습니다. 테스트가 실패하면 설명 메시지를 담은 예외가 올라갑니다. unittest 는 그 테스트 케이스를 실패로 식별합니다. 그 밖의 예외는 오류로 다룹니다. 각 테스트의 핵심은 기대한 결과를 확인하는 assertEqual() 호출입니다. 조건을 확인할 때는 assertTrue() 나 assertFalse() 를 씁니다. 특정 예외가 올라오는지 확인할 때는 assertRaises() 를 씁니다.
이 맥락이 실행시간 검사와 갈리는 자리를 문서가 직접 적습니다. 이 메서드들을 assert 문 대신 쓰는 이유는 테스트 러너가 모든 테스트 결과를 모아 보고서를 낼 수 있게 하기 위해서입니다. 실패를 받는 쪽이 프로세스가 아니라 테스트 러너입니다. 이름이 test 로 시작하는 규칙도 어느 메서드가 테스트인지를 테스트 러너에게 알리는 장치입니다.
sequenceDiagram
participant 테스트
participant 단언메서드
participant 테스트러너
테스트->>단언메서드: assertEqual(a, b)
단언메서드-->>테스트러너: 어긋나면 설명 메시지를 담은 예외
Note over 테스트러너: 그 테스트 케이스를 실패로 식별
테스트러너->>테스트러너: 결과를 모아 보고서를 냄
assert 계열 메서드는 모두 msg 인자를 받습니다. 지정하면 실패했을 때 오류 메시지로 쓰입니다. JUnit Jupiter 도 같은 자리를 둡니다. 그 단언은 전부 org.junit.jupiter.api.Assertions 클래스의 정적 메서드입니다. 단언 메서드는 세 번째 파라미터로 단언 메시지를 받을 수 있습니다. String 이거나 Supplier
프로그램 실행시간 검사
Python 언어 참조는 assert 문을 프로그램에 디버깅용 단언을 끼워 넣는 편한 방법이라고 적습니다. assert expression 은 if __debug__: if not expression: raise AssertionError 와 같습니다. 확장형인 assert expression1, expression2 는 AssertionError 에 두 번째 식을 실어 올립니다. 현재 구현에서 __debug__ 는 보통 True 입니다. 명령줄 옵션 -O 로 최적화를 요청하면 False 가 됩니다. 문서는 한 걸음 더 나갑니다. 컴파일 시점에 최적화가 요청되면 현재 코드 생성기는 assert 문에 대해 아무 코드도 내보내지 않습니다.
C 쪽도 같습니다. POSIX.1-2024 는 assert() 가 표준 오류에 쓰는 정보에 무엇이 들어가는지까지 적습니다. 인자의 텍스트와 소스 파일 이름과 소스 파일 줄 번호와 감싼 함수 이름입니다. 각각 전처리 매크로 __FILE__ 과 __LINE__ 의 값이고 식별자 __func__ 의 값입니다. 컴파일러 명령줄이나 #include <assert.h> 앞의 #define NDEBUG 로 이름 NDEBUG 를 정의하면 단언은 프로그램에 컴파일되지 않습니다.
flowchart TD
A["assert(식)"] --> B{"단언이 켜져 있나"}
B -->|꺼짐 · NDEBUG · -O| C["아무 일도 일어나지 않음"]
B -->|켜짐| D{"식이 참인가"}
D -->|참| E["그대로 진행"]
D -->|거짓| F["오류를 알리고 멈춤"]
Java 언어 명세도 활성과 비활성이라는 같은 두 상태를 씁니다. 세 문서가 겹치는 대목은 하나입니다. 이 맥락의 단언은 켜져 있을 때만 실행됩니다.
연합 신원 · 보안
SAML 표준은 온라인 사업 파트너 사이에서 보안 정보를 기술하고 교환하는 XML 기반 프레임워크를 정의합니다. 그 보안 정보가 이식 가능한 SAML 단언의 형태로 표현됩니다. 표준은 단언을 요청하고 만들고 전달하고 사용하는 문법과 규칙을 정합니다. 대부분의 SAML 단언 한가운데에는 주체가 있습니다. 주체는 특정 보안 도메인 안에서 인증될 수 있는 실체를 뜻합니다. 사람일 수도 있고 회사나 컴퓨터 같은 다른 종류의 실체일 수도 있습니다.
문서가 든 전형적인 단언은 이런 정보를 나릅니다. 이 사용자는 John Doe 이고, 이메일 주소는 [email protected] 이고, 암호 방식으로 이 시스템에 인증되었다는 것입니다. 그 단언은 신원 제공자가 냅니다. 서비스 제공자는 자기 접근 정책에 따라 그 정보를 써서 로컬 자원에 대한 웹 SSO(Single Sign-On, 통합 인증) 접근을 허용할지 고를 수 있습니다.
sequenceDiagram
participant 신원제공자
participant 서비스제공자
Note over 신원제공자: 주체에 대한 진술을 XML 단언으로 만듦
신원제공자->>서비스제공자: 서명된 단언을 보안 도메인 경계 너머로 보냄
Note over 서비스제공자: 접근 정책에 따라 자원 접근을 판정
RFC 7521 은 이 진술 묶음을 OAuth 2.0 에서 쓰기 위한 프레임워크를 정합니다. 새로운 클라이언트 인증 방식과 새로운 인가 그랜트 타입의 형태입니다. 토큰 엔드포인트와 주고받는 동안 단언을 실어 나르는 방식과 일반 처리 규칙을 규정합니다. 이 문서에서 발급자는 단언을 발급한 실체의 고유 식별자입니다. 발급자의 예로 문서가 드는 것은 단언을 스스로 발급하는 OAuth 클라이언트와 제삼자 보안 토큰 서비스입니다.
경계
사용자 입력을 assert 로 검사하는 것
사용자가 넣은 값이 올바른지 assert 로 검사하는 것도 단언인가. 문법으로는 단언이 맞습니다. 다만 그 검사가 실행된다는 보장이 없습니다.
근거는 세 명세가 나란히 적습니다. Python 은 컴파일 시점에 최적화가 요청되면 assert 문에 대해 아무 코드도 내보내지 않습니다. C 는 NDEBUG 가 정의되어 있으면 단언 자체가 프로그램에 컴파일되지 않습니다. Java 에서 단언이 비활성이면 실행해도 아무 효과가 없습니다. 입력 검사를 단언에 두면 그 검사는 빌드 설정 하나로 통째로 사라집니다. 사라진 자리에 남는 것은 검사 없이 지나가는 코드입니다.
관련 항목
자동화 테스트에서 단언을 호출하는 메서드와 그 결과
assertEqual · assertTrue · assertFalse · assertRaises · 예외 · 메시지
자동화 테스트에서 단언을 실행·집계하는 도구와 역할
테스트 러너 · 테스트 케이스 · unittest · JUnit
자동화 테스트에서 단언 메시지를 늦게 계산하는 기법
지연 평가 · 람다식 · 성능
실행시간 검사를 정의하는 표준과 이를 켜고 끄는 조건
POSIX · 불리언 식 · __debug__ · NDEBUG · 컴파일러
실행시간 검사 실패 진단에 담기는 정보
AssertionError · abort · 표준 오류 · 전처리 매크로 · __FILE__ · __LINE__ · __func__
연합 신원에서 단언을 다루는 역할과 경계
신원 제공자 · 서비스 제공자 · 발급자 · 클레임 제공자 · 보안 토큰 서비스 · 보안 도메인 · 웹 SSO
연합 신원에서 단언을 정의하는 표준과 형식
연합 신원에서 단언이 실어 나르는 정보
연합 신원에서 단언의 신뢰를 보장하는 장치
서명 · 무결성 · 키 재료
OAuth 확장에서 단언이 오가는 통로
OAuth 2.0 · 토큰 엔드포인트 · 인가 그랜트
다른 이름: assertion · assert · 어서션