5장 생성 코드 읽기 I: 코드를 말로 설명하기
이번 주의 도구: ④ 단위환산 + 물성 조회기
다음 상황을 생각해 보자. 유체역학 과제에 물의 밀도가 필요한 한 학생이 AI에게 물어 즉시 답을 받았고, 압력 단위를 psi에서 kPa로 바꾸는 코드도 AI가 10초 만에 만들어 주었다. 실행하니 숫자가 나왔고, 과제는 제출되었다. 그런데 검토 시간에 조교가 화면의 세 번째 줄을 가리키며 물었다. "이 줄은 무엇을 하는 겁니까?"
학생은 대답하지 못했다. 코드는 돌아갔지만, 그 코드가 압력을 곱하는지 나누는지, 어느 줄에서 단위가 바뀌는지 설명할 수 없었다. 돌아가는 코드와 이해한 코드는 다르다. 이 장은 그 간극을 메우는 기술, 곧 코드를 말로 설명하는 훈련을 다룬다.
이 장에서 다루는 것
- 코드를 자연어로 설명하는 EiPE 훈련법을 도입한다
- 변수·조건문·반복문·함수를 '읽기의 눈'으로 해부한다
- 리스트와 딕셔너리를 물성 데이터를 담는 최소 수준으로 다룬다
- CoolProp으로 물성을 조회하고 NIST 값과 대조하는 첫 화공 도구를 만든다
- 첫 30분 타이머와 공개 구술을 시작한다(마음의 준비를 포함해)
학습목표: 이 장을 마치면 다음을 할 수 있다
- AI가 생성한 코드의 목적·입력·처리·출력·한계를 한국어 2~3문장으로 설명할 수 있다.
- 변수 상태표를 그려 코드 실행을 한 줄씩 추적할 수 있다.
- 조건문과 반복문이 만드는 실행 경로를 읽고 출력을 예측할 수 있다.
- 함수의 첫 줄(시그니처)에서 입력과 출력의 계약을 읽어낼 수 있다.
- CoolProp 조회값과 NIST 대조값으로 AI가 제시한 물성·상수의 날조 여부를 판정할 수 있다.
- 30분 제한시간 안에서 커밋 규정을 지키며 작은 도구 하나를 완성할 수 있다.
이번 주 실습에서는 5.2~5.4절의 읽기 기술로 도구④ 단위환산 + 물성 조회기를 만든다. 이번 주부터 타이머(30분)와 공개 지목 구술이 시작된다. 매주 실습은 최종 시험의 축소판이며, 이번 주가 그 첫 리허설이다.
5.1 코드를 말로 설명한다는 것: EiPE
1주차의 역할 분담을 다시 꺼내자. 코드는 AI가 쓰고, 학생은 문제 분해·생성 코드 읽기·화학공학적 검증을 책임진다. 이 분담에서 "읽기"는 채점 대상이다. 최종 시험 루브릭의 코드 이해 10점은 무작위 지목 설명 4점, "이 줄을 바꾸면?" 예측 3점, 한계·개선점 3점으로 구성되고, 지목 질문 3개 중 2개 이상 설명에 실패하면 이 차원 전체가 0점이다.
코드 한 조각의 목적과 동작을 자연어로 설명하는 훈련을 EiPE(Explain in Plain English)라 한다. 컴퓨팅 교육 연구에서 코드 이해도를 측정하는 표준 문항 유형으로 쓰여 왔고, 이 수업에서는 시험1의 서술 문항과 매주 구술의 공통 형식이다. 프로그래밍 초보자가 LLM이 생성한 코드를 올바르게 이해하는 비율이 32.5%에 그쳤다는 보고(arXiv 2504.19037)가 있다. 셋 중 둘은 돌아가는 코드를 설명하지 못한 채 제출한다는 뜻이다.
- 문제 정의
- 분해
- 프롬프트
- 생성 코드 읽기
- 테스트
- 화공 검증
5.1.1 라인 낭독과 설명은 다르다
다음 함수를 보자. mmHg 단위의 압력을 bar로 바꾸는, AI가 생성했을 법한 네 줄짜리 코드다.
def mmhg_to_bar(p_mmhg):
"""mmHg 단위 압력을 bar로 환산한다."""
p_pa = p_mmhg * 133.322 # 압력 [Pa], 1 mmHg = 133.322 Pa
return p_pa / 1.0e5 # 압력 [bar], 1 bar = 1e5 Pa
이 코드에 대한 두 가지 설명을 비교해 보자.
나쁜 설명(라인 낭독): "p_mmhg에 133.322를 곱해서 p_pa에 넣고, p_pa를 1.0e5로 나눠서 반환한다."
좋은 설명(EiPE): "mmHg 단위의 압력을 받아 bar 단위로 바꿔 돌려주는 함수다. 중간에 Pa를 한 번 거쳐 두 단계로 환산한다. 음수 압력 같은 비물리적 입력은 걸러내지 않는다."
나쁜 설명은 코드를 소리 내어 읽었을 뿐이어서, 코드를 보지 않은 사람에게는 정보를 거의 주지 못한다. 좋은 설명은 코드 없이도 이 함수를 다시 만들 수 있을 만큼의 정보를 담는다. 무엇을 받아 무엇을 돌려주는지, 어떤 경로로 바꾸는지, 어떤 한계를 안고 있는지가 여기에 들어간다. 시험1의 EiPE 문항과 구술 평가의 지목 질문이 요구하는 것은 후자다.
좋은 설명에는 뼈대가 있다. 목적("무엇을 하는 함수인가"), 입력("무엇을, 어떤 단위로 받는가"), 처리("어떤 경로로 바꾸는가"), 출력("무엇을, 어떤 단위로 돌려주는가"), 한계("어떤 입력에서 무너지는가")의 다섯 요소다. 다섯 요소를 전부 갖추면 두세 문장이 된다. 이 공식은 장 끝의 요약에 S 5-1로 다시 나온다.
읽기가 쓰기보다 먼저인 이유는 이 수업의 구조 자체에 있다. 쓰기는 AI가 대신하지만, AI가 쓴 것이 맞는지 판정하는 읽기는 사람의 몫으로 남는다. 프로그래밍 문법을 다 배운 뒤에 읽기를 시작하지 않고, 읽기에 필요한 최소 문법(변수, 제어문, 함수)만을 이번 장에서 골라 배운다.
스스로 점검
- "p_pa를 1.0e5로 나눈다"는 문장은 EiPE 다섯 요소 중 무엇을 빠뜨리고 있는가?
- 최종 시험에서 지목 질문 3개 중 2개를 설명하지 못하면 코드 이해 차원의 점수는 몇 점인가?
5.2 변수 읽기: 이름, 값, 그리고 단위
값을 가리키는 이름을 변수(variable)라 한다. 코드를 읽는 일은 결국 각 변수가 어느 시점에 어떤 값을 가리키는지 따라가는 일이다. 아래 네 줄을 보자.
p_mmhg = 800.0 # 측정 압력 [mmHg]
PA_PER_MMHG = 133.322 # 환산계수 [Pa/mmHg]
p_pa = p_mmhg * PA_PER_MMHG # 압력 [Pa]
p_bar = p_pa / 1.0e5 # 압력 [bar], 1 bar = 1e5 Pa
print(f"{p_bar:.4f} bar") # 출력: 1.0666 bar
첫 줄은 p_mmhg라는 이름에 800.0이라는 값을 묶는다. 이런 문장을 할당(assignment)이라 한다. 둘째 줄의 PA_PER_MMHG는 환산계수를 담은 변수인데, 대문자 이름은 "이 값은 바꾸지 않겠다"는 관례적 신호다. 셋째 줄에서 곱셈이 일어나 새 변수 p_pa가 생기고, 넷째 줄에서 다시 p_bar가 생긴다.
실행 순서를 따라 변수의 값을 표로 적는 일을 상태 추적(tracing)이라 한다. 위 코드의 상태표는 다음과 같다.
| 실행 줄 | p_mmhg | p_pa | p_bar |
|---|---|---|---|
| 1행 후 | 800.0 | — | — |
| 3행 후 | 800.0 | 106657.6 | — |
| 4행 후 | 800.0 | 106657.6 | 1.0666 |
화공 코드의 변수에는 프로그래밍 교재에 없는 규율이 하나 더 붙는다. 물리량 변수에는 반드시 단위 주석을 단다는 규율이다. p = 800.0이라고만 적힌 코드에서 800이 mmHg인지 kPa인지 psi인지는 코드 어디에도 없다. 단위가 주석에 있어야 검증 루틴의 첫 항목인 단위 체크가 가능해진다.
단위를 추적하면 코드가 틀린 것도 잡아낸다. 단위환산 교재의 고전적 실수 사례를 코드로 옮겨 보자.
p_mmhg = 800.0 # 압력 [mmHg]
p_wrong = p_mmhg * 760.0 / 1.013 # 잘못된 환산: 단위가 [mmHg²/bar]가 된다
print(p_wrong) # 600197.4... — 비물리적 크기
환산계수 "1 atm = 760 mmHg = 1.013 bar"를 거꾸로 곱하면 값이 6.0×10⁵라는 터무니없는 크기가 되고, 단위는 mmHg²/bar라는 존재하지 않는 조합이 된다. 값을 보고 이상함을 느끼는 것이 극한값 감각이고, 단위를 적어 보고 오류를 확정하는 것이 단위 체크다. 3장에서 도입한 검증 루틴 3종이 코드 읽기에서 그대로 작동한다.
예제 5.2-1 생성 코드의 상태 추적과 EiPE 설명
문제 AI가 생성한 아래 코드 5-4를 실행하지 않고 읽어라. ① 변수 상태표를 만들고 ② 최종 출력을 예측한 뒤 ③ 코드 전체를 EiPE 다섯 요소로 2~3문장 설명하라.
풀이 전략 코드 생성은 이미 AI가 했으므로, 여기서 사람의 일은 읽기다. 위에서 아래로 한 줄씩 상태표를 채우고, 각 변수의 단위 주석을 따라가며 최종 단위를 확인한다.
t_f = 212.0 # 온도 [°F]
t_c = (t_f - 32.0) * 5 / 9 # 온도 [°C]
t_k = t_c + 273.15 # 온도 [K]
print(f"{t_k} K")
상태표를 채우면 t_f = 212.0 → t_c = 100.0 → t_k = 373.15가 되고, 출력은 373.15 K다. EiPE 설명은 이렇게 된다. "화씨 온도를 받아 섭씨를 거쳐 켈빈으로 바꿔 출력하는 스크립트다. 입력 212 °F는 코드에 박혀 있어 다른 온도를 쓰려면 첫 줄을 고쳐야 한다. 절대영도 아래의 비물리적 입력도 그대로 계산한다."
검증 루틴 3종
- 단위 체크: °F → °C → K로 각 줄의 주석과 수식이 일치한다.
- 대조값: 212 °F는 1 atm에서 물이 끓는 온도다. NIST WebBook의 물 끓는점 373.17 ± 0.04 K와 계산값 373.15 K가 부합한다.
- 극한값: t_f = 32.0을 넣으면 273.15 K(물의 어는점)가 나와야 한다. 손계산으로 확인된다.
분석 세 변수가 하나의 물리량(온도)을 단위만 바꿔 차례로 넘기는 구조다. 상태표 한 장이면 실행 없이도 출력을 확정할 수 있고, 이것이 시험1의 출력 예측 문항이 요구하는 능력이다. 코드 5-4의 첫 줄을 t_f = -500.0으로 바꿔 다시 추적해 보라. 코드는 절대영도 아래 온도도 그대로 출력하며, 이 한계가 5.3절의 조건문이 필요한 이유다.
스스로 점검
- 코드 5-2에서
p_pa의 단위는 코드의 어느 부분에서 결정되는가? - 코드 5-4에서
t_f = 32.0이면 출력은 무엇인가?
5.3 제어문 읽기: 갈림길과 반복
지금까지의 코드는 위에서 아래로 한 번씩만 실행됐다. 그러나 실제 코드는 "이 조건이 참이면 이것을 하고, 아니면 저것을 하라", "이 목록의 항목마다 같은 일을 반복하라" 같은 문장으로 흐름을 바꾼다. 조건에 따라 실행 경로를 가르는 문장을 조건문(conditional statement)이라 하고, 같은 블록을 여러 번 실행시키는 문장을 반복문(loop)이라 한다.
화공 도구에서 조건문의 첫 임무는 유효범위 검사다. 물성 상관식의 상수에는 반드시 유효 온도범위가 붙어 있고, 범위 밖의 온도로 값을 구하는 일을 외삽(extrapolation)이라 한다. 외삽을 조용히 허용하는 코드는 위험하므로, 좋은 도구는 계산 전에 범위를 검사한다.
t = 298.15 # 조회 온도 [K]
t_min, t_max = 379.0, 573.0 # 상수 유효범위 [K], NIST(Liu and Lindsay)
if t < t_min or t > t_max:
print("경고: 유효범위 밖 — 외삽 결과는 신뢰할 수 없다")
else:
print("유효범위 안")
if 다음의 t < t_min or t > t_max는 참 또는 거짓으로 계산되는 식이다. 참이면 바로 아래 들여쓰인 블록이 실행되고, 거짓이면 else 블록이 실행된다. 여기서는 298.15가 379보다 작으므로 조건이 참이 되어 경고가 출력된다. 들여쓰기가 곧 소속을 나타낸다. 어떤 줄이 어느 블록에 속하는지는 들여쓰기 깊이가 결정한다.
반복문은 같은 계산을 목록 전체에 적용한다. 여러 값을 순서대로 담는 자료형을 리스트(list)라 하며, 대괄호로 만든다.
pressures_psi = [10.0, 14.7, 30.0, 100.0] # 압력 목록 [psi]
KPA_PER_PSI = 6.895 # 환산계수 [kPa/psi]
for p in pressures_psi:
print(f"{p:6.1f} psi = {p * KPA_PER_PSI:8.1f} kPa")
for p in pressures_psi:는 리스트의 항목을 하나씩 꺼내 p에 담고, 들여쓰인 블록을 항목 수만큼(여기서는 네 번) 실행한다. 둘째 항목 14.7 psi는 101.4 kPa로 환산되는데, 이는 1 atm(101.325 kPa)과 거의 같다. 표 하나를 출력했을 뿐인데 대조값 검증이 공짜로 따라온 셈이다.
실행 흐름을 읽는 요령은 "다음에 실행될 줄이 몇 번째 줄인가"를 계속 자문하는 것이다. 조건문에서는 어느 가지로 가는지, 반복문에서는 몇 바퀴째인지를 상태표 옆에 함께 적으면 된다. 흐름 추적은 유용하지만 코드가 길어지면 금세 벅차진다. 그때 필요한 것이 다음 절의 함수 단위 읽기다.
예제 5.3-1 온도 구간별 상수 선택 코드의 출력 예측
문제 아래 코드 5-7은 조회 온도에 따라 물의 Antoine 상수 묶음을 골라 증기압을 계산한다. T = 320 K일 때 ① 어느 가지가 실행되는지 ② 출력이 대략 얼마인지 예측하고 ③ 이 코드의 한계를 한 문장으로 말하라. 상수는 표 5-2에서 왔다.
풀이 전략 조건문 읽기의 정석대로 위에서부터 조건식을 하나씩 평가한다. 320이 각 구간에 속하는지만 판정하면 가지가 정해지고, 나머지는 변수 추적이다.
t = 320.0 # 조회 온도 [K]
# 물의 Antoine 상수 (log10, p*[bar], T[K]) — 표 5-2, NIST WebBook
if 273.0 <= t <= 303.0:
a, b, c = 5.40221, 1838.675, -31.737
elif 304.0 <= t <= 333.0:
a, b, c = 5.20389, 1733.926, -39.485
elif 334.0 <= t <= 363.0:
a, b, c = 5.07680, 1659.793, -45.854
else:
raise ValueError("유효범위 밖 온도")
p_bar = 10 ** (a - b / (t + c)) # 증기압 [bar]
print(f"{p_bar:.3f} bar")
320은 첫 구간(273~303)에 속하지 않고 둘째 구간(304~333)에 속하므로 둘째 가지가 실행된다. 손계산으로 10^(5.20389 − 1733.926/280.515) ≈ 0.105 bar를 얻는다.
검증 루틴 3종
- 단위 체크: 상수 묶음이 bar·K 기준(log₁₀)임이 주석에 명시되어 있고, t의 단위 K와 일치한다.
- 대조값: 320 K(약 47 °C)의 물은 끓지 않으므로 증기압은 1 atm(1.013 bar)보다 훨씬 작아야 한다. 0.105 bar는 이 상식과 부합한다.
- 극한값: t = 380.0을 넣으면 세 구간 어디에도 속하지 않아 ValueError가 발생한다. 외삽을 조용히 허용하지 않는 설계다.
분석 조건문 읽기의 핵심 질문은 "이 입력이면 어느 가지인가"와 "어느 가지에도 안 걸리면 무슨 일이 나는가"의 두 개다. 이 코드는 범위 밖에서 에러를 일으키도록 마지막 else를 두었는데, AI가 생성한 코드에는 이 안전망이 빠져 있는 경우가 잦다. t = 340.0과 t = 365.0으로 바꿔 각각 어느 가지로 가는지 예측한 뒤 실행으로 확인해 보라.
| 유효범위 [K] | A | B | C | 원자료 |
|---|---|---|---|---|
| 273~303 | 5.40221 | 1838.675 | −31.737 | Bridgeman and Aldrich (1964) |
| 304~333 | 5.20389 | 1733.926 | −39.485 | Bridgeman and Aldrich (1964) |
| 334~363 | 5.07680 | 1659.793 | −45.854 | Bridgeman and Aldrich (1964) |
| 379~573 | 3.55959 | 643.748 | −198.043 | Liu and Lindsay (1970) |
표 5-2에는 이 교재의 상수 표기 의무 네 가지(로그 밑, 압력 단위, 온도 단위, 유효범위)가 전부 들어 있다. 넷 중 하나라도 빠진 상수 표는 쓰지 않는다. 마지막 행의 상수를 유효범위 아래인 373 K에 적용하면 0.76 bar가 나오는데, 물이 1 atm(1.013 bar)에서 끓는다는 상식과 25% 어긋난다. 외삽의 대가는 8장에서 정량적으로 다룬다.
스스로 점검
- 코드 5-7에서 t = 273.0이면 어느 가지가 실행되는가? t = 272.9라면?
- 코드 5-6의 반복 횟수를 결정하는 것은 코드의 어느 부분인가?
5.4 함수 읽기: 입력·변환·출력의 계약
이름을 붙여 두고 필요할 때마다 불러 쓰는 코드 묶음을 함수(function)라 한다. 함수에 넘겨주는 값을 인자(argument), 함수가 돌려주는 값을 반환값(return value)이라 한다. 함수의 첫 줄(이름과 인자 목록)은 "무엇을 주면 무엇을 돌려주겠다"는 계약서이고, 함수 읽기는 이 계약서 읽기에서 시작한다.
def mmhg_to_bar(p_mmhg):이라는 첫 줄만 보고도 세 가지를 읽어낼 수 있다. mmHg를 bar로 바꾸는 일을 하고, 압력 하나를 받으며, 이름의 방향(mmhg→bar)이 환산 방향을 약속한다. 본문을 읽기 전에 계약부터 읽는 습관은 코드가 길어질수록 도움이 된다. 흐름 추적이 벅찬 큰 코드도 함수 단위로 끊으면 계약들의 연결로 읽힌다.
실제로 AI에게 함수를 시키고 그 결과를 읽어 보자. 프롬프트-응답 리스팅의 3단 형식은 2장에서 선언한 그대로다.
압력을 psi에서 kPa로 바꾸는 파이썬 함수를 만들어 줘. 함수 이름은 psi_to_kpa, 주석은 한국어로, 환산계수에 단위 주석을 달아 줘.
def psi_to_kpa(p_psi):
"""psi 단위 압력을 kPa로 환산한다."""
KPA_PER_PSI = 6.895 # 환산계수 [kPa/psi]
return p_psi * KPA_PER_PSI # 압력 [kPa]
✔ 환산계수 6.895 kPa/psi가 화공양론 교재의 값과 일치. psi_to_kpa(14.7) → 101.36 kPa로 1 atm(101.325 kPa)과 부합한다(대조값 통과). 다만 음수 압력을 거르지 않으므로 유효성 검사를 다음 프롬프트에서 추가 요구했다.
검증 코멘트가 짚은 대로, 생성된 함수는 계약을 지키지만 비물리적 입력에 침묵한다. "절대압이 음수면 ValueError를 일으켜 줘"라고 한 줄 더 요구하면 5.3절의 조건문이 함수 안으로 들어온다. 프롬프트 → 읽기 → 결함 발견 → 프롬프트 개선의 사이클이 한 바퀴 돈 것이다.
5.4.1 딕셔너리: 이름으로 값을 꺼내는 상자
물성 조회기는 밀도·끓는점처럼 여러 값을 한꺼번에 다룬다. 이름표(키)로 값을 꺼내는 자료형을 딕셔너리(dictionary)라 하며, 중괄호로 만든다.
props = {"T_boil_K": 373.12, "rho_kg_m3": 997.0} # 물성 이름 → 값
print(props["T_boil_K"]) # 키로 조회: 373.12
리스트가 순서(0번째, 1번째)로 값을 꺼낸다면 딕셔너리는 이름으로 꺼낸다. props["rho_kg_m3"]처럼 키에 단위를 새겨 두는 것도 단위 주석 규율의 연장이다. 이 장에서 리스트와 딕셔너리는 여기까지만 필요하다. 항목을 담고, 꺼내고, 반복문으로 순회하는 수준이면 도구④를 읽고 만들 수 있다.
5.4.2 CoolProp: 물성을 조회하는 함수 라이브러리
물성값 자체를 AI에게 묻는 것은 위험하다는 사실을 3장에서 보았다. 대안은 검증된 물성 라이브러리를 코드로 조회하는 것이다. CoolProp은 순수 유체의 열역학 물성을 계산해 주는 오픈소스 라이브러리로, PropsSI 함수 하나로 대부분의 조회가 끝난다.
예제 5.4-1 CoolProp 물성 조회 함수 만들기와 검증
문제 압력을 받아 물의 끓는점을 돌려주는 함수를 AI로 생성하고, 1 atm에서의 반환값을 NIST 대조값으로 검증하라.
풀이 전략 함수 생성은 AI에게 맡기고("CoolProp의 PropsSI로 압력[Pa]을 받아 물의 포화온도[K]를 반환하는 함수를 만들어 줘"), 사람은 반환값의 계약(단위)과 대조값 검증을 맡는다.
from CoolProp.CoolProp import PropsSI
def water_boiling_t(p_pa):
"""압력 p_pa[Pa]에서 물의 끓는점[K]을 반환한다."""
return PropsSI("T", "P", p_pa, "Q", 0, "Water") # 포화온도 [K]
t_b = water_boiling_t(101325.0) # 1 atm = 101325 Pa
print(f"{t_b:.2f} K") # 출력: 373.12 K
PropsSI의 인자를 계약으로 읽으면 이렇다. 첫 인자 "T"는 구하려는 물성(온도), 이어지는 "P"와 값은 주어진 조건(압력), "Q", 0은 포화액 상태라는 지정, 마지막이 물질명이다. 모든 입출력은 SI 단위다.
검증 루틴 3종
- 단위 체크: 입력 Pa, 출력 K다. PropsSI는 SI 단위만 쓰므로 101325를 kPa로 착각해 넘기면 즉시 어긋난다.
- 대조값: NIST WebBook의 물 끓는점 373.17 ± 0.04 K. 반환값 373.12 K와의 차이는 0.05 K(0.013%) 수준이다.
- 극한값: 압력을 낮춰 water_boiling_t(50000.0)을 부르면 끓는점이 373 K보다 내려가야 한다. 감압하면 낮은 온도에서 끓는다는 상식과 방향이 맞는지 확인하라.
분석 이 예제의 교훈은 분업이다. 함수 골격은 AI가, 물성값은 CoolProp이, 판정은 사람이 맡는다. 세 주체 중 어느 하나가 나머지를 대신하기는 어렵다. 물질명을 "Ethanol"로 바꿔 재실행하고, 반환값이 물보다 낮은지 확인해 보라. 에탄올이 물보다 먼저 끓는다는 일반화학 상식과 맞는지 보면 된다.
생각해보기
AI가 준 물성값의 진위를 판단할 방법을 두 가지 제안해 보라. 인터넷이 되지 않는 시험장이라면 두 방법 중 무엇이 살아남는가?
스스로 점검
- psi_to_kpa(-10.0)은 무엇을 반환하는가? 그 값은 물리적으로 말이 되는가?
- 코드 5-9에서 373.12를 돌려주는 조회식은 무엇인가?
5.5 첫 타이머, 첫 공개 구술: 마음의 준비
이번 주 실습부터 두 가지가 바뀐다. 첫째, 과제에 30분의 제한시간이 걸린다. 둘째, 실습 마무리에 무작위로 지목된 학생이 자기 코드 한 부분을 모두 앞에서 1분간 설명한다. 1~4주의 실습이 시간 무제한에 페어 안에서만 설명하는 저부담 구간이었다면, 5주차는 시험 형식으로 넘어가는 첫 계단이다.
제한시간은 1장에서 안내한 대로 최종 시험의 120분까지 매주 조금씩 늘어난다. 처음부터 2시간짜리 압박을 주는 대신 시간 감각을 단계적으로 키우는 설계다. 30분 안에 도구④를 완성하지 못해도 성적에는 아무 일도 일어나지 않는다. 이번 주 결과는 등수 없이 통과/재도전의 2단계로만 처리되고, 재도전은 다음 실습 전까지 열려 있다.
공개 구술이 두려운 것은 정상이다. 다만 이 장치의 정체를 알면 부담이 줄어든다. 구술은 4장에서 배운 인출연습의 사회적 버전이다. 머릿속에 있다고 믿는 지식을 꺼내 보는 행위 자체가 기억을 강화하며, 설명하다 막히는 지점이 곧 공부할 지점이다. 지금 사람들 앞에서 막히는 데에는 아무 대가가 없지만, 최종 시험의 구술 방어에서 막히면 점수로 이어진다. 매주 반복되는 리허설이 그 부담을 미리 덜어 준다.
준비 방법은 단순하다. 실습 중 함수 하나를 완성할 때마다 소리 내지 않아도 좋으니 S 5-1의 순서(목적→입력→처리→출력→한계)로 속으로 한 번 설명해 본다. 퇴실 전 페어에게 1분 설명을 한 번 하고 나가면 그 주의 구술 리허설은 끝난 셈이다. 막히면 침묵하지 말고 "목적부터 다시 말하겠습니다"라고 처음으로 돌아가면 된다. 구조를 따라 말하는 훈련이다.
생각해보기
타이머가 5분 남았는데 도구가 미완성이다. 남은 5분을 기능 추가에 쓰는 것과 README 검증 기록·커밋에 쓰는 것 중 어느 쪽이 유리한가? 최종 시험 루브릭(작동성 14점에 검증 증빙 필수, 30분 스냅샷 커밋이 부분 채점 근거)을 근거로 판단해 보라.
실습 5: 도구④ 단위환산 + 물성 조회기 (30분)
준비물
- 스타터 repo(조교 배포)를 클론한 상태. (성공 시
tool04/폴더와test_tool04.py가 보인다) - CoolProp 설치: 터미널에서
pip install CoolProp. (확인:python -c "import CoolProp"이 아무 오류 없이 끝난다) - 3주차에 만든 검증 README 양식. 이번 주 검증 기록도 같은 3종 형식으로 쓴다.
- 타이머는 강의실 공용으로 30분. 시작과 동시에 출발한다.
과제
- 실습 5.1. repo에 빈 상태로 첫 커밋을 남겨라. (성공 시 커밋 로그에 시작 시각이 찍힌다. 최종 시험의 "빈 repo 첫 커밋" 규정 리허설이다)
- 실습 5.2. 단위환산 함수 3종(psi→kPa, mmHg→bar, °C→K)을 AI로 생성하고, 각 함수 위에 EiPE 설명을 한국어 주석 2~3문장으로 직접 써넣어라. (완료 기준: 세 함수 모두 단위 주석과 EiPE 주석이 있다) 커밋하라.
- 실습 5.3. CoolProp으로 물질명·온도·압력을 받아 밀도와 끓는점을 딕셔너리로 반환하는 조회 함수를 생성하고 물에 대해 실행하라. (성공 시 끓는점이 373 K 부근으로 나온다)
- 실습 5.4. AI에게 물의 Antoine 상수를 물어라. 받은 상수로 373.15 K의 증기압을 계산해 1.013 bar와 비교하고, NIST WebBook의 표 5-2와 대조해 날조·불일치 여부를 README에 기록하라. (완료 기준: 판정과 근거 수치가 README에 있다)
- 실습 5.5. 검증 루틴 3종(단위·대조값·극한값)을 README에 채우고 최종 커밋을 남겨라. (성공 시
pytest test_tool04.py의 스모크 테스트 3개가 통과한다)
완성 기준
- 스모크 테스트 3개 통과 (
pytest test_tool04.py) - README에 검증 루틴 3종 기록 + 실습 5.4의 날조 판정 기록
- 30분 내 커밋 2회 이상 (시작 커밋 포함)
- 미완성이면 재도전한다. 다음 실습 전까지 같은 기준으로 다시 제출한다
막혔는가? CoolProp이 설치되지 않을 때
에러 메시지를 요약하지 말고 전문 그대로 AI에게 붙여넣고 이렇게 물어라. "이 에러의 원인 후보 3개와 각각의 확인 방법을 알려 줘. 내 환경은 Windows, pip 사용."
막혔는가? PropsSI 인자 순서가 헷갈릴 때
"CoolProp PropsSI로 물의 1 atm 끓는점을 구하는 최소 예제를 보여 주고, 인자 각각이 무엇을 뜻하는지 한 줄씩 설명해 줘"라고 요구하라. 설명 없는 코드만 주면 설명을 다시 요구하라.
막혔는가? 내 코드를 설명할 수 없을 때
"이 함수를 공학도 저학년에게 설명하듯 세 문장으로 설명해 줘. 그다음 내가 내 말로 다시 설명할 테니 틀린 부분을 지적해 줘"라고 하라. AI의 설명을 그대로 외우는 것이 아니라, 내 설명을 AI로 검증하는 방향이다.
퇴실 전 위키 기록 (15분)
오늘 만든 것 1건, 막힌 것 1건, 틀린 것 1건을 위키에 커밋해야 퇴실한다. 이번 주는 위키 마일스톤①(2점) 채점 주간이다. 1~5주의 커밋 리듬과 "내가 틀렸던 것" 기록이 자동 집계된다.
요약
- S 5-1 EiPE 설명 공식: 목적 → 입력 → 처리 → 출력 → 한계. 다섯 요소를 채우면 두세 문장의 설명이 된다.
- S 5-2 Antoine 식 (5.1): log₁₀ p* = A − B/(T + C). 상수를 받으면 로그 밑·압력 단위·온도 단위·유효범위 4종을 먼저 확인한다.
- S 5-3 물성 프롬프트 패턴: 값을 묻지 말고 "NIST/CoolProp에서 조회·검증하는 코드"를 요구한다.
| 요소 | 읽을 때 던지는 질문 | 시험1 출제 형태 |
|---|---|---|
| 변수 | 이 이름은 지금 어떤 값·단위를 가리키는가 | 상태표 채우기, 출력 예측 |
| 조건문 | 이 입력이면 어느 가지인가, 안 걸리면 무슨 일이 나는가 | 가지 판정, 경계값 추적 |
| 반복문 | 몇 번 도는가, 매 바퀴 무엇이 변하는가 | 반복 횟수·누적값 예측 |
| 함수 | 무엇을 주면 무엇을 어떤 단위로 돌려주는가 | EiPE 설명, "이 줄을 바꾸면?" |
AI 협업 사이클의 ④ 생성 코드 읽기 블록이 이번 장에서 처음으로 본격 훈련되었고, 도구 사다리는 학습 OS 3종에 이어 첫 화공 도구인 도구④까지 왔다. 읽기는 이제 시작이다. 읽을 수 있어야 다음 장에서 AI의 틀린 답을 채점하고 고칠 수 있다.
용어 정리
- EiPE (Explain in Plain English)
- 코드의 목적과 동작을 자연어로 설명하는 훈련·문항 유형.
- 변수 (variable)
- 값을 가리키는 이름.
- 할당 (assignment)
- 이름에 값을 묶는 문장.
- 상태 추적 (tracing)
- 실행 순서를 따라 각 변수의 값을 표로 적으며 코드를 읽는 방법.
- 조건문 (conditional statement)
- 조건의 참·거짓에 따라 실행 경로를 가르는 문장.
- 반복문 (loop)
- 같은 블록을 여러 번 실행시키는 문장.
- 리스트 (list)
- 여러 값을 순서대로 담는 자료형.
- 딕셔너리 (dictionary)
- 키(이름표)로 값을 꺼내는 자료형.
- 함수 (function)
- 이름을 붙여 두고 필요할 때 불러 쓰는 코드 묶음.
- 인자 (argument)
- 함수에 넘겨주는 값.
- 반환값 (return value)
- 함수가 돌려주는 값.
- 외삽 (extrapolation)
- 상관식을 유효범위 밖에 적용해 값을 구하는 일.
- CoolProp
- 순수 유체의 열역학 물성을 계산하는 오픈소스 라이브러리.
연습문제
Q군: 개념·읽기 (AI 없이 푼다)
- Q5.1 코드 5-2에서
p_mmhg = 760.0으로 바꾸었을 때의 출력을 실행 없이 예측하고, 그 값이 어떤 대조값과 일치해야 하는지 밝혀라. - Q5.2 켈빈 온도를 받아 섭씨로 바꿔 반환하는 함수
k_to_c(t_k)가 주어졌다고 하자. 이 함수를 EiPE 다섯 요소로 2~3문장 설명하라. - Q5.3 코드 5-7에서 t = 273.0일 때와 t = 272.9일 때 각각 무슨 일이 일어나는지 실행 경로를 따라 설명하라.
- Q5.4 단위환산 함수를 일부러 틀리게 만드는 방법을 두 가지 제시하고, 각각이 검증 루틴 3종 중 무엇에 걸리는지 밝혀라.
P군: 제작·계산 (AI 사용 전제)
- P5.1 도구④에 길이 환산(ft→m)을 추가하라. 1 ft = 0.3048 m를 대조값으로 쓰고, 검증 README를 갱신하라.
- P5.2 Antoine 상수 자동 검증기를 만들어라. 상수 A, B, C와 유효범위를 받아 373.15 K의 계산 증기압이 1.013 bar의 ±5% 안이면 PASS, 아니면 FAIL을 출력한다(유효범위가 373 K를 포함하지 않으면 SKIP). 표 5-2의 진짜 상수와 본문 경고 박스의 날조 상수로 시험하고, 결과를 EiPE 설명과 함께 위키에 기록하라.
위키 기록 과제 (이번 주 의미 커밋 ≥1이 채점 지표다)
① 이 장의 핵심(EiPE 다섯 요소와 문법 요소별 읽기 질문)을 1페이지로 정리하라(#seed). ② 이번 주 "내가 틀렸던 것" 1건을 에러 화면과 함께 기록하라. ③ 타 과목 연결 1건. 화공양론이나 유체역학 과제에서 단위환산이 필요했던 장면을 찾아 도구④로 다시 풀어 보고 결과를 남겨라. 이번 주는 위키 마일스톤①(2점) 채점 주간이다.