탐구

통역 없이 앉는다 — 판단 한 조각이 규칙이 되는 자리

작성: makemind · 2026년 7월 17일

2026년 3월에 「기반은 이미 있다」를 실었다. 요지는 이랬다 — "당신도 도구를 만들 수 있다"가 맨바닥에서 시작하라는 말처럼 들리지만 사실은 정반대이고, 도구의 8할은 판단이며 그 판단은 정작 만들면 좋을 사람의 손에 이미 들려 있다. 빠진 건 화면이라는 한 축뿐이라고.

그 글에서 가장 좋았던 문단은 비유가 아니라 경고였다.

반장이 "이 소리"라고 말한 것이 문서에선 "이상 소음 발생 시"가 되고, 그 사이에서 30년의 귀가 통째로 증발한다.

이게 8할을 잃는 방식이다. 판단은 옮기는 동안 닳는다. 요구사항 문서를 거치고 개발자의 해석을 거치며, "이런 경우엔 좀 다른데요"의 뉘앙스가 사라진다.

그래서 그 글의 진짜 주장은 "화면을 쉽게 만들 수 있다"가 아니었다. 판단이 통역 없이 앉을 수 있는가였다. 그건 난이도의 문제가 아니라 경로의 문제다.

그때는 그 경로를 말로만 적었다. 이번엔 실제로 돌아가는 것에서 확인한다.

농부의 판단 한 조각 — 일곱 줄

온실 제어 샘플을 만들면서, 재배 규칙을 이렇게 두었다.

Rule(
  name: 'vent above 26C',
  whenKind: 'temperature',
  above: 26.0,
  thenKind: 'vent',
  setTo: 80.0,
  elseSetTo: 0.0,
),

일곱 줄이다. 그리고 이 일곱 줄이 무엇을 말하지 않는지가 중요하다.

어느 센서인지 말하지 않는다. 어느 릴레이인지 말하지 않는다. 모델 번호가 한 글자도 없다. 읽는 값의 종류와 움직일 것의 종류만 있다. 그래서 온도계를 다른 회사 제품으로 갈아 끼워도 이 일곱 줄은 그대로 산다 — 실제로 갈아 끼워 봤고, 섭씨 센서를 화씨 모델로 바꾸고 CO2 센서와 밸브를 증설해도 규칙은 한 글자도 안 바뀌었다.

A: vent above 26C: 26.5 -> v1=80.0     (TH-100, 섭씨, 3노드)
B: vent above 26C: 26.3 -> v1=80.0     (FX-200, 화씨, 5노드)
   server code: unchanged   rules: unchanged   rebuild: none

원래 글이 "판단 한 조각이 통역 없이 정의가 되어 화면에 앉는다"고 적은 자리에, 이제 그 조각이 몇 줄이고 무엇을 견디는지가 들어간다.

(온실 사슬 전체는 센서를 갈아 끼워도 제어는 그대로에.)

반장의 점검표 — 한 글자도 못 바꾸게 막았다

원래 글의 그 경고를 정면으로 받은 게 하나 더 있다.

설비 정비 어시스턴트를 만들면서 안전 점검표를 서버에 두었다. 그리고 그 도구의 설명문에 이렇게 적었다.

server.addTool(
  name: 'checklist.get',
  description:
      'Get the plant safety checklist for a machine type (press, conveyor, welder). '
      'These steps are set by the plant engineer and must not be paraphrased.',

도구 설명은 장식이 아니다. 모델이 실제로 읽는 텍스트다. 그리고 그 위에 얹은 지시에도 같은 줄이 있다.

- Safety checklist steps are the plant engineer's. Quote them in order and do
  not paraphrase, shorten or reorder them.

그런데 지시는 부탁이지 보장이 아니다. 그래서 검증이 실제로 대조한다.

# 점검표는 인용이지 요약이 아니어야 한다 — 한 줄을 원문 그대로 대조
grep -q "Verify emergency pull-cord continuity along both sides" captures/run.log \
  || { echo "a checklist step was altered on its way to the answer"; exit 1; }

"30년의 귀가 증발한다"를 막는 방법이 이것이다. 옮기지 말라고 부탁하고, 옮겨졌는지 기계가 대조한다. 통과 조건에 넣지 않으면 부탁은 언젠가 안 지켜지고, 안 지켜진 걸 아무도 모른다.

원래 글은 판단이 닳는 걸 문제로 짚었지만 대책은 "직접 만드는 것"까지였다. 실제로 만들어 보니 대책이 하나 더 필요했다. 직접 적은 것이 그대로 남아 있는지 확인하는 장치. 직접 적어도, 그 아래 층이 요약하면 똑같이 증발한다.

(설비 어시스턴트는 대답 옆에 근거를 붙인다에.)

판단을 넘겨받는 쪽이 안 해야 하는 일

이 글의 원편은 도메인 전문가 쪽에서만 봤다. 만들어 보니 반대편에도 규율이 필요했다.

설비 서버의 상태 핸들러다.

// 서버는 사실과, 그 사실이 한계와 어떻게 비교되는지를 말한다.
// 기계가 "괜찮다"고는 말하지 않는다 — 그 단어는 점검표를 든
// 사람의 것이다.
final overdue = (m['runHours'] as int) > (m['serviceEveryHours'] as int);
final vibrationOver =
    (m['vibrationMm'] as num) > (m['vibrationLimitMm'] as num);

serviceOverdue: true 는 사실이다. safe: false 는 판단이다. 판단을 시스템이 대신 내리기 시작하면, 8할이 손에 있다는 말이 무의미해진다. 전문가가 판단을 갖고 있는데 도구가 먼저 결론을 내면, 그 판단은 쓰이지 않는다.

그러니 원래 글의 명제에 반쪽을 더한다. 8할은 전문가의 손에 있다 — 그리고 시스템은 그 8할이 놓일 자리를 비워 두어야 한다.

2할은 얼마나 낮아졌나 — 그리고 원래 글이 틀린 곳

원래 글은 2할의 벽이 낮아졌다고 했다. 얼마나 낮아졌는지는 재지 않았다.

이제 몇 개는 잴 수 있다.

재배 규칙 한 조각7줄
규칙 목록 전체(규칙 2개)18줄
화면 정의 한 장1~2 KB
무인매장 앱 전체JSON 4개, 약 6 KB, 컴파일 0회
화면 문구 수정 → 반영83 ms, 빌드 0회

그런데 여기서 원래 글이 틀린 곳이 드러난다.

"열 줄"이라는 말이 그 글에 있었다. 화면 하나가 열 줄이면 된다는 취지였는데, 그때 그 열 줄이 실제로 무엇인지 보이지 않았다. 지금 세어 보니 규칙 한 조각은 일곱 줄이 맞다. 하지만 화면 한 장은 1~2 킬로바이트이지 열 줄이 아니다. 버튼 하나 텍스트 하나면 열 줄이지만, 쓸모 있는 화면 한 장은 그보다 크다. 그 차이를 원래 글은 얼버무렸다.

"사흘 대 한 시간" 같은 시간 비교도 그 글에 있었다. 근거가 없었다. 이 시리즈도 그 비교를 대신할 실측을 갖고 있지 않다 — 옛 방식으로 같은 것을 만들어 재 본 적이 없기 때문이다. 비교가 없으면 비교를 적지 않는다. 이 글에서 그 문장은 뺀다.

그리고 하나 더. 2할이 낮아진 것은 맞지만, 사라진 것은 아니다. 무인매장 번들을 세탁소로 고쳐 봤더니 라벨은 바뀌었는데 품목은 아이스크림 그대로였다. 화면은 JSON이라 도메인 전문가가 고칠 수 있지만, 품목이 무엇인지·재주문점이 몇인지는 여전히 번들 밖에 있다. 무코드로 되는 일과 안 되는 일의 경계가 정확히 거기다.

(그 경계는 폴더 하나가 앱이다에서 그림으로 볼 수 있다.)

무른 것의 복권 — 여전히 유효한 부분

원래 글의 마지막 축은 이랬다. 오랫동안 "딱딱한 것"(코드·기술)이 값지고 "무른 것"(경험·감·눈썰미)은 값이 매겨지지 않았는데, 2할의 벽이 낮아지면 그 값이 뒤집힌다는 것.

만들어 보고 이 축은 유효하다고 본다. 다만 근거를 하나 붙일 수 있다.

온실 규칙이 부품 번호를 한 글자도 안 갖는 것 — 그게 무른 것을 값지게 만드는 구조다. 규칙이 FX-200 을 알면 그 규칙은 부품에 매인다. 종류로만 말하면 규칙이 부품보다 오래 산다. 오래 사는 쪽이 값진 쪽이고, 여기서 오래 사는 것은 "26도에서 열어라"라는 판단이다.

이 샘플이 안 한 것

원래 글의 정직 절을 유지하고, 이번에 알게 된 것을 더한다.

이 글에는 새 샘플이 없다. 인용한 코드와 로그는 전부 앞선 편들에서 만든 것이다. horizon 글의 일은 새로 짓는 게 아니라 이미 지은 것을 딛는 것이고, 원편의 문제는 딛을 것이 없는데 딛는 척했다는 것이었다.

"한나절이면 된다" 류의 소요 시간은 재지 않았다. 원편에 그런 취지의 문장이 있었고, 이 시리즈도 그걸 대신할 실측이 없다. 도메인 전문가가 실제로 규칙을 적는 데 얼마나 걸리는지는, 도메인 전문가에게 시켜 봐야 알 수 있고 그걸 하지 않았다. 여기 실린 일곱 줄은 내가 적은 것이지 농부가 적은 것이 아니다.

8할/2할이라는 비율 자체도 측정된 적이 없다. 원편의 수사이고 이 글도 그걸 검증하지 않았다. 비유로만 읽어 주기 바란다.

규칙이 종류로 말하면 산다는 것은 확인했지만, 도메인 전문가가 그 형식을 직접 다룰 수 있는지는 확인하지 않았다. 위 일곱 줄은 Dart 문법이다. 농부가 저걸 그대로 쓸 수 있느냐는 별개의 물음이고, 이 시리즈는 그 물음에 답하지 않았다.

판단이 앉을 자리

원편은 이렇게 물었다 — 8할을 가진 사람이 왜 2할 앞에서 멈추는가.

만들어 보고 답을 조금 바꿔 적는다. 멈추게 하는 것은 2할의 난이도만이 아니다. 판단이 옮겨지는 동안 닳는다는 것, 그리고 옮긴 다음에 그게 남아 있는지 확인할 방법이 없다는 것이다.

그래서 필요한 것은 셋이다.

  • 판단이 짧게 적히는 형식 — 일곱 줄. 부품 번호 없이 종류로.
  • 옮기지 말라는 규율 — 도구 설명과 지시문에.
  • 옮겨졌는지 대조하는 장치 — 통과 조건에. 부탁만으로는 안 지켜진다.

셋 중 마지막이 원편에 없던 것이고, 실제로 만들어 보지 않으면 나오지 않는 항목이었다.

기반은 이미 있다 — 그 말은 여전히 맞다. 거기에 한 줄을 붙인다. 그 기반이 도구가 되는 길에서 닳지 않는지, 누군가는 확인해야 한다.


makemind.dev 「탐구」 — 판단 한 조각의 실제 크기와, 그 판단이 닳지 않게 막는 장치를 실물로 갚았다.

Twitter