Numpilot
손안의 수치해석/2부 언어의 문제 — DSL

자연어에서 DSL로 — 번역층의 구조

12 / 30
2026-08-04 · 읽는 데 10분

한 문장이 지나는 길

사용자가 문장을 쓴다. 그 문장이 계산 결과가 되기까지 어떤 경로를 지나는가.

이 편에서는 그 경로를 단계별로 따라간다. 각 단계가 무엇을 하고, 무엇이 검사되고, 어디서 실패하는지.

사용자 문장
   ↓  ① 해석
의도 파악 (무슨 문제인가)
   ↓  ② 추출
명시된 값 뽑기
   ↓  ③ 보충
빠진 값 채우기
   ↓  ④ 검사
완전성·타당성 확인
   ↓  ⑤ 제시
사람에게 보여주기
   ↓  ⑥ 실행
솔버로 넘기기

여섯 단계다. 그리고 이 중 가장 중요한 단계는 다섯 번째다. 그 이유는 마지막에 이야기한다.

① 해석 — 무슨 문제인가

먼저 결정할 것은 이것이 어떤 종류의 문제인지다.

6편의 네 유형 분류가 여기서 쓰인다. 완결형인가, 목적형인가, 변형형인가, 관찰형인가.

이 판단이 중요한 이유는 경로가 갈리기 때문이다.

  • 완결형·목적형 → 새 문제를 만든다. 전체 경로를 지난다.
  • 변형형 → 기존 DSL을 고친다. 바뀐 항목만 다시 검사한다.
  • 관찰형 → 계산을 다시 하지 않는다. 결과 표시만 바꾼다.

세 번째가 특히 이득이다. “손잡이 끝만 보여줘”는 계산이 필요 없다. 이미 계산된 결과에서 표시 범위만 바꾸면 된다. 즉시 반응한다.

그리고 변형형도 상당히 절약된다. 재료만 바꾸는 경우, 형상과 격자는 그대로다. 격자 생성을 다시 할 필요가 없다.

4편에서 “번역은 첫 회에만, 그 뒤는 거의 0”이라고 했던 것이 이 구조에서 나온다.

② 추출 — 명시된 값 뽑기

문장에 실제로 적힌 값을 뽑는다. “알루미늄”, “200도”, “플라스틱”.

여기서 원칙이 하나 있다. 적히지 않은 것을 추측해서 채우지 않는다. 이 단계에서는 오직 명시된 것만 뽑는다.

왜냐하면 다음 단계에서 채운 값과 사용자가 준 값을 구분해야 하기 때문이다. 구분이 안 되면 5단계에서 “이건 제가 정했습니다”라고 표시할 수 없다.

그래서 추출된 값에는 출처가 따라붙는다. 사용자 지정 또는 자동.

③ 보충 — 빠진 값 채우기

7편에서 세어본 스무 개를 여기서 채운다. 채우는 근거는 세 가지다.

기본값. 항목마다 미리 정해둔 값. 주변 공기 온도 = 실온.

맥락 추론. 문제의 성격에서 유도. “프라이팬”이라는 단어에서 크기 규모와 사용 환경이 좁혀진다.

직전 상태. 변형형 입력에서는 바뀌지 않은 값은 이전 것을 그대로 쓴다.

이 단계가 편의의 원천이다. 그리고 위험의 원천이기도 하다. 그래서 다음 단계가 붙는다.

④ 검사 — 완전성과 타당성

두 종류의 검사를 한다.

완전성 검사 — 계산에 필요한 모든 칸이 채워졌는가. DSL의 구조가 정해져 있으므로 기계적으로 확인된다. 8편에서 이야기한 “좁은 언어의 이점” 중 첫 번째다.

타당성 검사 — 채워진 값이 물리적으로 말이 되는가.

  • 두께가 형상 크기보다 크지 않은가
  • 온도가 재료의 사용 범위를 넘지 않는가 (플라스틱에 500도)
  • 단위 추정이 자릿수 상식에 맞는가 (11편)
  • 경계조건이 서로 모순되지 않는가 (같은 면에 고정 온도와 열유입을 동시에)

마지막 항목이 실제로 자주 걸린다. 사용자가 조건을 추가하다 보면 앞의 조건과 충돌하는 경우가 생긴다. 이걸 잡지 않으면 솔버가 이상한 답을 내거나 아예 발산한다.

⑤ 제시 — 사람에게 보여주기

이 단계가 이 설계의 심장이다.

완성된 DSL을 사용자에게 보여준다. 그리고 세 가지가 시각적으로 구분된다.

문제: 정상 상태 열전달

형상: 원판 + 막대
  원판 지름     280 mm   ← 자동
  원판 두께       4 mm   ← 자동
  막대 길이     180 mm   ← 자동
  막대 단면    20×15 mm  ← 자동

재료
  원판   알루미늄        ← 사용자
  막대   페놀수지        ← 자동 (플라스틱)
    열전도율  0.25 W/m·K  ⚠ 결과에 영향 큼

경계조건
  원판 하면    200 °C 고정   ← 사용자
  그 외 모든 면  실온 25°C 공기와 열교환  ← 자동 (기본 규칙)

관심 지점: 막대 끝    ← 사용자
  • ← 사용자 — 당신이 준 값
  • ← 자동 — 제가 정한 값
  • — 결과를 크게 바꾸므로 확인 필요

사용자는 이 화면을 다 읽지 않아도 된다. 대개 안 읽는다. 그냥 결과를 본다.

그런데 결과가 이상할 때 여기로 돌아온다. 그리고 그때 무엇이 잘못됐는지 찾을 수 있다.

이게 “조용히 틀리는” 실패를 막는 방식이다. 실패를 완전히 없애지는 못한다. 대신 실패했을 때 원인을 찾을 수 있게 만든다.

⑥ 실행 — 솔버로 넘기기

DSL이 검사를 통과하면 솔버가 받는다.

여기서 솔버는 아무것도 해석하지 않는다. 애매함도, 기본값도, 단위 변환도 이미 앞에서 끝났다. 솔버는 완전하고 정확한 조건만 받아 계산한다.

이 분리가 중요하다. 솔버가 단순해지면 검증하기 쉬워지고, 빨라지고, 기기에서 돌릴 수 있게 된다. 4편에서 “계산은 기기에서”라고 했던 것이 이 분리 덕분에 가능하다.

어디서 실패하는가

정직하게 말하면 이 경로는 여러 곳에서 실패할 수 있다.

단계 실패 유형 결과
① 해석 유형을 잘못 판단 엉뚱한 계산
② 추출 값을 놓침 자동값이 사용자 의도를 덮음
③ 보충 기본값이 부적절 조용히 틀림
④ 검사 검사 규칙이 부족 모순을 통과
⑤ 제시 사용자가 안 읽음 실패를 못 알아챔

⑤가 가장 근본적인 약점이다. 아무리 잘 보여줘도 읽지 않으면 소용없다.

그래서 우리가 택한 완화책은 읽어야 할 것을 줄이는 것이다. 스무 개의 자동 결정 중 결과를 크게 바꾸는 것만 로 표시한다. 대개 한두 개다. 두 개를 확인하는 것은 사람이 한다.

이 구조가 의미하는 것

번역층은 통역이 아니다. 판단하는 층이다.

문장을 형식으로 옮기는 것은 이 층이 하는 일의 일부에 불과하다. 실제로는 스무 개의 결정을 내리고, 그 결정이 타당한지 검사하고, 사람이 감사할 수 있게 제시한다.

그래서 이 프로젝트에서 가장 어려운 부분은 솔버가 아니었다. 방정식을 푸는 방법은 이미 알려져 있다. 어려운 것은 무엇을 풀어야 하는지 정하는 일이었다.

다음 편에서는 이 접근이 최근의 기술 흐름과 어떻게 이어지는지 이야기한다. 흔히 vibe coding이라 불리는 방식이 무엇을 바꿨고, 무엇은 바꾸지 못했는지.


다음 편 예고 — vibe coding이 바꾼 것, 그리고 바꾸지 못한 것. 자연어로 지시하는 방식이 왜 코드에서는 잘 통하고 수치해석에서는 조건이 붙는지 짚는다.