콘텐츠로 바로가기

Program Correctness & Verification

소스 코드 레벨에서 프로그램이 명세대로 동작함을 수학적으로 입증하는 호어 논리와 루프 불변량, 그리고 정적 분석 기법을 통해 소프트웨어 무결성을 다루는 학습 노드입니다.

Article
M

Me

hyunyoun's Blog

mathematics-computing-logicmathematicscomputing-logiclogicformal-verificationprogram-correctnessverificationmath-logic9 min read

1. Overview

프로그램 정확성 검증(Program Correctness & Verification, PCV)은 내가 짠 코드 덩어리가 "입력 데이터에 대해 예상한 출력을 단 0.1%의 오차도 없이 뱉어내는가?"를 수만 번의 테스트 케이스 실행이 아닌, 단 한 장의 수학적 연역 논리로 완벽히 증명해 내는 '알고리즘 물리학'입니다.

학습자는 코드의 윗줄과 아랫줄 사이에 성립해야 하는 수학적 제약 조건(Pre-condition, Post-condition)을 명시하는 **호어 논리(Hoare Logic)**를 뜯어보고, while 루프가 도는 와중에도 절대 깨지지 않는 불변의 진리인 **루프 불변성(Loop Invariants)**의 수리적 역학을 해부합니다. 나아가 재귀(Recursion)나 무한 루프가 영원히 돌지 않고 반드시 종료(Termination)됨을 정렬(Well-founded) 관계로 증명하며, 미션 크리티컬(의료기기, 항공우주) 소프트웨어가 결함 제로를 보장하는 극한의 무결성 아키텍처 능력을 확보합니다.

2. Scope & Boundaries

In-Scope

  • 호어 논리 물리 (Hoare Mechanics): 사전 조건(Pre-condition, PP), 사후 조건(Post-condition, QQ), 호어 트리플(Hoare Triple, {P}C{Q}\{P\} C \{Q\}).
  • 공리적 의미론 (Axiomatic Semantics): 할당 공리(Assignment Axiom), 조건문 규칙(Conditional Rule), 시퀀스 합성 규칙(Composition Rule).
  • 루프의 수리적 해부 (Loop Physics): 루프 불변성(Loop Invariant, II), 유지성(Maintenance), 부분 정확성(Partial Correctness).
  • 종료성 증명 (Termination & Total Correctness): 부분 정확성 + 루프 종료(Termination) = 완전 정확성(Total Correctness), 바운드 함수(Bound Function), 정초 관계(Well-founded Relation).

Out-of-Scope

  • 시스템 아키텍처 단위의 동시성 증명: 스레드 2개가 경합을 벌일 때 발생하는 데드락 증명 \rightarrow 01-02-03. Formal Specifications & TLA+ 영역.
  • 화이트박스/블랙박스 유닛 테스트 기법: 경계값 분석(Boundary Value)이나 분기 커버리지(Branch Coverage) 같은 QA 기법 \rightarrow 09-04. QA & Quality Assurance 영역.

Boundaries

  • PCV vs. Testing (09-04): 소프트웨어 테스팅(09-04)이 "벌레(Bug)가 있는지 여기저기 찔러보는 귀납적 낚시"라면, PCV는 "이 웅덩이에는 애초에 벌레가 물리적으로 존재할 수 없음을 수식으로 못 박아버리는 연역적 결계"입니다.

3. Counterexample

  • 루프 불변성 누락의 배열 폭발 (Loop Boundary Fallacy): 이진 탐색(Binary Search) 코드를 짜면서 low <= high 루프 안의 mid = (low + high) / 2 계산식만 집중할 뿐, 매 반복(Iteration)마다 "찾고자 하는 값은 반드시 [low, high] 구간 내에 존재한다"는 루프 불변성(II)을 수학적으로 세우지 않는 행위. 오프 바이 원(Off-by-one, low = mid인지 low = mid + 1인지) 에러로 인해 배열 범위를 초과(Out of Bounds)하여 메모리 세그먼테이션 폴트가 터지는 건, 루프 진입 전/중/후의 불변성이 깨졌기 때문입니다.
  • 종료 조건 증명 부재 (Non-termination Fallacy): while(x != 0)이라는 루프를 짜놓고 xx가 홀수일 때 2를 빼고 짝수일 때 3을 더하는 짓을 하면서 루프가 알아서 언젠가 끝나겠지 착각하는 무지. 감소하는 바운드 함수(Bound Function)가 0을 향해 단조 감소(Monotonically Decreasing)함을 수리적으로 증명하지 않은 코드는, 우연히 조건이 빗맞을 경우 서버의 CPU 점유율을 100%로 쳐박는 무한 루프 폭탄이 됩니다.

4. Prerequisites

  • 명제 및 술어 논리 (Basic): 사전 조건과 사후 조건을 P(x)(y>0)P(x) \land (y > 0) 같은 술어 논리로 작성하고 조작해야 하므로 필수적입니다. (01-02-01 PPL)

5. Learning Map

Sequence Core Cluster Objective & Description Evidence (BoK)
1 Hoare Triples "입력이 P일 때, C 코드를 돌리면 무조건 Q가 된다"는 계약 주도 프로그래밍의 수학적 틀을 쥡니다. P1
2 Axiomatic Rules 변수에 값을 넣거나 if 분기를 탈 때 수학적 조건(Q)이 어떻게 역방향으로 쪼개지는지(WP) 뜯어봅니다. P5
3 Loop Invariants 수백만 번 도는 while 루프 속에서도 1스텝마다 절대 깨지지 않는 진리의 닻(Anchor)을 찾습니다. Industry
4 Total Correctness 루프가 영원히 돌지 않고 반드시 바닥(0)을 쳐서 끝난다는 종료 증명을 통해 완전 무결성을 달성합니다. Industry

6. Learning Topics

Basic

Core Topic 01: 호어 논리와 계약 주도 프로그래밍 (Hoare Triples)

  • Why to Learn: 함수 하나를 짜더라도 호출자가 보장해야 할 입력(Pre)과 내가 책임질 출력(Post)의 선을 수학적으로 긋기 위해서입니다.
  • What to Learn:
    • Concepts: 사전 조건(Pre-condition, PP), 사후 조건(Post-condition, QQ), 호어 트리플(Hoare Triple, {P}C{Q}\{P\} C \{Q\}).
    • Skills: 상태(State) 검증, 계약에 의한 설계(Design by Contract).
    • Tools: 코드 내 assert() 문.
    • Trade-offs: 모든 함수마다 {P}\{P\}{Q}\{Q\}를 주석이나 assert로 떡칠해야 하는 타이핑 피로도 vs 이 계약이 한 번만 잘 설정되면 런타임에 에러가 났을 때 누구의 잘못(호출자 vs 구현자)인지 0.1초 만에 밝혀지는 디버깅의 신속성.
  • How to Learn:
    • 1단계: {x>0}  y=x+1  {y>1}\{x > 0\} \; y = x + 1 \; \{y > 1\} 이라는 호어 트리플에서, xx가 양수라는 사전 조건이 코드 y = x + 1의 물리를 거쳐 yy가 1보다 크다는 완벽한 사후 조건으로 맵핑됨을 해부합니다.
    • 2단계: 사전 조건을 너무 느슨하게(Weak) 잡으면 함수 내부에서 예외 처리를 다 해줘야 하고, 너무 빡세게(Strong) 잡으면 함수 호출하기가 극도로 까다로워지는 아키텍처적 줄다리기를 뜯어봅니다.
  • Implement: 나눗셈 함수 div(a, b)를 구현할 때 맨 윗줄에 사전 조건 assert(b != 0)과 맨 아랫줄에 사후 조건 assert(result * b == a)를 박아넣어, 계약이 깨질 시 크래시를 내는 계약 주도 함수 작성.

Core Topic 02: 공리적 의미론과 가장 약한 사전 조건 (Axiomatic Rules & WP)

  • Why to Learn: 내가 원하는 결과(QQ)를 얻기 위해, 코드(CC) 진입 전에 변수들이 어떤 상태여야 하는지(PP)를 수학 공식으로 거꾸로 역산해 내기 위함입니다.
  • What to Learn:
    • Concepts: 할당 공리(Assignment Axiom), 가장 약한 사전 조건(Weakest Precondition, wp(C,Q)wp(C, Q)).
    • Skills: 조건문 규칙(if-else), 순차 합성 규칙(Sequence Composition).
    • Tools: 연역적 추론 시스템.
    • Trade-offs: 결과에서부터 거꾸로 역추적하여(Backward Chaining) 코드가 무조건 작동하는 최소한의 허들을 수학적으로 뽑아내는 우아함 vs 복잡한 객체 참조(Pointer)나 함수 호출이 끼어들면 수식이 뇌 용량을 초과해 버리는 연산 복잡도.
  • How to Learn:
    • 1단계: 사후 조건 Q:{x>5}Q: \{x > 5\}와 할당문 C:x=y+2C: x = y + 2가 주어졌을 때, xx 자리에 y+2y+2를 치환하여 가장 약한 사전 조건 wpwpy>3y > 3 임을 기계적으로 도출해 내는 할당 공리를 해부합니다.
    • 2단계: if (B) C1 else C2 구문의 wpwp를 계산할 때, (Bwp(C1,Q))(¬Bwp(C2,Q))(B \rightarrow wp(C1, Q)) \land (\lnot B \rightarrow wp(C2, Q))라는 무자비한 명제 논리로 분해하여 CPU 브랜치의 물리적 양면성을 수학으로 증명합니다.
  • Implement: 기호 연산 라이브러리(예: SymPy)를 이용해, 파이썬 할당문 문자열 "x = y + 2"와 사후 조건 수식 "x > 5"를 파싱한 뒤 역산하여 사전 조건 수식 "y > 3"을 뱉어내는 미니 WP 계산기 모듈 작성.

Practical

Core Topic 03: 루프 불변성과 부분 정확성 증명 (Loop Invariants)

  • Why to Learn: 수십만 번 반복되는 루프 안에서 iijj 인덱스가 미쳐 날뛰더라도, 내가 짠 코드가 절대 정렬을 흩트리거나 메모리를 터트리지 않음을 머릿속으로 증명하기 위해서입니다.
  • What to Learn:
    • Concepts: 루프 불변성(Loop Invariant, II), 부분 정확성(Partial Correctness).
    • Skills: 3단계 증명법(초기화 Initialization, 유지 Maintenance, 종료 증명 Termination/Post-condition).
    • Tools: 이진 탐색(Binary Search), 삽입 정렬(Insertion Sort) 알고리즘 분석.
    • Trade-offs: 어떤 강력한 불변성 공식을 찾아내기만 하면 루프 전체의 복잡도를 단 3줄의 귀납법으로 찌그러뜨리는 강력함 vs 정작 그 알맞은 불변성 식(II)을 기계가 자동으로 찾아주지 못하고 인간의 통찰력에 의존해야 하는 휴리스틱.
  • How to Learn:
    • 1단계: 배열의 원소를 다 더하는 루프에서 "현재 단계 kk까지 sumsum 변수 안에는 배열의 00부터 k1k-1까지의 합이 들어있다"라는 루프 불변성 II를 수립하고, 루프 한 바퀴(CC)를 돌았을 때 이 불변성이 유지됨({IB}C{I}\{I \land B\} C \{I\})을 뜯어봅니다.
    • 2단계: 루프가 종료되는 순간 조건 BB가 거짓이 되므로, I¬B    QI \land \lnot B \implies Q (최종 사후 조건)로 자연스럽게 연결되는 톱니바퀴 같은 수학적 증명 구조를 해부합니다.
  • Implement: 삽입 정렬(Insertion Sort) 1스텝마다 assert(is_sorted(arr[0:i])) 불변성 체크 함수를 강제로 박아넣어, 인덱스 오타로 인해 정렬이 깨지는 즉시 루프 불변성 위반 에러를 뿜게 하는 방어적 정렬 코드 작성.

Advanced

Core Topic 04: 종료성 증명과 완전 정확성 (Termination & Total Correctness)

  • Why to Learn: 내 알고리즘이 "만약 끝난다면 올바른 답을 낸다(부분 정확성)"는 변명에서 벗어나, "무조건 끝난다(종료성)"는 것을 합쳐 시스템 멈춤(Hang)의 공포를 완전히 소거하기 위함입니다.
  • What to Learn:
    • Concepts: 완전 정확성(Total Correctness = Partial Correctness + Termination).
    • Skills: 바운드 함수(Bound Function / Variant), 정초 관계(Well-founded Relation, 무한히 작아지지 않는 집합).
    • Tools: Halting Problem 한계 이해.
    • Trade-offs: while(true) 형태의 무한 대기 서버 로직에서는 종료성 증명이 의미가 없고 Safety(죽지 않음)만 중요한 비동기 패러다임 vs 반드시 유한한 시간 안에 답을 내고 죽어야 하는 배치 데이터 파이프라인(Batch Algorithm)에서의 완벽한 종료 보장.
  • How to Learn:
    • 1단계: 정수 NN에서 시작해 루프를 돌 때마다 NN이 반드시 1 이상 감소하고, N=0N=0이 되면 루프를 탈출하는 바운드 함수 V(N)V(N)을 설정하여 "정수는 무한히 쪼개질 수 없으므로 무조건 끝난다"는 정초성의 물리를 뜯어봅니다.
    • 2단계: 앨런 튜링의 '정지 문제(Halting Problem)' 증명을 통해, 임의의 프로그램이 멈출지 안 멈출지를 100% 알아내는 범용 알고리즘은 수학적으로 불가능하며, 인간 아키텍트가 직접 각 코드마다 바운드 함수를 짜내야만 하는 철학적 한계를 분석합니다.
  • Implement: 재귀 깊이(Recursion Depth)나 루프 변수(Iteration Count)가 루프마다 단조 감소(Monotonically Decreasing)하는지 런타임에 추적하여, 값이 커지거나 변동이 없으면 무한 루프 가능성 폭발(Infinite Loop Panic)을 던지는 디버깅 트레이서 구현.

7. Terminology

Term (EN / ko, abbr) 1문장 정의 단계(기본/권장/실무/심화) 역할/맥락 관련 개념 유사/대비/함께 사용 오해 포인트 Evidence(Primary/Secondary/Industry) Flags(core)
Post-condition (사후조건) 명령어가 성공적으로 실행된 직후 시스템이 반드시 만족해야 하는 상태 물리입니다. 기본 결과 보장 Pre-condition Triple '리턴 값'으로만 오해 P1:CS2023/BasicLogic core
Loop Invariant (루프불변량) 반복문이 실행되는 도중과 종료 직후에 항상 유지되어야 하는 핵심 논리입니다. 추천 반복 무결성 Induction Assertion '고정된 값'과 혼동 P1:CS2023/BasicLogic core
Symbolic Execution 입력을 기호로 처리하여 프로그램의 모든 가능한 실행 경로를 수학적으로 탐색하는 기술입니다. 실무 자동 검증 SAT Solver Testing '심볼 검색'과 혼동 Industry analysis core
Total Correctness 프로그램의 로직이 맞을 뿐만 아니라, 반드시 유한 시간 내에 끝남까지 보장된 상태입니다. 심화 절대 신뢰 Termination Liveness 단순히 '에러 없음'으로 오해 P1:CS2023/BasicLogic core

8. References

Primary

Secondary

  • [The Science of Programming] David Gries — Classic text on Hoare logic.
  • [Formal Methods for Software Engineering] — Modern approach to PCV tools.

Industry

  • [MISRA C Standards] — Correctness-focused coding rules for safety-critical.
  • [Static Analysis Security Testing (SAST) Guides] — PCV in modern DevSecOps.

9. Final Checklist

Primary

  • 주어진 코드 한 줄과 그 사후조건을 바탕으로, 해당 등식이 성립하기 위해 필요한 사전조건을 '호어 트리플' 규칙에 따라 유도 가능한가? (P1)
  • 특정 루프 로직에서 불변량(Invariant)이 초기화 단계에서는 맞지만 유지 단계에서 깨지는 사례를 찾아 논리적 오류를 지적할 수 있는 가? (P1)

Secondary

  • '부분 정당성' 증명이 '완전 정당성'으로 격상되기 위해 순위 함수(Ranking Function)가 물리적으로 어떤 역할을 수행해야 하는지 설명 가능한가?
  • 정적 분석 도구가 잡아내는 'Potential Null Pointer' 오류가 PCV의 사전조건(Pre-condition) 검증과 어떻게 수학적으로 연결되는지 소통 가능한가?

Industry

  • 항공우주나 의료용 소프트웨어와 같은 고신뢰 시스템 설계 시, 코드 작성 전 불변 조건을 먼저 설계하여 런타임 치명 결함을 0%로 수렴시키는 전략을 제안할 수 있는 가? (SFIA)
  • 코드 리뷰 과정에서 주관적인 의견이 아닌, 호어 논리 기반의 데이터 흐름 분석을 통해 잠재적 엣지 케이스 버그를 수학적으로 증명하고 설득할 수 있는 가?

Math Logic / Logic & Formal Verification

5 / 5