{
  "title": "언어 의미론: 정적 vs 실행",
  "description": "정적 의미론과 실행(동적) 의미론을 가르고, 작동적·표시적·공리적 의미론을 정리합니다. '그냥 의미론'이라 뭉뚱그릴 때 생기는 함정도 함께.",
  "languageCode": "ko",
  "cards": [
    {
      "type": "ox",
      "prompt": "정적 의미론(static semantics)은 프로그램을 실행하지 않고 컴파일 시점에 판정하는 규칙(타입 검사·스코프 규칙 등)을 다룬다.",
      "answer": true,
      "explanation": "정적 의미론은 '실행 전에 성립해야 하는 성질'을 규정합니다. 타입 검사가 대표적입니다."
    },
    {
      "type": "ox",
      "prompt": "실행 의미론(동적 의미론)은 프로그램이 실제 실행될 때의 동작(계산 결과·상태 변화 등)을 규정한다.",
      "answer": true,
      "explanation": "실행 의미론은 '프로그램이 돌 때 무슨 일이 일어나는가'를 정의합니다."
    },
    {
      "type": "choice",
      "prompt": "프로그램의 의미를 '추상 기계의 상태 전이(step)'로 정의하는 의미론은?",
      "choices": [
        "작동적 의미론(operational)",
        "표시적 의미론(denotational)",
        "공리적 의미론(axiomatic)",
        "정적 의미론"
      ],
      "answer": 1,
      "explanation": "작동적 의미론은 상태가 어떻게 한 단계씩 바뀌는지로 의미를 줍니다."
    },
    {
      "type": "choice",
      "prompt": "프로그램을 수학적 대상(예: 함수)으로 사상하여 의미를 부여하는 방식은?",
      "choices": [
        "표시적 의미론(denotational)",
        "작동적 의미론",
        "공리적 의미론",
        "어휘 분석"
      ],
      "answer": 1,
      "explanation": "표시적 의미론은 각 구문을 수학적 값/함수에 대응시킵니다."
    },
    {
      "type": "choice",
      "prompt": "사전조건/사후조건과 호어 논리(Hoare logic)로 프로그램의 성질을 다루는 의미론은?",
      "choices": [
        "공리적 의미론(axiomatic)",
        "작동적 의미론",
        "표시적 의미론",
        "정적 타이핑"
      ],
      "answer": 1,
      "explanation": "공리적 의미론은 {P} C {Q} 형태의 논리로 프로그램의 성질을 증명합니다."
    },
    {
      "type": "text",
      "prompt": "프로그램의 의미를 상태 전이 규칙으로 정의하는 의미론을 무엇이라 하는가?",
      "answers": [
        "작동적 의미론",
        "작동적",
        "operational semantics",
        "operational",
        "연산적 의미론"
      ],
      "explanation": "작동적(operational) 의미론입니다. small-step·big-step 두 형태가 있습니다."
    },
    {
      "type": "ox",
      "prompt": "small-step(구조적 작동) 의미론과 big-step(자연) 의미론은 모두 작동적 의미론의 형태다.",
      "answer": true,
      "explanation": "small-step은 한 걸음씩, big-step은 최종 결과로의 평가 관계로 의미를 줍니다. 둘 다 작동적입니다."
    },
    {
      "type": "ox",
      "prompt": "작동적·표시적·공리적 의미론은 서로 배타적이어서 한 언어에는 하나만 적용할 수 있다.",
      "answer": false,
      "explanation": "세 방식은 상호 보완적입니다. 같은 언어를 여러 방식으로 기술하고 서로 대응(적정성)을 증명하기도 합니다."
    },
    {
      "type": "ox",
      "prompt": "'그냥 의미론'이라고만 하면 정적 의미론까지 포함되므로, 정적 의미론에 존재 양화(∃)를 가진 언어가 매우 많아진다.",
      "answer": true,
      "explanation": "타입 추론·라이프타임 추론 등은 정적 의미론의 ∃입니다. 그래서 '실행 의미론'인지 명시하는 것이 중요합니다."
    },
    {
      "type": "ox",
      "prompt": "어떤 언어가 정적 의미론에서 존재 판정(∃)을 요구한다고 해서, 그 언어의 실행 의미론까지 선언형이 되는 것은 아니다.",
      "answer": true,
      "explanation": "정적 의미론의 ∃와 실행 의미론의 ∃는 다른 층위입니다. 분류를 논할 때 층위를 뒤섞으면 부정확해집니다."
    },
    {
      "type": "ox",
      "prompt": "정적 의미론과 실행 의미론을 구분하지 않으면 선언형/명령형 논의가 부정확해질 수 있다.",
      "answer": true,
      "explanation": "어느 층위의 ∃를 말하는지에 따라 결론이 달라지므로, 층위 구분은 이 논의의 출발점입니다."
    },
    {
      "type": "ox",
      "prompt": "타입 검사는 프로그램을 실제로 실행해야만 결과를 알 수 있으므로 실행 의미론에 속한다.",
      "answer": false,
      "explanation": "타입 검사는 실행 없이 컴파일 시점에 판정하는 정적 의미론의 성질입니다."
    },
    {
      "type": "ox",
      "prompt": "타입 안전성(type soundness)은 보통 진행(progress)과 보존(preservation) 두 정리를 합쳐 증명한다.",
      "answer": true,
      "explanation": "진행은 '잘-타입된 식은 값이거나 한 걸음 더 갈 수 있다', 보존은 '한 걸음 가도 타입이 유지된다'입니다. 둘을 합치면 잘-타입된 프로그램은 결코 막힌(stuck) 상태에 빠지지 않습니다."
    },
    {
      "type": "ox",
      "prompt": "big-step(자연) 의미론은 무한히 도는 프로그램과 오류로 막힌 프로그램을 자연스럽게 구별해준다.",
      "answer": false,
      "explanation": "big-step에서는 두 경우 모두 '평가 관계의 도출이 존재하지 않음'으로 뭉뚱그려집니다. 발산과 막힘(stuck)을 구분하려면 한 걸음씩 보는 small-step 의미론이 유리합니다."
    },
    {
      "type": "choice",
      "prompt": "표시적 의미론에서 재귀적으로 정의된 프로그램(while 루프·재귀 함수)에 의미를 부여하는 표준 도구는?",
      "choices": [
        "레지스터 할당",
        "꼬리 호출 최적화",
        "최소 고정점(least fixed point)",
        "어휘 분석"
      ],
      "answer": 3,
      "explanation": "재귀 정의는 어떤 함수의 방정식으로 표현되고, 그 해를 순서 구조 위의 최소 고정점으로 잡습니다. 이것이 표시적 의미론의 고전적 기법입니다."
    },
    {
      "type": "ox",
      "prompt": "표시적 의미론은 합성성(compositionality)을 원칙으로 삼아, 복합 구문의 의미를 그 부분 구문들의 의미만으로 정한다.",
      "answer": true,
      "explanation": "합성성 덕분에 부분식의 의미가 같으면 바꿔 끼워도 전체 의미가 같다는 추론이 가능해집니다. 이는 등식 추론과 최적화 정당화에 쓰입니다."
    },
    {
      "type": "ox",
      "prompt": "호어 삼중 {P} C {Q}의 부분 정확성(partial correctness) 해석은 C가 반드시 종료한다는 것까지 보장한다.",
      "answer": false,
      "explanation": "부분 정확성은 'C가 종료한다면 Q가 성립한다'만 말합니다. 종료성까지 요구하는 것은 총 정확성(total correctness)입니다."
    },
    {
      "type": "text",
      "prompt": "호어 논리로 반복문을 증명할 때, 반복 진입 전과 매 반복 후에 항상 성립하도록 잡는 성질을 무엇이라 하는가?",
      "answers": [
        "루프 불변식",
        "불변식",
        "반복 불변식",
        "loop invariant",
        "invariant"
      ],
      "explanation": "루프 불변식(loop invariant)입니다. 불변식이 유지되고 반복 조건이 거짓이 되면, 둘을 합쳐 사후조건을 이끌어냅니다."
    },
    {
      "type": "ox",
      "prompt": "보존(preservation, subject reduction) 정리는 잘-타입된 식이 한 걸음 계산된 뒤에도 같은 타입을 유지한다는 주장이다.",
      "answer": true,
      "explanation": "보존은 계산이 진행돼도 타입 판정이 무너지지 않음을 보장합니다. 그래서 귀납적으로 계산 전 구간에 걸쳐 타입이 유지됩니다."
    },
    {
      "type": "choice",
      "prompt": "진행(progress) 정리가 말하는 내용으로 옳은 것은?",
      "choices": [
        "잘-타입된 닫힌 식은 값이거나 한 걸음 더 계산할 수 있다",
        "잘-타입된 식은 반드시 유한 걸음 안에 종료한다",
        "모든 식은 유일한 타입을 가진다",
        "계산 결과의 타입은 계산 전보다 항상 구체적이 된다"
      ],
      "answer": 1,
      "explanation": "진행은 '잘-타입된 닫힌 식은 이미 값이거나, 아직 한 걸음 더 계산할 수 있다'입니다. 즉 값도 아니면서 멈춰버리는 상태가 없다는 뜻입니다."
    },
    {
      "type": "ox",
      "prompt": "타입 안전성이 증명된 언어에서는 0으로 나누기 같은 실행 시 오류가 전부 사라진다.",
      "answer": false,
      "explanation": "타입 안전성이 배제하는 것은 의미론이 정의하지 않는 '막힌' 상태입니다. 0 나누기처럼 의미론이 예외로 정의해 둔 동작은 여전히 실행 중에 일어날 수 있습니다."
    },
    {
      "type": "ox",
      "prompt": "small-step 의미론에서 평가 문맥(evaluation context)은 식의 어느 위치에서 다음 축약이 일어나는지를 지정하는 장치다.",
      "answer": true,
      "explanation": "평가 문맥은 '구멍이 하나 뚫린 식'으로, 계산 순서를 규칙 하나로 깔끔하게 규정합니다. 값 호출·이름 호출 같은 전략 차이도 문맥 정의로 표현됩니다."
    },
    {
      "type": "choice",
      "prompt": "최약 사전조건 wp(C, Q)의 정의로 옳은 것은?",
      "choices": [
        "C를 실행한 뒤 반드시 거짓이 되는 가장 강한 조건",
        "Q를 만족하는 상태의 개수",
        "C를 실행하면 Q가 성립하도록 보장하는 가장 약한 사전조건",
        "C가 종료하지 않을 필요충분조건"
      ],
      "answer": 3,
      "explanation": "wp(C, Q)는 'C를 실행하면 Q가 성립하도록 보장하는 사전조건들 중 가장 약한 것'입니다. 다익스트라의 술어 변환기(predicate transformer) 방식의 출발점입니다."
    },
    {
      "type": "ox",
      "prompt": "공리적 의미론의 목적은 프로그램의 최종 출력값을 계산해 주는 알고리즘을 제공하는 것이다.",
      "answer": false,
      "explanation": "공리적 의미론은 값을 계산하지 않고, 프로그램이 만족하는 성질을 논리 규칙으로 증명합니다. 값을 실제로 굴려 내는 쪽은 작동적 의미론입니다."
    },
    {
      "type": "ox",
      "prompt": "같은 언어에 작동적 의미론과 표시적 의미론을 각각 정의한 뒤, 두 의미가 서로 맞아떨어짐(적정성, adequacy)을 정리로 증명하는 연구가 있다.",
      "answer": true,
      "explanation": "적정성은 '표시적 의미가 같으면 관측 가능한 실행 결과도 같다'류의 대응을 말합니다. 이런 대응 증명 덕분에 세 의미론을 함께 쓸 수 있습니다."
    },
    {
      "type": "ox",
      "prompt": "정적 의미론의 규칙은 모두 문맥 자유 문법(CFG)으로 표현할 수 있다.",
      "answer": false,
      "explanation": "'변수는 사용 전에 선언되어야 한다' 같은 조건은 문맥 의존적이라 CFG로 잡히지 않습니다. 그래서 파서를 통과한 뒤 별도의 타입·스코프 검사 단계를 둡니다."
    },
    {
      "type": "choice",
      "prompt": "다음 중 정적 의미론이 아니라 실행(동적) 의미론에 속하는 것은?",
      "choices": [
        "함수 호출의 인자 개수가 선언과 일치하는지 검사",
        "식별자가 어느 선언을 가리키는지 결정하는 스코프 규칙",
        "덧셈 피연산자가 수치 타입인지 검사",
        "배열 인덱스가 실제 길이를 벗어났는지 확인"
      ],
      "answer": 4,
      "explanation": "배열 인덱스가 실제 길이를 넘었는지는 실행 중의 값에 달려 있어 동적으로 판정됩니다. 타입 검사·스코프 해석·인자 개수 검사는 실행 없이 결정되는 정적 성질입니다."
    },
    {
      "type": "ox",
      "prompt": "문법적으로 올바르게 파싱되는 프로그램이라도 정적 의미론 규칙을 어기면 컴파일에 실패할 수 있다.",
      "answer": true,
      "explanation": "구문(syntax)과 정적 의미론은 별개의 관문입니다. 파싱은 통과하지만 타입이 맞지 않아 거부되는 코드가 그 예입니다."
    },
    {
      "type": "text",
      "prompt": "호어 삼중 {P} C {Q}에서 명령 C를 실행하기 전에 성립해야 하는 P를 무엇이라 하는가?",
      "answers": [
        "사전조건",
        "선행조건",
        "precondition",
        "pre-condition"
      ],
      "explanation": "사전조건(precondition)입니다. 실행 후에 성립해야 하는 Q는 사후조건(postcondition)이라 부릅니다."
    },
    {
      "type": "ox",
      "prompt": "표시적 의미론은 종료하는 프로그램만 다룰 수 있고, 비종료(발산)에는 의미를 줄 수 없다.",
      "answer": false,
      "explanation": "발산은 보통 최소 원소 ⊥(bottom)으로 표시합니다. 정의역에 ⊥를 두어 부분 함수와 비종료를 정식으로 다룹니다."
    },
    {
      "type": "choice",
      "prompt": "small-step 의미론과 big-step 의미론의 차이를 가장 정확히 말한 것은?",
      "choices": [
        "small-step은 인터프리터용, big-step은 컴파일러용이라는 구현상의 구분이다",
        "small-step은 한 걸음 축약 관계를, big-step은 식에서 최종 값으로의 평가 관계를 정의한다",
        "small-step은 타입을 다루고 big-step은 값을 다룬다",
        "small-step은 정적 의미론, big-step은 실행 의미론이다"
      ],
      "answer": 2,
      "explanation": "small-step은 '한 걸음 축약' 관계를 정의하고 그것을 반복해 결과에 이릅니다. big-step은 식에서 최종 값으로 가는 평가 관계를 한 번에 정의합니다."
    },
    {
      "type": "ox",
      "prompt": "총 정확성(total correctness)은 부분 정확성에 종료성 증명을 더한 것이다.",
      "answer": true,
      "explanation": "총 정확성 = 부분 정확성 + 종료. 반복문의 종료는 보통 매 반복마다 줄어드는 감소 척도(variant)를 잡아 증명합니다."
    },
    {
      "type": "ox",
      "prompt": "호어 논리의 대입 규칙은 {P} x := E {P[E/x]} 형태로, 사후조건 쪽에 대입을 수행한다.",
      "answer": false,
      "explanation": "올바른 형태는 {Q[E/x]} x := E {Q}로, 대입은 사전조건 쪽에서 뒤로 계산됩니다. 그래서 호어 논리의 증명은 사후조건에서 앞으로 거슬러 올라가는 방식이 자연스럽습니다."
    },
    {
      "type": "choice",
      "prompt": "표시적 의미론의 값 영역에 두는 ⊥(bottom)이 뜻하는 것은?",
      "choices": [
        "정수 0에 해당하는 기본값",
        "타입 오류가 난 식의 타입",
        "비종료하거나 정의되지 않은 계산",
        "가장 많은 정보를 가진 최대 원소"
      ],
      "answer": 3,
      "explanation": "⊥는 '결과 없음', 즉 비종료하거나 정의되지 않은 계산을 나타내는 최소 원소입니다. 정보량 순서에서 가장 아래에 놓입니다."
    },
    {
      "type": "ox",
      "prompt": "진행·보존 정리는 정적 타입 규칙과 실행 의미론을 함께 놓아야 비로소 진술할 수 있다.",
      "answer": true,
      "explanation": "두 정리는 '타입 판정'과 '한 걸음 계산'을 잇는 주장이므로, 정적 의미론과 실행 의미론이 모두 형식적으로 정의되어 있어야 합니다. 타입 안전성이 두 층위를 연결하는 다리인 셈입니다."
    },
    {
      "type": "ox",
      "prompt": "일반적인 프로그래밍 언어에서 타입 검사를 통과했다면 그 프로그램의 종료도 보장된다.",
      "answer": false,
      "explanation": "재귀나 반복이 있는 실용 언어의 타입 검사는 종료를 보장하지 않습니다. 강한 정규화(모든 잘-타입된 항이 종료)는 단순 타입 람다 계산 같은 제한된 체계에서 성립하는 성질입니다."
    }
  ]
}
