Ritual

Claude가 같은 실수를 반복하지 않도록 돕는 교훈

모든 실수를 교훈으로, 모든 교훈을 규칙으로, 그리고 가능하다면 모든 규칙을 테스트나 가드로 바꿔 주는 Claude Code 플러그인입니다.

claude plugin marketplace add Zurishadday/Ritual
claude plugin install ritual@ritual

전체 63개 중 63개

1

“읽지 못했다”는 “아무것도 없다”가 아니다

숫자와 데이터

모든 데이터 포인트에는 세 가지 상태가 있다. 값이 있음, 정말로 아무것도 없었음, 모름. 뒤의 두 상태는 차트에서 똑같이 0으로 그려지지만, 뜻은 정반대다.

감지 질문

내가 보여 주려는 숫자나 “전부 괜찮다”는 판단이, 실패한 쿼리, 빈 테이블, 거부된 권한, 또는 끝까지 읽지 않은 출력(교훈 44 참고)에서 나온 것은 아닌가?

경고 신호

“실패하면 그냥 0으로 두고 넘어가죠.”

예시와 해결 방법

예시

만료된 권한 때문에 쿼리가 실패했는데, 대시보드에는 해당 지역의 ‘판매 0건’이 표시되었다. 아무도 의심하지 않았다. 0은 데이터처럼 보이니까.

해야 할 일

읽기가 실패하면 빈칸이나 0이 아니라 오류를 카드 위에 직접 표시한다. 그리고 “문제 0건”이라고 말하는 카운터는, 먼저 일부러 심어 둔 문제를 찾아낸 적이 있을 때만 믿을 수 있다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
2

이름이 같다고 같은 것은 아니다

숫자와 데이터

“활성 고객”, “날짜”, “상사”, “기준값”처럼 같은 단어가 두 가지 정의를 감추고 있는 경우가 많다. 두 보고서가 맞지 않을 때는 거의 항상 이것이 원인이다.

감지 질문

두 가지 중 하나에만 참인 규칙이 있는가? 그리고 한 계산에서 두 수치를 합치거나 나눌 때, 같은 집합, 같은 척도, 같은 기간에서 나온 것인가?

경고 신호

“날짜는 같아요” · “뷰에서 이미 걸러져 있어요” · “둘 다 페소예요.”

예시와 해결 방법

예시

“날짜”는 이벤트 날짜일 수도, 적재 날짜일 수도, 파티션 날짜일 수도 있다. 또는 “상사”: 지금의 상사일 수도, 측정하려는 일이 일어났을 때의 상사일 수도 있다.

또 다른 예시

한 캠페인 테이블에는 회사 전체의 광고비가 들어 있었지만, 매출은 구매 100건 중 1건만 뽑은 표본에서 가져왔다. 두 열 모두 ‘페소’라고 적혀 있었고, 그 결과 모든 캠페인의 수익률이 음수로 나왔다.

해야 할 일

코드와 화면에서 변형마다 다른 이름을 붙인다. 이름이 어색해도 괜찮다. 그리고 서로 다른 출처의 두 수치를 나누거나 빼기 전에, 각 수치가 어디에서 왔는지 적어 둔다. 결과가 모든 경우에 똑같이 나온다면(모두 손해, 모두 이익), 사업 문제보다 척도 문제를 먼저 의심한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
3

현재 기간은 언제나 불완전하다

숫자와 데이터

아직 끝나지 않은 달은 끝난 달보다 늘 나빠 보인다. 추세가 아니라 달력 때문이다.

감지 질문

이 계산에 아직 끝나지 않은 기간이 포함되어 있는가?

경고 신호

“벌써 추세가 보여요.”

예시와 해결 방법

예시

매출 곡선이 마지막 점에서 “떨어진다”. 그 달은 절반만 지나간 상태였다.

해야 할 일

지표는 마지막으로 마감된 기간에서 끊거나, 부분 기간을 화면에 표시한다. 그리고 두 시계를 구분해 둔다. 집단 단위 수치는 마감된 달을, 개인 단위 수치는 오늘 날짜를 쓴다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
4

원천이 덮어쓰는 필드는 이력이 아니다

숫자와 데이터

많은 시스템은 오늘의 값만 저장한다. 그 필드 위에 “과거” 변수를 만들면, 과거인 척하며 현재를 측정하는 셈이다.

감지 질문

이 필드는 값이 바뀔 때 이전 값을 보존하는가, 아니면 그냥 덮어쓰는가?

경고 신호

“칼럼이 바로 있으니 그냥 쓰면 되죠.”

예시와 해결 방법

예시

시스템에는 각 사람의 최신 상사만 저장되어 있다. 이미 퇴사한 사람의 상사는 그 자리에 굳어 있으므로, ‘상사별 팀 이직률’은 결국 “이 팀은 더 이상 존재하지 않는다”를 측정하게 된다.

해야 할 일

과거를 거슬러 보기 전에, 데이터가 스냅샷인지 이력인지 원천에 확인한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
5

완벽한 결과는 승리가 아니라 경고다

숫자와 데이터

하나의 변수가 떠난 사람과 남은 사람을 거의 오류 없이 갈라낸다면, 그 변수 안에 결과 자체가 숨어 있을 가능성이 크다.

감지 질문

품질 지표가 올라가는 이유가, 모델이 누구에게 일어났는지가 아니라 언제 일어났는지를 맞히고 있기 때문은 아닌가?

경고 신호

“거의 완벽하게 나왔어요!” · “연도로 보정하고 넘어가죠.”

예시와 해결 방법

예시

모델 성능이 갑자기 훨씬 좋아졌다. 알고 보니 한 변수는 떠난 사람에게는 모두 1이고 남은 사람에게는 모두 0이었다. 원천이 두 집단을 서로 다르게 채웠기 때문이다. 또 다른 변형: 모델이 누구에게 일어났는지가 아니라 언제 일어났는지를 학습하고 있었다.

해야 할 일

미래를 기준으로 검증한다. 과거로 학습하고 이후 기간으로 평가한다. 그리고 무언가로 보정하기 전에, 그 요소가 내가 예측하려는 결과를 결정하는 것인지 묻는다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
6

업무 정의는 한 곳에만 둔다

스크립트와 파일

“활성”의 기준이 모든 쿼리에 반복되어 있으면, 복사본들은 서로 어긋난다. 어긋날지 아닐지의 문제가 아니라, 언제 어긋나느냐의 문제다.

감지 질문

이 정의를 바꾸면 몇 개의 파일을 건드려야 하는가? 하나보다 많다면, 규칙이 한 곳에 설정되어 있지 않은 것이다.

경고 신호

“여기에도 넣죠, 한 줄이잖아요” · “이 숫자는 안 바뀔 거예요.”

예시와 해결 방법

예시

검증기는 참조 항목의 개수 43을 손으로 적어 두고 있었다. 문서가 47개로 늘어나자, 새로 추가된 네 개를 존재하지 않는 항목으로 거부했다. 지금은 문서 안의 항목을 직접 센다.

해야 할 일

정의를 모든 쿼리가 지나가는 한 곳에 두고, 모두가 거기서 읽게 한다. 다른 곳의 값을 복사해 온 손으로 적은 숫자도 반복된 정의다.

혼동하지 말 것

학습 자료에서 설명을 일부러 되풀이하는 것은 정의를 복사하는 것이 아니다. 복사하지 말아야 할 것은 값을 계산하는 규칙이다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
7

의도가 아니라 공개된 결과를 읽는다

스크립트와 파일

프로세스는 무엇을 하려는지 선언하지만, 실제로 한 일을 공개한다. 둘이 항상 일치하지는 않는다. 출력을 소비하는 쪽은 결과를 읽어야 한다.

감지 질문

이것은 프로세스의 설정으로 만들어졌는가, 아니면 공개된 결과로 만들어졌는가?

경고 신호

“선언된 목록과 모델은 같은 거예요.”

예시와 해결 방법

예시

화면이 모델이 사용하려던 변수 목록으로 컨트롤을 만들었다. 학습 과정에서 그중 하나가 빠졌고, 며칠 동안 아무 일도 하지 않는 컨트롤이 있었다.

해야 할 일

공개된 결과에서 도출한다. 그리고 도출할 수 없는 것은 조용히 사라지게 두지 말고, 크게 실패하게 한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
8

소비자는 기억하지 말고 목록으로 만든다

Git과 프로세스

다른 것들이 이름으로 읽는 데이터를 바꿀 때는, 그것을 읽는 사람들의 목록을 적어 두어야 한다. 기억은 항상 하나를 빠뜨린다.

감지 질문

이것을 사용하는 사람들의 목록을 어디서 얻었는가? 검색에서인가, 기억에서인가?

경고 신호

“그것이 쓰이는 세 곳은 이미 다 처리했어요” · “그 사람들은 이미 봤어요” · “필요한 건 다 추가했어요.”

예시와 해결 방법

예시

모델이 바뀐 뒤 세 화면의 라벨을 갱신했다. 아무도 떠올리지 못한 네 번째 화면은 여전히 이전 모델의 선택지를 보여 주고 있었다.

또 다른 예시

한 장을 쓰면서, 독자가 앞 장에서 이미 세 함수를 안다고 기억에 의존해 썼다. 검색해 보니 그 장은 하나만 가르쳤고, 새 것처럼 소개한 주제는 다른 장에서 이미 설명되어 있었다.

예시 하나 더

변경을 저장할 때 쓴 파일 목록을 기억에 의존해 적었는데, 새 기능을 작동하게 하는 파일 하나가 빠져 있었다. 나중에 검토한 보류 변경 목록이 그것을 보여 주었다.

해야 할 일

변경 유형별로 영향 범위를 적은 지도를 유지한다. 그것을 빠짐없이 훑으면서 “변경함” 또는 “~이므로 해당 없음”이라고 말한다. 변경으로 새 소비자가 생긴다면, 같은 변경에 추가한다. 그리고 출처를 인용하기 전에, 그 출처에서 주장하는 문장을 그대로 옮겨 적는다. 누군가 다른 사람이 무엇을 했다거나 보았다고 말하는 것도 확인해야 한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
9

한 상태가 여러 기록에 있다: 함께 옮긴다

Git과 프로세스

보류 항목을 닫는 일에는 보통 세 곳이 관여한다. 보류 목록, 그것을 감시하는 테스트, 그것을 설명하는 문서. 한 곳만 옮기면 나머지는 그것과 모순된다.

감지 질문

이 상태를 단언하는 다른 곳은 어디인가? 저장하기 전에 이름을 적는다.

경고 신호

“반대쪽은 나중에 갱신할게요.”

예시와 해결 방법

예시

보류 항목을 목록에서는 닫음으로 표시했다. 그런데 그것을 감시하는 테스트는 여전히 “실패가 예상됨”으로 표시되어 있었고, 문서는 여전히 열린 상태로 설명하고 있었다. 세 곳에 세 가지 버전이 있었다.

해야 할 일

작업 단위는 완전한 세트다. 같은 변경에서 함께 바꾼다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
10

쌍둥이 모듈은 함께 바뀐다

인터페이스와 디자인

제품에 같은 화면의 두 버전이 있다면(두 종류의 사용자, 두 지역, 두 제품), 한쪽의 개선은 다른 쪽에서는 아직 처리되지 않은 개선이다.

감지 질문

내가 건드리는 것에 사용자가 “같은 모듈”로 보는 쌍둥이가 있는가?

경고 신호

“다른 쪽에서는 요청하지 않았어요.”

예시와 해결 방법

예시

데스크톱 버전에 날짜 필터가 추가되었다. 사람들이 “같은 화면”으로 보는 모바일 버전에는 한 달 동안 그 필터가 없었다.

해야 할 일

쌍둥이를 확인하고 “같음” 또는 “~이므로 해당 없음”이라고 적기 전에는 변경을 닫지 않는다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
11

차트를 지워도 그 주장은 남는다

글쓰기와 문서

데이터가 믿을 만하지 않아서 무언가를 지웠다면, 같은 주장이 다른 글에 다른 말로 여전히 남아 있을 가능성이 높다.

감지 질문

방금 지운 내용과 같은 말을 하고 있는 다른 글이 있는가?

경고 신호

“차트는 이미 지웠어요.”

예시와 해결 방법

예시

신뢰할 수 없는 차트를 내렸지만, ‘핵심 발견’ 카드와 실행 계획에는 그 차트가 말했던 내용이 여전히 권고로 남아 있었다.

또 다른 예시

장 계획을 7번에서 15번으로 다시 번호 매겼다. 다른 문서의 두 목록은 예전 계획의 ‘7.4’와 ‘7.7’을 가리킨 채 남아 있었는데, 그 번호는 이제 전혀 다른 주제가 되어 있었다. 계획을 바꿀 때 예전 번호도 주장이다.

해야 할 일

식별자가 아니라 주제로 검색한다. 되풀이된 주장에는 변수 이름이 붙어 있지 않다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
12

쿼리가 돌았다고 숫자가 맞는 것은 아니다

숫자와 데이터

“오류가 나지 않았다”는 “정확하다”와 같지 않다. 내 계산과 무관한 무언가와 비교한다.

감지 질문

내 코드 바깥의 무엇과 이 결과를 대조할 것인가? 그리고 글이 시스템의 동작이라고 말하는 모든 것, 즉 예시든, 규칙이든, 옵션 설명이든, 실제 엔진에서 실행해 보았는가?

경고 신호

“내 컴퓨터에서는 돌아가요” · “오류가 안 났어요” · “원래 이렇게 동작해요, 그냥 설명하는 거예요.”

예시와 해결 방법

예시

객관식 문제에서 숫자를 따옴표가 붙은 텍스트와 비교하면 오류가 난다고 주장했다. 일부 다른 엔진에서는 실제로 그렇지만, 사람들이 실제로 쓰던 엔진에서는 쿼리가 실행되어 행을 반환했다.

또 다른 예시

한 글은 이름 붙은 블록이 자기 쿼리 안에서만 살아 있다고 올바르게 설명했다. 그런데 그 글의 예시는 같은 블록을 세 개의 쿼리가 공유한다고 가정하고 있었다. 실행해 보니 두 번째 쿼리가 오류를 냈다. 테이블이 존재하지 않았다.

예시 하나 더

한 페이지의 모든 예시를 실행했는데도 문장 세 개가 여전히 거짓이었다. 맨 끝에 쓴 옵션 설명은 아무도 실행해 보지 않은 줄의 동작을 설명하고 있었다. 오류를 읽는 규칙(“이런 메시지가 나오면 저것이 빠진 것”)은 같은 페이지의 다른 단계와 모순되었다. 그리고 소개글은 어떤 함수가 “결과를 돌려준다”고 했지만, 실제로는 돌려주지 않았다.

해야 할 일

알려진 수치, 원천 시스템, 이전 기간과 대조한다. 실제 환경에서 테스트한다. 그 환경의 권한, 라이브러리, 실제로 돌아가는 코드 사본을 그대로 쓴다. 시스템 동작에 대한 모든 주장은 적기 전에 한 번은 실행해 본다. 예시 속에 지나가듯 나오는 주장이나 맨 마지막에 쓴 주장도 마찬가지다. 주장이 “만”, “항상”, “절대” 같은 일반 규칙이라면, 그것을 깨뜨릴 사례를 찾아서 그것도 실행한다. “정수로 변환하면 정수만 읽는다”는 주장은 소수점이 있는 텍스트로 확인했더니, 소수가 있는 숫자에 대해서는 거짓이었다. 분수로 말할 때(“여섯 중 다섯”)는 전체가 무엇인지 밝힌다. 가상의 시나리오도 확인한다. 표본 크기, 차이, p값이 서로 일관되어야 한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
13

오류를 본 적 없는 검사기는 아무것도 검증하지 않는다

테스트와 점검

항상 통과하는 테스트는 고장 났을 수 있다. 그것을 알 수 있는 유일한 방법은 실제 오류에 대해 실패하는 모습을 직접 보는 것이다.

감지 질문

내 검사기를 실제로 나타날 형태의 오류에 대해 테스트했는가? 그리고 올바른 경우에 대해서도 테스트했는가?

경고 신호

“이미 통과하니까 제대로 설정된 거예요.”

예시와 해결 방법

예시

특정 단어를 금지하는 테스트가 소문자 버전만 찾고 있었다. 대문자나 악센트가 붙으면 그냥 통과했다.

또 다른 예시

연습을 위해 중복 레코드 37개를 심었는데, 개수가 92로 나왔다. 데이터에 이미 자연스럽게 일치하는 항목이 있었기 때문이다. 저장하기 전에 심은 개수와 비교하는 검사가 이것을 잡아냈다.

예시 하나 더

들여쓰기된 코드를 감지하는 규칙이 텍스트로 시작하는 줄을 플래그했다. 통과해야 하는 경우가 그 모양이 아니었던 것이다. 그리고 텍스트 비교가 작동한다는 것을 확인하는 테스트는, 비교가 고장 났는데도 통과했다. 다른 검토가 오류를 먼저 거부했기 때문이다.

해야 할 일

두 가지 사례로 보정한다. 하나는 반드시 무언가를 찾아야 하는 사례, 다른 하나는 아무것도 찾으면 안 되는 사례다. 태어난 날 실제로 한 번 돌려 본다. 올바른 사례도 나쁜 사례만큼 중요하다. 올바른 것을 거부하는 검사기도 고장 난 것이며, 엄격해 보이기 때문에 알아채기 더 어렵다. 올바른 사례에는 내가 직접 쓰지 않은 것을 포함해, 올바른 것의 실제 형태가 들어가야 한다. 다른 순서, 다른 이름 같은 것들. 각 검사는 스스로 보정되어야 한다. 다른 검사가 오류를 먼저 잡았다면, 내 검사는 한 번도 시험받지 않은 것이다. 그리고 이미 읽은 것을 다시 읽기만 하는 검토(“두 번째 실행”이 같은 파일을 다시 읽는 것)는 실패할 수 없다. 무언가 잘못되었다면 실패할 수 있는 대조로 바꾼다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
14

탐침은 조사하는 경로를 그대로 지나가지 않는다

테스트와 점검

검사가 피해를 일으킬 수 있는 것과 같은 파이프라인을 지난다면, 그 피해가 검사에도 영향을 준다. 그러면 모든 것이 맞든 틀리든 같은 답을 내놓는다.

감지 질문

내가 조사하는 변환이 내 테스트도 변환하고 있는가?

경고 신호

“똑같은 쿼리를 하나 더 보내서 확인해요.”

예시와 해결 방법

예시

악센트 문제를 찾으면서, 바로 그 문제를 일으키는 경로로 악센트가 든 쿼리를 보내고 있었다.

해야 할 일

피해가 건드릴 수 없는 형태로 테스트를 만든다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
15

스스로 꺼지는 테스트는 꺼졌다고 보고하지 않는다

테스트와 점검

“데이터를 찾지 못하면 테스트를 건너뛴다”는 분기는 세상이 바뀔 때 정확히 작동하고, 아무도 모르게 감시를 멈춘다.

감지 질문

내 테스트에 정당한 변경이 생겼을 때 활성화되는 조용한 출구가 있는가?

경고 신호

“앵커를 못 찾으면 테스트를 건너뛰어요.”

예시와 해결 방법

예시

테스트가 표의 제목으로 표를 찾았고, 못 찾으면 건너뛰었다. 제목이 바뀌었고, 테스트는 몇 주 동안 아무것도 확인하지 않은 채 통과했다.

변형

첫 번째 깨진 파일에서 멈추는 검사는 그 뒤의 모든 파일을 감시하지 않은 채 남겨 둔다. 검증기가 “이 페이지는 읽을 수 없음, 12번째 줄”이라고 보고하는 대신 충돌해 버리면, 검토 전체가 꺼진다.

해야 할 일

빠진 것이 도구라면 건너뛰는 것이 정직하다. 빠진 것이 감시 대상 데이터라면 테스트는 실패해야 한다. 그리고 읽을 수 없는 파일은 검토의 끝이 아니라, 줄 번호가 적힌 발견 사항이다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
16

검사기의 필터는 대개 정작 중요한 것을 빼 버린다

테스트와 점검

모든 자동 검토는 “관련 있는 것”만 거르는데, 그 필터 때문에 문제가 있는 바로 그 자리가 보이지 않을 수 있다.

감지 질문

내 필터는 무엇을 빠뜨리는가? 결과를 믿기 전에 적어 둔다.

경고 신호

“차이가 48개 나왔어요, 목록은 이미 있어요” · “테스트가 전부 돌아요.”

예시와 해결 방법

예시

디자인 감사 도구가 자식 요소가 없는 요소만 검토했다. 검토가 필요한 라벨 안에는 도움말 아이콘이 들어 있었기 때문에, 도구는 그 라벨을 한 번도 보지 못했다.

또 다른 예시

테스트가 모든 페이지를 돌며 항상 첫 번째 선택지를 표시하고, 쿼리를 하나씩 실행했다. 늘 통과했지만, 정답이 실제로 받아들여지는지는 한 번도 확인하지 않았다.

예시 하나 더

글이 바뀌었는지 판단하려고 공백을 무시했다. 그 결과 바로 그 글, 즉 공백과 줄바꿈으로 텍스트를 배치하는 방법을 설명하는 페이지가 빠져 버렸다. 정규화도 필터링이다.

해야 할 일

필터가 빠뜨리는 것을 적고, 제외된 항목의 표본을 직접 확인한다. 그리고 필터 때문에 눈이 멀었다는 것을 알게 되면, 이미 만들어 둔 비슷한 다른 필터도 찾아본다. 코드의 공백을 전부 지우는 검토는 두 단어를 하나로 붙여 올바른 코드를 거부했다. 같은 교훈을 다른 정규화에서 얻은 직후였는데도 말이다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
17

컴파일되는 코드가 실행되는 코드는 아니다

테스트와 점검

문법 검사기는 실행하면 충돌하는 코드도 통과시킨다. 모든 것이 ‘초록불’인데 화면이 하얗게 비어 있는 것이 최악의 실패다.

감지 질문

내 테스트는 코드를 실행하는가, 아니면 읽기만 하는가?

경고 신호

“문법 검사가 통과했으니 코드는 괜찮아요.”

예시와 해결 방법

예시

한 페이지가 문법 검사와 타입 검사를 통과했다. 그런데 열어 보니 빈 화면이었다. 서버에만 존재하는 변수를 쓰고 있었기 때문이다.

해야 할 일

페이지나 프로그램 전체를 실행하는 테스트를 최소 하나는 둔다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
18

원본을 검사하는 것은 전달되는 것을 검사하는 것이 아니다

테스트와 점검

X를 검사했는데 사용자가 받는 것이 X에서 파생된 Y라면, 둘 사이에는 아무도 들여다보지 않는 코드가 있다.

감지 질문

원본에서 나오는 것만 누군가 확인하는가, 아니면 화면에 도달하는 것도 확인하는가?

경고 신호

“이미 검증된 데이터에서 나온 거예요” · “파일은 괜찮아요.”

예시와 해결 방법

예시

게시된 각 결과가 맞는지는 확인했다. 그런데 그 결과로 만든 버전이 화면까지 가는 동안, 누락된 데이터에 대해 다른 규칙을 쓰는 버전이 되어 있었다.

또 다른 예시

검토자가 각 페이지의 원본 파일을 읽고 승인했다. 모바일에서 카드로 쌓이면서 더는 비교할 수 없게 된 표는, 페이지를 실제로 열어 봤을 때에야 드러났다.

해야 할 일

사람에게 도달하는 지점에서 검사한다. 보이는 그대로의 페이지, 사람이 내려받는 파일, 받는 메시지를 확인한다(교훈 41 함께 참고).

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
19

한 가지 차원만 검토하면 검토가 아니다

인터페이스와 디자인

“이미 같아요”라고 말하려면, 눈에 보이는 속성을 하나만이 아니라 전부 비교해야 한다.

감지 질문

속성 하나를 비교했는가, 아니면 사용자가 보는 속성 전부를 비교했는가?

경고 신호

“크기가 이제 맞으니 디자인도 같아요.”

예시와 해결 방법

예시

두 화면의 디자인을 네 번의 라운드에 걸쳐 맞추었다. 처음에는 크기, 그다음 타이포그래피, 그다음 색, 마지막으로 라벨 색이었다. 매번 “끝났어요”라고 했다.

또 다른 예시

자료의 일러스트를 내용과 크기 측면에서는 검토했지만 대비는 보지 않았다. 그 결과 네 개의 이미지에서 두 텍스트 색이 최소 가독성 기준 아래로 떨어져 있었다.

해야 할 일

첫 번째 차이를 고치기 전에 모든 차이를 나열한다. 그리고 메모에서 동사를 보면 알 수 있다. “고쳤다”와 “이렇게 된다”는 의도이고, “~라고 나온다”와 “~을 보여 준다”는 측정이다.

확인된 모델~opus 2026-08claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
20

멱등성과 갱신 가능성은 같은 것이 아니다

스크립트와 파일

“없으면 삽입한다”는 중복은 막아 주지만, 모든 것을 얼려 버린다. 이미 있는 것은 다시 쓰이지 않는다.

감지 질문

이 코드가 주입하는 내용을 바꾸면, 다음 실행에서 갱신되는가?

경고 신호

“이미 들어가 있으니 다시 건드리지 않아요.”

예시와 해결 방법

예시

분류 기준의 범례를 한 번 삽입했다. 기준은 바뀌었는데 범례는 옛 범위를 계속 보여 줬다.

해야 할 일

교체한다. 옛것을 지우고 다시 주입한 뒤, 사본이 하나만 남았는지 확인한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
21

표식은 내 것이어야 한다

스크립트와 파일

사용자가 읽는 텍스트(제목이나 라벨)를 검색해서 내 변경을 찾으면, 다른 개선이 그 위에 무언가를 덧붙이는 순간 내 변경을 더 이상 찾지 못한다.

감지 질문

내가 앵커로 쓰는 텍스트가 다른 이유로도 존재할 수 있는가? 그 안에서 무언가가 자랄 수 있는가?

경고 신호

“제목에 고정하면 돼요, 유일하니까.”

예시와 해결 방법

예시

여러 제목 옆에 도움말 아이콘이 추가되었다. 제목으로 자기 위치를 찾던 업데이트들이 작동을 멈췄다.

또 다른 예시

검토가 사람이 숫자를 변환했는지 확인하려고 “int(”를 찾았다. 그런데 “print(” 안에서도 매치되었다. 무언가를 출력하는 줄은 모두 통과하는 것처럼 보였다. 찾는 것은 다른 단어의 일부가 아니라 온전한 단어여야 한다.

예시 하나 더

검토가 코드가 마지막으로 출력한 줄을 답으로 삼았다. 함수가 내부에서 숫자를 출력하고 돌려주지는 않는 경우, 그 줄은 다른 이유로 존재했다. 답은 화면에 나왔지만, 코드는 실제로 답을 전달하지 않았던 것이다.

해야 할 일

ID나 섹션 주석처럼 내 것인 표식을 쓴다. 그리고 변경이 여러 블록에 동시에 닿는다면, 첫 번째 블록만이 아니라 전부 확인한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
22

두 번째 실행이 버그를 찾아낸다

스크립트와 파일

아무것도 깨뜨리지 않으면서 반복되는 변경은, 한 번이 아니라 두 번 실행해서 확인해야 한다.

감지 질문

이미 적용된 것이 있는 대상에 내 변경을 실행해 보았는가? 나 다음에 이 같은 텍스트를 건드리는 다른 프로세스는 무엇인가?

경고 신호

“잘 돌았으니 끝났어요.”

예시와 해결 방법

예시

스크립트가 두 번째 실행에서 아무것도 바꾸지 않는지 확인하려고, 같은 실행의 체크섬을 두 번 비교했다. 그다음에는 서로 다른 파일 목록에서 얻은 두 체크섬을 비교했다. 두 비교 모두 “같다” 또는 “다르다”고 말했지만 아무것도 증명하지 못했다. 제대로 된 비교는 같은 파일로, 한 명령 안에서 체크섬을 구하고, 스크립트를 실행하고, 다시 체크섬을 구하는 것이다.

해야 할 일

같은 출발점에서 두 번 실행하고 파일을 비교한다. 두 번째 실행은 아무것도 바꾸지 않아야 한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
23

위치 기반 주소는 만료된다

스크립트와 파일

“9번 셀” 앞에 무언가를 삽입하면, 9번 셀은 이제 다른 셀이다.

감지 질문

이 도구는 위치로 대상을 찾는가? 그리고 내가 방금 그 앞에 무언가를 삽입하거나 삭제했는가?

경고 신호

“9번 셀은 방금 봤던 그거예요.”

예시와 해결 방법

예시

스크립트가 노트북의 9번 셀 앞에 제목 셀을 삽입한 뒤 “9번 셀”을 수정했다. 그런데 방금 삽입한 셀을 수정하고 말았다.

해야 할 일

삽입할 때마다 위치를 다시 찾고, 전체 구조를 검토해서 결과를 확인한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
24

안전망을 두고 쓴다

스크립트와 파일

쓰기 위해 파일을 열면 그 즉시 파일이 비워진다. 쓰는 도중에 무언가 실패하면, 빈 파일만 남는다.

감지 질문

파일을 열고 쓰기를 끝내기 전 사이에 무엇인가 실패할 수 있는가?

경고 신호

“단순 교체니까 바로 쓰면 돼요.”

예시와 해결 방법

예시

스크립트가 설정 파일을 다시 쓰려고 열었다. 그런데 값 하나를 계산하는 도중 실패했고, 파일은 빈 채로 남았다. 서버는 다시 시작되지 않았다.

해야 할 일

메모리에서 모든 것을 준비하고, 임시 파일에 쓴 다음, 마지막에 원본을 한 번에 교체한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
25

설정은 상태가 아니고, 경고는 보장이 아니다

스크립트와 파일

“예약 작업이 활성화되어 있다”는 “이번 달에 실행되었다”는 뜻이 아니다. 실패하면 경고가 올 것이라고 기다리는 것은, 경고가 결코 실패하지 않는다고 믿는 것이다.

감지 질문

“알아서 실행되겠지”라고 기대하고 있는 것이 있는가?

경고 신호

“예약되어 있으니 돌고 있겠죠.”

예시와 해결 방법

예시

예약 작업이 ‘활성’으로 표시되었지만, 만료된 인증 정보 때문에 두 달 동안 실행되지 않았다. 대시보드는 마지막 데이터 포인트를 오늘 것처럼 보여 주었다.

해야 할 일

데이터가 마지막으로 언제 갱신되었는지 화면에 표시한다. 어떤 기간이 빠졌는지 확인한다. 그리고 프로세스를 중복 행 없이 다시 실행해도 안전하게 만든다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
26

이미 운영 중인 것도 나빠질 수 있다

테스트와 점검

품질 필터는 보통 새로 들어오는 것만 검토한다. 이미 들어가 있는 것은 그대로 두고, 그 가정은 아무도 다시 묻지 않은 채 낡아 간다.

감지 질문

몇 달째 돌아가고 있는 이것의 가정을, 게시된 뒤로 누군가 다시 검증했는가?

경고 신호

“게시할 때 이미 검증했어요.”

예시와 해결 방법

예시

게시된 보고서가 원천이 더 이상 채우지 않는 칼럼으로 계속 필터링하고 있었다. 결과는 0을 보여 줬고, 이미 ‘검증되었다’는 이유로 아무도 다시 묻지 않았다.

해야 할 일

검토할 때마다, 이미 쓰고 있는 것도 새 후보와 같은 테스트에 올린다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
27

시스템보다 도구를 먼저 의심한다

콘솔과 도구

숫자가 바뀌어야 할 때 바뀌지 않았거나, 여러분이 보고 있는 순간에 바뀌었다면, 다음 순서로 의심한다. 캐시, 같은 테이블에 쓰는 다른 프로세스, 여러분이 들여다보고 있는 도구, 그리고 맨 마지막에야 시스템 자체.

감지 질문

나는 시스템을 보고 있는가, 아니면 캐시, 복사본, 또는 오래된 스냅샷을 지니거나 중간에 바꿔 버린 도구를 보고 있는가?

경고 신호

“이미 고쳤는데 여전히 똑같아요” · “이번엔 정말 제대로 입력했어요.”

예시와 해결 방법

예시

한 표의 열이 절반으로 줄어든 것처럼 “보였다”. 몇 분 뒤에는 완전했다. 다른 프로세스가 표를 다시 만들고 있는 중에 여러분이 보고 있었던 것이다.

또 다른 예시

페이지에 새 이미지가 “로드되지 않았다”. 파일은 멀쩡했다. 테스트 서버가 시작된 뒤에 만들어진 폴더를 보지 못했던 것이다.

예시 하나 더

스크립트가 텍스트 패턴을 “잘못 계산했다”. 스크립트는 멀쩡했다. 코드를 넘겨주는 콘솔이 스크립트가 읽기 전에 모든 \n을 실제 줄바꿈으로 바꿔 버린 것이다. 그리고 셀들이 메모리를 공유하는 노트북에서는, 나타났어야 할 오류가 나타나지 않았다. 변수가 앞선 셀에서 저장된 채로 남아 있었기 때문이다.

해야 할 일

재난을 선언하기 전에 몇 분 뒤 두 번째 스냅샷을 찍는다. 도구가 이미 같은 방식으로 여러분을 실망시켰다면, 계속 들여다보지 말고 도구를 바꾼다. 같은 실수가 반복되는 것은 운이 나쁜 게 아니라 잘못된 도구를 쓰고 있다는 뜻이다. 중간에 \n이나 \\을 바꾸는 콘솔은 코드를 넘기기에 적합하지 않다. 코드는 파일에 담고, 그 내용을 건드리지 않는 도구로 쓴 뒤, 그 파일에서 실행한다. 그리고 기계적인 것(이미 세 번 실패한 명령)은 기억에 의존하지 말고 가드로 막는다.

확인된 모델~opus 2026-08claude-opus-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
28

실행하는 사람과 검증하는 사람은 다른 사람이어야 한다

테스트와 점검

같은 사람이 실행하고 확인하면, 실행 오류가 스스로를 확인해 준다.

감지 질문

한 일을 한 사람 말고, 사용자가 받는 결과를 보고 검토한 사람은 누구인가?

경고 신호

“제가 이미 직접 검토했어요.”

예시와 해결 방법

예시

각 페이지를 쓴 사람이 검토용 스크린샷도 찍었는데, 위험하다고 생각한 단계만 찍었다. 검토자는 원본 파일을 읽었다. 스크린샷이 없는 단계는 아무도 보지 않았다.

해야 할 일

한 사람이 실행하고, 다른 사람이 결과를 읽어서 확인한다. “내가 이미 했다”는 검증이 아니라, 이제 검증할 수 있게 되었다는 신호다. 그리고 검증하는 사람은 실행한 사람과 같은 경로로 보지 않는다(교훈 14 참고). 둘 다 원본만 읽는다면, 둘 다 화면은 보지 못한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
29

남에게 넘기기 전에 명령을 확인한다

콘솔과 도구

남의 명령을 실행하는 사람은 아무것도 보지 못한 채 실행한다. 망가진 명령은 다음 명령에 대해 그들이 가진 신뢰를 깎아 먹는다.

감지 질문

이 명령의 각 이름을, 오늘 시스템에서 읽었는가, 아니면 기억에서 입력했는가?

경고 신호

“늘 쓰던 명령과 같아요.”

예시와 해결 방법

예시

배포 명령에 브랜치 이름이 기억에 의존해 적혀 있었다. 실제 브랜치는 다른 이름이었고, 실행한 사람은 묻기 전에 30분을 잃었다.

해야 할 일

넘기기 전에 직접 실행해 보고, 각 이름(스크립트, 경로, 브랜치)은 기억이 아니라 시스템에서 복사한다.

확인된 모델~opus 2026-08claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
30

행동하기 전에 설명하고, 그렇다는 답을 기다린다

Git과 프로세스

잘못된 방향으로 빠르게 움직이는 것은 진전이 아니다.

감지 질문

이 블록이 크거나, 되돌리기 어렵거나, 다른 사람이 이미 정한 것을 바꾸는가? 그렇다면 설명하고 기다린다. 아니라면 무엇을 할지 말하고 진행한다. 모든 단계마다 허락을 구하는 것에도 비용이 든다.

경고 신호

“그들이 무엇을 원하는지 이미 알아요.”

예시와 해결 방법

예시

프로젝트 전체의 폴더 구조가 미리 알리지 않고 재편되었다. 그 변경은 그 자체로는 옳았지만, 다른 사람이 코드에 없는 이유로 이미 그 구조를 정해 두었기 때문에 완전히 되돌려졌다.

해야 할 일

큰 작업 블록을 시작하기 전에, 무엇을 왜 할지 쉬운 말로 설명하고 확인을 기다린다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
31

결정을 바꾸지 않는다면, 기술적인 것은 화면에 두지 않는다

인터페이스와 디자인

업무 화면의 모든 요소는 무언가를 결정하는 데 도움이 되어야 한다. 감사에 도움이 되는 것은 코드에, 결정에 도움이 되는 것은 업무 언어로 화면에 둔다.

감지 질문

이것이 화면을 쓰는 사람의 어떤 결정이라도 바꾸는가? 바꾸지 않는다면, 왜 여기 있는가?

경고 신호

“혹시 누가 필요로 할까 봐요.”

예시와 해결 방법

예시

판매 화면의 첫 행에 주문마다의 내부 ID와 마지막 계산 시각이 표시되어 있었다. 아무도 그것으로 결정하지 않았고, 정작 중요한 데이터가 놓일 자리를 차지했다.

해야 할 일

화면에 무엇을 추가하기 전에, 그것이 어떤 결정을 바꾸는지 적는다. 아무것도 바꾸지 않는다면, 기술 로그나 코드로 보내고 화면에는 두지 않는다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
32

작동하지만 보이지 않는 것은 고장 난 것으로 보고된다

인터페이스와 디자인webapps

버튼이 화면 밖의 무언가를 바꾼다면, 사용자에게는 작동하는 것과 작동하지 않는 것이 똑같이 보인다.

감지 질문

컨트롤을 사용한 직후, 그 자리에서 움직이지 않고도 사용자가 무엇이 바뀌었는지 보는가?

경고 신호

“작동은 해요, 그냥 안 보일 뿐이에요.”

예시와 해결 방법

예시

필터는 표를 실제로 걸러냈다. 그런데 표는 두 화면 아래에 있었다. 사람들은 “아무 일도 안 한다”고 보고했다.

변형

컨테이너를 숨기면 그 안의 모든 것이 숨겨지는데, 아무 상관 없는 것까지 포함된다. 예를 들어 폐기된 컨트롤 안에 들어 있던 유용한 링크.

해야 할 일

모든 컨트롤은 무엇이 바뀌었는지 말하고, 사용자를 그곳으로 데려간다. 그리고 무언가를 숨기기 전에, 그 안에 어떤 다른 요소가 들어 있는지 확인한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
33

글리프는 글자가 아니다

인터페이스와 디자인

작은 글씨에서는 “÷”와 “+”, “l”과 “1”, “O”와 “0”이 헷갈린다. 같은 것을 두 사람이 잘못 읽었다면, 그들이 산만했던 것이 아니다. 글자 크기 때문이다.

감지 질문

읽히는 크기와 글꼴에서, 이 기호가 다른 기호와 헷갈릴 수 있는가? 아니면 입력할 수 없는 무언가처럼 보이는가?

경고 신호

“내 화면에서는 괜찮아 보여요.”

예시와 해결 방법

예시

두 사람이 작은 글씨로 된 카드에서 “98 ÷ 441”을 “98 + 441”로 읽었고, 둘 다 계산이 틀렸다고 보고했다.

또 다른 예시

자료의 코드 글꼴은 >=를 하나의 기호 ⩾로 합쳐 보여 주었다. 배우는 사람은 보이는 대로 따라 치는데, 그 기호는 키보드에도, 언어에도 존재하지 않는다.

해야 할 일

기호가 헷갈린다면 단어로 바꾼다. “÷” 대신 “98 나누기 441”처럼 쓴다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
34

QA 발견 사항은 증상을 믿고, 원인은 측정한다

테스트와 점검

QA 보고서는 대개 증상에 대해서는 옳지만, 제시하는 원인은 가설에 그치는 경우가 많다.

감지 질문

내 측정으로 원인을 재현할 수 있는가, 아니면 그럴듯하게 들리니까 받아들이는가?

경고 신호

“보고서에 이미 원인이 나와 있어요.”

예시와 해결 방법

예시

보고서는 합계가 틀리게 나오는 차트를 고치라고 했다. 그런데 그 차트는 화면에 존재하지 않았다. 데이터는 그것을 그리는 무엇도 없이 그냥 흘러가고 있었다.

해야 할 일

수정 전과 후를 측정한다. 증상을 일부만 개선하는 수정은 아직 끝난 것이 아니다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
35

지나가며 적은 할 일 목록은 금방 낡는다

Git과 프로세스

다른 일을 하다가 “나중에”라고 적어 둔 것은 이미 존재하지 않을 수도 있고, 의도적인 결정이었을 수도 있다.

감지 질문

이 항목을 오늘 확인했는가, 아니면 적혀 있다는 이유만으로 작업하려고 하는가?

경고 신호

“목록에 있었어요.”

예시와 해결 방법

예시

메모에 “날짜 필터를 제거할 것”이라고 적혀 있었다. 나중에 작업하려고 보니, 그 필터는 이미 팀이 문서로 결정한 것이었다. 제거했더니 보고서가 깨졌다.

해야 할 일

보류 항목을 작업하기 전에 오늘 확인하고, 그대로 두기로 의도적으로 정했다고 말하는 문서화된 결정이 있는지 찾는다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
36

쓰기 전에 측정한다

숫자와 데이터

문서의 모든 수치는 날짜와 출처가 있는 측정에서 나와야 한다. 기억이나 문서의 이전 판본에서 가져오면 안 된다.

감지 질문

이 수치나 비교(“천 명이 넘는”, “절반이 넘는”, “거의 전부”)는 어떤 데이터와 어떤 날짜에서 나왔는가?

경고 신호

“전에 있던 수치예요” · “대충 그 정도 나와요” · “보면 다 통과하는 걸 알 수 있어요.”

예시와 해결 방법

예시

한 설명에서는 버그 때문에 티켓의 “거의 5분의 1”을 잃었다고 했다. 측정해 보니 5분의 1보다 많았다. 그 문장은 데이터가 아니라 머릿속 계산에서 나온 것이었다.

또 다른 예시

한 글은 코호트 집단의 “50%를 넘었다”고 했다. 그런데 열두 개 중 다섯 개는 50% 미만이었다. 다른 글의 그림에는 손으로 계산한 식이 있었는데 맞지 않았다. 백분율에 전체를 곱해도 그림에 그려진 숫자가 나오지 않았다.

해야 할 일

수치를 적기 전에 다시 측정하고, 옆에 어떤 데이터와 어떤 날짜에서 왔는지 적는다. 수량 표현(“거의”, “이상”, “대부분”)도 숫자가 변장한 것이므로 똑같이 측정한다. 그리고 그림에 계산이 들어 있다면, 그림을 그리는 바로 그 스크립트가 계산까지 하게 한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
37

문서에는 있는 그대로 적고, 있었으면 하는 대로 적지 않는다

글쓰기와 문서

문서 검토는 문서를 개선하는 일이지, 시스템을 다시 설계하는 일이 아니다. 시스템에 한계가 있으면 문서는 그 한계를 명시한다. 숨기거나 곧 고쳐 주겠다고 약속하지 않는다.

감지 질문

지금 쓰려는 내용이 오늘 동작하는 방식을 설명하는가, 아니면 동작해야 하는 방식을 설명하는가?

경고 신호

“원래 이렇게 동작해야 해요” · “곧 고칠 거예요.”

예시와 해결 방법

예시

매뉴얼에는 데이터가 저절로 동기화된다고 적혀 있었다. 실제로 시스템은 앱을 열었을 때만 동기화했다. 검토에서는 매뉴얼을 ‘곧 자동으로 바뀔 것’이라고 약속하는 쪽으로 ‘고쳤다’. 한계를 있는 그대로 적었어야 했다.

해야 할 일

문서에 대한 지적(“글이 엉성하다”)과 시스템에 대한 지적(“이상적인 것과 다르게 동작한다”)을 구분한다. 두 번째 종류는 한계로 명시한다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
38

모르는 것은 지어내지 않고 표시한다

글쓰기와 문서

공식 문서는 모든 내용을 같은 권위로 말한다. 담당자, 일정, 응답 시간처럼 지어낸 세부사항도 진짜 정보와 똑같이 읽힌다.

감지 질문

이 세부사항을 정말 알고 있는가, 아니면 그럴듯해 보여서 가정하고 있는가?

경고 신호

“당연히 그럴 거예요.”

예시와 해결 방법

예시

어떤 절차에 아무도 합의한 적 없는 24시간 응답 시간이 적혀 있었다. 그럴듯해 보여서 적었는데, 일단 공개되자 약속이 되어 버렸다.

해야 할 일

빠진 내용은 눈에 띄게 표시한다. 예를 들어 빨간색 ‘확인 대기’처럼. 그리고 아는 사람에게 묻는다. 틀린 표현보다 중립적인 표현이 낫다.

혼동하지 말 것

이 표시는 결정하는 사람을 위한 것이지, 최종 독자를 위한 것이 아니다. 공개된 글 안의 ‘확인 대기 중’은 그곳에 있으면 안 되는 또 다른 데이터다. 확인되기 전에 문서를 내보내야 한다면, 빠진 부분을 주장하지 않는 중립적인 표현을 쓰고, 대기 항목은 보고서나 프로젝트 기록에 남긴다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
39

눈에 보이도록 버전을 매긴다

글쓰기와 문서

모든 변경에는 표지의 새 버전 번호와, 날짜·무엇이 바뀌었는지·누가 바꿨는지를 적은 이력 한 줄이 붙어야 한다. 사본이 두 개 돌아다닐 때 어느 쪽이 좋은 판본인지 알려 주는 것은 버전뿐이다.

감지 질문

누군가 지난주 사본을 가지고 있다면, 그것이 더는 좋은 판본이 아니라는 것을 어떻게 알 수 있는가?

경고 신호

“작은 변경이라 버전이 필요 없어요.”

예시와 해결 방법

예시

매뉴얼 사본 두 개가 이메일로 돌고 있었다. 오래된 쪽에는 도구가 ‘더블클릭으로 연다’고 적혀 있었는데 더는 사실이 아니었다. 둘 중 어느 것이 좋은 판본인지 아무도 알 수 없었다.

해야 할 일

문서를 수정하는 바로 그 변경에서 버전 번호를 올리고 이력 한 줄을 쓴다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
40

기록에는 남은 것과 그 이유를 적는다. 실수의 연대기가 아니다

Git과 프로세스

변경 이력은 제품을 이해하기 위한 것이지, 변경한 사람의 이미 해결된 실수를 이야기하기 위한 것이 아니다.

감지 질문

이 줄이 제품을 이해하거나 같은 실수를 피하는 데 도움이 되는가, 아니면 나에게 일어난 일을 기록할 뿐인가?

경고 신호

“일어난 모든 것의 기록을 남겨 두죠.”

예시와 해결 방법

예시

이력에는 “A를 시도했고 실패했다. B를 시도했고 실패했다. C를 남겼다”라고 적혀 있었다. 몇 달 뒤 이것을 읽는 사람에게는 C와 그 이유만 필요했는데, 그것을 찾으려고 세 문단을 읽어야 했다.

해야 할 일

최종 상태와 그 이유를 적는다. 시도했다가 실패한 것은, 같은 것을 반복하지 않도록 누군가 필요로 하는 무언가를 가르칠 때만 적는다.

확인된 모델~opus 2026-08AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
41

독자가 실제로 보는 형식으로 확인한다

인터페이스와 디자인web

텍스트에서 단어를 찾았다고 해서 그것이 화면에 나온다는 뜻은 아니다. 텍스트는 문서의 다른 곳에 있는데, 그것을 보여 주어야 할 형식은 비어서 나올 수 있다.

감지 질문

독자가 보는 그대로 그 요소를 봤는가, 아니면 원본에서 단어(또는 코드)만 찾았는가?

경고 신호

“단어는 파일에 있어요” · “한 줄 고치는 거예요.”

예시와 해결 방법

예시

번호가 붙은 세 단계가 빈 글머리 기호로 나왔다. 그 단어들이 문서의 다른 곳에 있었기 때문에 자동 검사는 통과시켰다.

또 다른 예시

“오른쪽에 열이 더 있습니다”라는 안내를 추가하고 코드가 있으니 완료로 처리했다. 그런데 한 번도 나타나지 않았다. 일반 표 스타일이 그것을 켜는 조건을 지워 버렸기 때문이다. 스크린샷을 보고서야 다른 사람이 알아챘다.

예시 하나 더

답 선택지에 파일상으로는 “합계: {2 * 78}”이라고 적혀 있었다. 페이지가 그려질 때 시스템은 중괄호 안을 계산해 “합계: 156”을 보여 주었다. 두 선택지가 똑같아진 것이다. 화면을 본 사람만 이것을 알아챘다.

변형

리뷰어가 판단하는 스크린샷이 아무도 도달하지 않는 화면을 보여 줄 수 있다. 한 강좌의 캡처 도구는 코드 연습마다 넘어가기만 하려고 채운 한 줄을 답으로 넣었다. 그래서 “이후” 스크린샷에는 그 채움 줄과 “예상 결과가 아닙니다”라는 메시지가 보였다. 리뷰어는 정답을 맞힌 뒤 학습자가 보는 화면을 한 번도 보지 못했다. 데스크톱에서는 캡처에 헤더와 측면 메뉴까지 담겨서, 수업이 읽을 수 없는 띠처럼 나왔다. 리뷰용으로 캡처할 때는 각 단계에 성공한 사용자가 하듯 답하고, 검토 대상 부분만 캡처한다.

해야 할 일

“이 세 단계가 글머리 기호로 나오는지”처럼 정확한 요소를 확인하고, 독자가 볼 페이지를 적어도 한 번은 본다. 작은 수정도 확인한다. 다른 규칙이 그것을 덮어쓸 가능성이 가장 낮다고 예상되는 곳이 바로 그 자리이기 때문이다. 그리고 페이지에 새로운 요소(코드 블록, 고정 헤더)를 처음 쓸 때는 모바일에서도 본다.

확인된 모델~sonnet 2026-09claude-sonnet-5-5 2026-10claude-opus-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
42

최신 버전에서 작업한다

글쓰기와 문서

오래된 사본을 가지고 한 검토는 이미 고쳐진 오류를 다시 가져온다.

감지 질문

내가 편집하고 있는 판본이 가장 최근 것인가, 아니면 내가 열어 두었던 것인가?

경고 신호

“어제부터 이 판본을 열어 두고 있었어요.”

예시와 해결 방법

예시

매뉴얼 재구성 작업을 몇 주 전 판본으로 했다. 그 판본에는 다시 도구가 ‘더블클릭으로 연다’고 적혀 있었는데, 이미 사실이 아니었다.

해야 할 일

검토가 제안한 구조에 가장 최근 내용을 채워 넣는다. 반대로 하지 않는다.

확인된 모델~sonnet 2026-09AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
43

여러 번 고친 뒤에는 처음부터 끝까지 다시 읽는다

글쓰기와 문서

부분 수정을 여러 번 하고 나면 문서가 스스로 모순될 수 있다. 각 수정은 자기 절에서는 맞았지만, 다른 절은 아무도 다시 읽지 않았다.

감지 질문

누군가 전체를 마지막으로 읽은 뒤로 이 문서에 수정이 몇 번이나 있었는가?

경고 신호

“각 수정은 해당 자리에서 확인했어요.”

예시와 해결 방법

예시

한 절에는 연결이 없으면 아무것도 저장되지 않는다고 적혀 있었다. 그런데 FAQ에는 캡처된 내용은 기기에 보관된다고 여전히 적혀 있었다.

해야 할 일

수정 한 라운드를 마칠 때마다, 고친 내용과 관련된 모든 부분을 주제로 검색해서 확인한다.

확인된 모델~sonnet 2026-09AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
44

출력에서 잘라낸 부분이 판정일 수 있다

콘솔과 도구

결과의 마지막 줄만 보거나 다른 명령으로 파이프를 거치면, 정확히 “실패했다”고 말한 부분이 버려질 수 있다. 실패한 테스트의 잘린 출력은 통과한 테스트의 잘린 출력과 똑같아 보인다.

감지 질문

나는 판정(몇 개가 통과했는지, 몇 개가 실패했는지, 어떻게 끝났는지)을 읽고 있는가, 아니면 출력의 일부만 읽고 있는가?

경고 신호

“화면에 오류가 안 떴어요” · “마지막 몇 줄이면 충분해요.”

예시와 해결 방법

예시

한 페이지가 테스트가 “오류 없이 끝났다”는 이유로 검토 완료 처리되었다. 결과가 끝부분만 보여 주는 명령을 거쳤고, 테스트가 실패했다는 알림은 그 과정에서 사라졌다.

또 다른 예시

테스트 스위트가 실패한 테스트를 자동으로 다시 실행했다. 두 번째에 통과한 테스트는 실패로 세지 않고 “불안정”으로만 표시했고, 원인은 숨겨졌다. 단계를 바꿀 때마다 서버에 페이지를 다시 요청했기 때문이다. 재시도가 없었다면 실패가 드러났고 측정할 수 있었을 것이다.

해야 할 일

상태를 바꾸기 전에 판정 줄을 찾는다. 명령을 연결한다면, 첫 번째 명령의 실패가 끝까지 전달되는지 확인한다. 출력에 판정이 없다면 그것은 “통과했다”가 아니라 “모른다”는 뜻이다(교훈 1 참고). 그리고 전체 출력을 파일에 저장하고 판정을 거기서 찾는다. 그러면 미리 얼마나 읽을지 정해 둘 필요가 없다.

확인된 모델~sonnet 2026-09AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
45

오류 경로도 누군가는 걷는다

인터페이스와 디자인webapps

모든 것이 옳게 돌아가는 경우만 테스트하면, 실수하는 사람이 그 빈틈을 찾는다. 배우는 중에는 실수가 가장 흔한 일이다.

감지 질문

사용자가 가장 흔하게 하는 잘못된 행동(오타, 빈 답, 두 번 클릭)을 하면, 무엇을 보고, 계속 진행할 수 있는가?

경고 신호

“정답을 넣으면 잘 돼요.”

예시와 해결 방법

예시

쿼리 셀은 쿼리가 실행되어야만 시도 횟수를 셌다. 오타가 있으면 다음 단계로 넘어가는 버튼이 활성화되지 않아서, 사람이 꼼짝 못 하게 되었다. 테스트는 늘 오류가 없는 시작 쿼리를 실행했기 때문에 통과했다.

해야 할 일

모든 컨트롤마다 세 경로를 테스트한다. 정상 경로, 가장 흔한 오류, 빈 입력. 세 경로 모두 무슨 일이 일어났는지 말해 주고, 사용자가 계속 진행할 수 있게 해야 한다.

확인된 모델~sonnet 2026-09claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
46

모든 요청마다 도는 것은 콘텐츠와 함께 커질 수 없다

인터페이스와 디자인web

모든 페이지에서 하는 일, 예를 들어 모든 콘텐츠를 읽거나 색인을 다시 계산하는 일은, 페이지가 열 개일 때는 비용이 적지만 백 개일 때는 많이 든다. 서서히 커지기 때문에, “가끔 실패한다”는 상황이 오기 전까지 아무도 알아채지 못한다.

감지 질문

모든 요청마다 실행되는 이 코드는 모든 콘텐츠를 훑는가? 지금은 얼마나 걸리는가, 두 배면 얼마나 걸리는가, 많은 요청이 동시에 오면 얼마나 걸리는가?

경고 신호

“로컬에서는 빨리 로드돼요” · “간헐적인 실패예요.”

예시와 해결 방법

예시

사이트의 모든 페이지가 목차를 만들기 위해 모든 콘텐츠를 읽고 파싱했다. 페이지 하나만 보면 0.4초였다. 하지만 사이드바가 한 번에 약 40개를 요청했고, 합치면 16초가 걸렸다. 몇 달 뒤 페이지를 전환할 때 테스트가 실패하기 시작했고, 그 실패는 테스트 자체의 문제처럼 보였다.

해야 할 일

사람들이 쓰는 방식 그대로, 컴파일된 서버에서 모든 요청을 함께 넣어 측정한다. 페이지 하나만 재지 않는다. 서버가 도는 동안 바뀌지 않는 것은 캐시하고, 실제로 느리게 만든 그 경우로 측정하는 테스트를 남긴다.

확인된 모델~sonnet 2026-09claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
47

병렬 작업은 공유하는 부분에서 충돌한다

Git과 프로세스

여러 사람이 동시에 일하면 각자 자기 부분은 분명히 본다. 하지만 공유하는 것(테스트, 데이터, 프로젝트 전체의 문서)에서는 변경들이 합쳐지면서 충돌한다. 이름이 겹치고, 사본이 뒤처지고, 다른 사람이 아직 끝내지 못한 작업을 테스트가 읽는다. 통합은 붙여 넣기가 아니라 일이다.

감지 질문

두 부분이 동시에 건드리는 파일은 무엇이며, 누가 통합하는가? 내 테스트는 다른 사람이 아직 끝내지 못한 작업을 읽고 있는가?

경고 신호

“우리는 각자 자기 것을 테스트했어요” · “실패는 다른 부분에 있어요.”

예시와 해결 방법

예시

네 사람이 동시에 각자 한 부분을 쓰면서, 공유 부분을 결과물로 남겼다. 통합하자 두 결과물이 공유 테스트에 이미 있는 이름을 썼고, 테스트가 돌지 않게 되었다. 다른 테스트는 확인 대상의 사본을 보관하고 있었는데, 그 부분은 바뀌었지만 사본은 바뀌지 않았다. 한 테스트 실행은 다른 사람이 아직 그리고 있던 이미지 때문에 실패했다. 결국 각 부분은 따로 저장할 수 없었다. 공유 파일에 이미 모든 사람의 변경이 들어 있었기 때문이다.

해야 할 일

공유 부분은 한 사람이 통합하고, 이름이 충돌하면 멈추는 단계를 둔다. 테스트는 사본이 아니라 원본을 읽게 한다. 모두 끝난 뒤에 전체 테스트 스위트를 한 번 돌리거나, 아직 바뀌고 있는 부분을 뺀 채로 돌리고, 어떤 부분을 뺐는지 말한다. 그리고 파일을 공유하는 부분은 함께 저장해서, 저장된 각 버전이 전체로 작동하게 한다.

확인된 모델~sonnet 2026-09AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
48

생성된 파일이라면 수정은 생성기에 한다

스크립트와 파일

파일이 스크립트나 다른 조각들로 조립되는 경우, 그 파일은 원본이 아니라 결과물이다. 파일을 직접 고치면, 다음에 생성될 때 아무 경고 없이 사라진다.

감지 질문

이 파일을 다른 무엇(스크립트, 템플릿, 조각 조립)이 쓰는가? 다시 생성하면 내 변경이 남아 있는가?

경고 신호

“파일에서 직접 고쳤어요” · “방금 다시 생성했어요.”

예시와 해결 방법

예시

각자 제출한 섹션으로 메모를 조립했다. 세 행을 메모에서 직접 고쳤는데, 제출물에서 다시 만들자 옛 세 행이 돌아왔다. 다른 작업에서는 검토자가 템플릿에서 만들어진 페이지의 대체 텍스트를 손으로 고쳤다. 작성자가 페이지를 다시 생성하자 수정이 사라졌다.

해야 할 일

파일을 고치기 전에 그것이 어디서 오는지 확인한다. 원본(템플릿, 스크립트, 제출물)을 고치고 다시 생성한다. 결과물을 고쳐야 한다면, 같은 단계에서 원본도 함께 고친다. 생성된 결과물을 검토하는 사람은 무엇이 바뀌었는지 말해서, 원본으로 옮겨질 수 있게 한다. 그리고 원본에서 파일을 다시 만들기 전에, 나올 결과와 비교한다. 차이가 나는 부분은 모두 사라질 수정이다.

확인된 모델~sonnet 2026-09AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
49

일반 규칙이 특정 규칙을 조용히 이기면 안 된다

인터페이스와 디자인web

모든 것에 적용되는 규칙(전역 스타일, 기본값)은 각 부분이 스스로 정한 것을 아무 경고 없이 덮어쓸 수 있다.

감지 질문

이 일반 규칙이 각 부분이 이미 스스로 정한 것을 건드리는가? 둘이 충돌하면, 어느 쪽이 이기는가?

경고 신호

“반복하지 않으려고 전역으로 만들었어요.”

예시와 해결 방법

예시

사이트 전체를 위해 쓴 키보드 포커스 스타일에 자체 테두리 둥글기가 들어 있었다. 각 컴포넌트의 스타일보다 우선순위가 높았기 때문에, 알약 모양 버튼이 키보드로 포커스를 받으면 모양이 바뀌었다. 마우스로는 포커스가 보이지 않기 때문에 아무도 알아채지 못했다.

해야 할 일

일반 규칙은 자기 것만 건드리게 한다(포커스 윤곽선만, 모양은 건드리지 않는다). 일부러 이겨야 한다면, 그 사실을 옆에 적어 둔다. 그리고 가장 흔한 것이 아니라 가장 다른 부분에서 테스트한다.

확인된 모델~sonnet 2026-09claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
50

두 설명이 같은 결과를 예측하면, 예시는 둘 중 무엇도 고르지 못한다

숫자와 데이터

예시가 설명을 확인해 주려면 경쟁하는 설명이 다른 결과를 냈어야 한다. 두 설명이 똑같이 예측한다면, 예시는 먼저 떠오른 쪽을 믿게 만들 뿐이다.

감지 질문

같은 결과를 낼 수 있는 다른 설명은 무엇인가? 내 예시가 그것을 배제하는가?

경고 신호

“숫자가 그것을 확인해 줘요.”

예시와 해결 방법

예시

한 수업은 퍼널의 첫 단계를 5포인트 올린 것과 마지막 단계를 올린 것을 비교했다. 첫 단계가 이겼고, 본문에는 “방문이 더 많은 곳에서 더 가치가 있다”고 적혀 있었다. 그런데 첫 단계는 전환율이 가장 낮은 단계이기도 했고, 그것이 실제 원인이었다. 첫 단계의 전환율이 더 좋은 퍼널에서는 방문이 더 적어도 마지막 단계가 이긴다. 다른 프로젝트에서는 한 페이지가 2.7초 걸려 로드된다는 이유로 탓을 들었다. 페이지를 하나씩 요청하는 테스트는 수정 없이도 통과했다. 진짜 원인은 요청 40개가 동시에 나가는 것이었다.

해야 할 일

무엇인가를 가르치거나 보고하기 전에, 경쟁하는 설명을 적고 둘이 다르게 예측하는 사례를 만든다. 같은 크기의 부분끼리 비교하고, 예시의 크기를 바꿔 보고, 일반적인 주장은 글로 쓰기 전에 시뮬레이션 데이터로 측정한다. 둘을 가려낼 수 없다면, 그 예시는 두 설명 모두와 양립한다고 적는다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
51

당신에게 뻔한 것이 가르칠 때 가장 먼저 짚어야 할 것이다

글쓰기와 문서

이미 아는 사람은 무의식적으로 하는 단계를 보지 못한다. 그래서 그 사람의 첫 예시에는 새로운 것이 한꺼번에 여러 개 등장하고, 초보자는 첫 줄에서 길을 잃는다.

감지 질문

내 첫 예시에서, 아무것도 모르는 사람에게 새로운 것은 몇 개인가? 내가 요구하는 모든 기호, 단어, 버튼 이름, 동작이 이미 가르쳐졌는가?

경고 신호

“누구나 알잖아요” · “한 줄일 뿐이에요” · “흔한 단어예요.”

예시와 해결 방법

예시

초보자를 위한 프로그래밍 강좌는 한 셀에 새로운 것이 여섯 개나 한꺼번에 나오는 것으로 시작했다. 강의 계획은 자료형이 무엇인지, 그리고 =가 오른쪽에서 왼쪽으로 저장하고 읽는다는 것을 가르치지 않았다. 강좌 운영자는 한 문장으로 말했다. “학생들에 대해 많은 것을 가정하고 있어요.” 이후 세 강의는 “수식을 끌어다 놓듯이”라고 했지만, 끌기를 가르친 강의는 없었다. 그전까지는 “수식을 아래로 복사하기”만 가르쳤다.

해야 할 일

쓰기 전에 예시가 당연하다고 여기는 것(기호, 단어, 클릭, 학습자가 이미 만들었어야 할 것)을 목록으로 적고, 그것을 먼저 가르친다. 한 번에 새로운 개념 하나씩, 기호는 처음 나올 때마다 설명한다. 버튼 이름과 맞는 모든 단어, 그리고 요구하는 모든 동작을 기호를 찾을 때처럼 검색한다. 가능하다면 자동 검사로 각 예시가 쓰는 것과 이미 가르친 것을 비교하게 한다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
52

빠르게 바뀌는 도구에 대해서는 기억이 아니라 오늘의 실제 사용을 바탕으로 쓴다

글쓰기와 문서

몇 달마다 바뀌는 도구에 관한 수업이나 가이드는, 저자가 기억하는 것을 바탕으로 쓰면 쓰는 도중에 이미 낡아 버린다. 첫 독자가 읽기도 전에 전제가 틀렸을 수 있다.

감지 질문

이 글의 전제 중 어떤 것이 도구가 오늘 할 수 있는 일에 의존하는가? 그것을 마지막으로 언제, 어떤 출처로 확인했는가?

경고 신호

“원래 이렇게 동작해요” · “다들 이렇게 해요.”

예시와 해결 방법

예시

“AI로 하는 분석” 모듈의 계획은 “AI는 당신의 데이터를 볼 수 없으니, 표를 붙여 넣는 대신 표를 설명하라”로 시작했다. 강좌 운영자는 이제 에이전트가 데이터베이스에 직접 연결되어 질의를 스스로 실행하고 숫자를 돌려준다고 지적했다. 출처와 날짜가 있는 조사로 확인해 보니, 2년 전에는 채팅창에서 코드를 복사하는 방식이었다. 여러 수업이 여전히 유효한 것을 중심으로 다시 쓰였다. 질문을 정의하기, 에이전트를 감독하기, 숫자를 확인하기.

해야 할 일

빠르게 바뀌는 도구에 대해 쓰기 전에, 출처와 날짜가 있는 현재의 실제 사용법을 찾아본다. 도구가 지금 하는 일, 무엇이 무료인지, 사람들이 실제로 무엇을 쓰는지 확인한다. 다음 버전에도 살아남는 기술(틀 잡기, 감독하기, 검증하기)을 중심으로 글을 짜고, 도구별 단계는 한 곳에 모아 쉽게 갱신할 수 있게 한다. 확인하지 못한 것은 표시하고, 발행하기 전에 직접 해 본다.

확인된 모델claude-opus-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
53

코드는 셸의 문자열 처리가 아니라 편집기로 고친다

콘솔과 도구

소스 파일을 셸의 문자열 도구로 다시 쓰면(읽고, 바꾸고, 다시 쓰기) 코드는 다른 용도로 만들어진 규칙을 거치게 된다. 기본 인코딩, 연산자 우선순위, 따옴표와 이스케이프 규칙이 그것이다. 명령만 보면 변경이 맞아 보이는데, 파일은 명령이 하려는 것처럼 보였던 내용과 다르게 나온다.

감지 질문

이 코드 변경은 편집기를 거치고 있는가, 아니면 셸의 읽기, 바꾸기, 쓰기를 거치면서 그 인코딩, 우선순위, 따옴표 규칙까지 함께 적용받고 있는가?

경고 신호

“그냥 간단히 바꾸는 거라 명령 하나로 끝내면 돼요” · “여러 군데를 한꺼번에 바꾸는 게 더 빨라요”.

예시와 해결 방법

예시

한 세션에서 편집이 두 번 있었고, 둘 다 Windows PowerShell 5.1에서였다. 스크립트를 읽고, 바꾸고, 다시 쓰는 작업(Get-Content, -replace, Set-Content -Encoding utf8)은 파일을 시스템의 ANSI 코드 페이지로 읽은 뒤 UTF-8로 다시 썼다. 그 결과 파일 안의 ✓와 · 는 모두 ✓와 ·로 바뀌었고, 스크립트의 자체 점검도 깨진 기호를 출력했다. 이어서 교체할 내용의 목록을 `@('old', 'new' + "n" + 'more')`로 쓴 작업에서는 줄이 빠졌다. PowerShell에서는 쉼표가 +`보다 강하게 묶이므로, 각 쌍이 네 개의 항목이 되었고 새 텍스트 중 첫 조각만 쓰였다.

해야 할 일

코드는 편집기 자체의 편집 도구와 쓰기 도구로 바꾼다. 변경을 스크립트로 해야 한다면, 스크립트를 파일에 쓰고, UTF-8을 읽고 쓰며 문자열 리터럴이 단순한 인터프리터로 실행한다(node fix.mjs, python -I fix.py). 그다음 diff를 본다. 의도한 것보다 많은 줄이 바뀌었거나 건드리지 않은 문자가 바뀌었다면, 그것은 셸이 한 짓이다.

확인된 모델claude-opus-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
EDU-1

기술 없이도 같은 답이 나온다면, 그 연습문제는 그 기술을 측정하지 않는다

테스트와 점검education

연습문제는 그 기술을 건너뛰는 사람이 다른 결과를 얻을 때에만 그 기술을 확인한다. 시작점, 예시, 지름길이 이미 올바른 답을 만들어 낸다면, 그 연습문제는 모두를 통과시킨다. 연습문제에 적용한 교훈 13이다. 검사는 실수를 거부하는 것을 한 번이라도 본 뒤에야 가치가 있다.

감지 질문

내가 가르치는 것을 정확히 건너뛰거나, 연습문제를 건드리지 않고 제출하는 사람은 어떤 결과를 얻는가? 그것이 올바른 결과와 다른가? 두 계산이 우연히 같아지는 경우(첫 그룹, 첫 단계, 전체 합계)를 골라 버리지 않았는가?

경고 신호

“맞는 답이 나오니까 작동하는 거죠.”

예시와 해결 방법

예시

한 연습문제는 날짜 필터를 써서 여름에 나온 가장 큰 구매를 찾으라고 했다. 그런데 전체 표에서 가장 큰 구매도 여름에 있었다. 날짜 필터 없이도 같은 숫자가 나왔고, 연습문제는 그것을 받아 주었다. 다른 연습문제는 코드에 =가 들어 있어야 한다고 요구했다. 결과를 손으로 total = 1945라고 적어도 통과했다. 검사는 기술이 아니라 글자만 보았다.

해야 할 일

모든 연습문제를 세 번 풀어 본다. 손대지 않은 채로, 가장 가능성 높은 실수를 넣고, 올바르게. 세 번째만 통과해야 한다. 그다음 같은 지름길 목록을 모든 연습문제에 적용한다. 손으로 입력한 숫자, 끝에 답을 덧붙인 시작 코드, 원인이 아니라 증상을 손으로 고친 것, 빈 필수 단어를 쓴 경우, 앞선 시도에서 남은 메모리를 가지고 실행한 경우. 허용 오차는 정답과 가장 흔한 실수 사이의 거리보다 작게 유지하고, 학습자가 쓸 법한 올바른 형태 세 가지를 적어서 옳은 답을 거부하지 않게 한다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
EDU-2

학습자가 답하기 전에 보는 것에는 답이 들어 있으면 안 된다

글쓰기와 문서education

질문은 답이 이미 눈에 보이는 순간 측정을 멈춘다. 그림, 핵심 아이디어, 다른 연습문제의 설명, 단계 제목, 앞선 수업 등 어디에서든 그렇다. 정답을 맞힌 사람은 방금 그것을 읽었을 수도 있다.

감지 질문

학습자가 답하기 전에 이 그림, 이미지, 문구를 보는가, 여기서든 앞선 수업에서든? 정확한 숫자만이 아니라 근사치(“약 25”), 캡션에 적힌 결론, 제목, “방금 보았듯이…”, 또는 앞선 연습문제에서 가장 흔한 오답이 화면에 무엇을 보여 주는지도 포함한다.

경고 신호

“그냥 맥락일 뿐이에요” · “제목일 뿐이에요” · “캡션이에요.”

예시와 해결 방법

예시

올바른 수치가 담긴 삽화가 그것을 묻는 연습문제 바로 위에 있었다. 한 수업은 변수에 새 값을 저장하면 무슨 일이 일어나는지 묻는데, 그 단계의 제목은 ‘다시 저장하면 대체된다’였다. 마지막 퀴즈 아래에 있던 요약을 학습자가 답하기 전에 읽어 버렸다. 첫 시도 뒤에 나타나는 피드백 상자는, 실패한 시도라 해도, 답의 방향을 보여 주었다.

해야 할 일

질문 앞에 보이는 모든 것에서 각 답을 찾아본다. 첫 실패한 시도 뒤에 나타나는 내용, 시작 코드를 실행했을 때 출력되는 것, 내려받을 수 있는 파일, 그림에서 셀 수 있는 것까지 포함한다. 단계 제목과 학습 목표는 마지막에 쓰고, 각 예측의 결과 옆에 두고 읽는다. 자동 검사는 정확한 수치를 찾지만, 근사치와 바꿔 쓴 표현은 답을 염두에 두고 읽는 사람만 찾는다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
EDU-3

그럴듯하게 방어할 수 있는 답이 둘인 질문은 아무것도 측정하지 못한다

글쓰기와 문서education

문제의 문장으로 볼 때 다른 선택지도 옳다고 방어할 수 있다면, 좋은 이유로 ‘틀린’ 것을 고른 사람은 틀렸다고 채점되고, 정답을 맞힌 사람은 운이 좋았던 것일 수 있다. 그 질문이 측정하는 것은 빠진 문장이지, 개념이 아니다.

감지 질문

문제의 문장과 수업에서 가르친 내용만으로, 다른 선택지를 방어할 수 있는가? 그것을 배제하려면 어떤 사실이 필요하며, 그 사실은 적혀 있는가?

경고 신호

“당연히 그런 뜻이죠” · “분명히 이런 의미예요.”

예시와 해결 방법

예시

한 질문은 “매출에 할인이 없었을 때” 빈 할인액을 어떻게 해야 하는지 물었다. 수업은 사실로서 비어 있는 값은 그대로 비워 둔다고 가르쳤으므로 “그대로 둔다”도 방어할 수 있었다. 예상 답인 0으로 채우는 것은 문제가 말하지 않은 것에 달려 있었다. 목표가 전체 판매의 평균이라는 것이다. 다른 문제에서 “핵심 지표는 두 번째 달에 결제하는 사람의 비율이다”라는 문장은 누구의 비율인지 말하지 않았다. 해석에 따라 두 버전의 결과가 같기도 하고 다르기도 했다.

해야 할 일

틀린 선택지마다, 문제와 수업만 사용해서 왜 틀렸는지 한 줄씩 적는다. 배제하려면 적혀 있지 않은 사실이 필요하다면, 그것을 문제에 추가한다. 계산의 목적, 시스템의 규칙, 비율의 분모, 데이터에 대해 알려진 사실 등이다. 분류 연습에서는 각 항목을 자기 범주만이 아니라 모든 범주에 대해 확인한다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
EDU-4

선택지의 위치나 길이로 정답을 맞힐 수 있다면, 퀴즈는 찍기를 측정하는 것이다

테스트와 점검education

각 문항은 그 자체로는 괜찮은데도, 전체 세트가 정답을 드러낼 수 있다. 정답이 항상 두 번째에 있거나, 항상 가장 길거나, 항상 중간 길이다. 학습자는 작성자보다 패턴을 빨리 알아챈다.

감지 질문

선택지의 위치와 길이만 읽고 본문은 읽지 않았을 때, 정답을 세 번에 한 번보다 자주 맞히는가?

경고 신호

“문항마다 확인했고, 전부 맞아요.”

예시와 해결 방법

예시

한 모듈의 마지막 퀴즈에서 정답은 일곱 문항 중 여섯 문항에서 두 번째 선택지였다. 강좌 전체에서는 정답이 가장 긴 선택지인 문항이 55 %였다. 선택지가 세 개일 때 우연히 맞힐 확률은 3분의 1인데도 그랬다. 길이를 손으로 맞춘 뒤에는, 한 수업의 일곱 문항 중 여섯 문항에서 정답이 가장 짧은 선택지가 되었고, 연이은 세 수업의 모든 문항에서는 정답이 중간 길이가 되었다.

해야 할 일

선택지를 보여 줄 때 섞는다. 그 순서는 정답이 원래 어디에 적혔는지와 무관해야 한다. 파일마다 가장 긴 것, 가장 짧은 것, 중간 것의 비율을 재고, 작은 파일들은 모듈 단위로 묶어서 몇 문항이 패턴을 가리지 않게 한다. 집계 결과를 원래 목표와 비교해 읽는다. 균형을 맞추는 작업은 단서를 없애는 대신 자리만 옮길 수 있다.

확인된 모델~opus 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
EDU-5

힌트는 답이 아니라 실수의 원인을 가리켜야 한다

글쓰기와 문서education

힌트는 틀린 시도 뒤에 나타난다. 힌트가 답을 주거나, 풀이 줄을 알려 주거나, 정답과 가장 흔한 실수를 가르는 순서를 알려 준다면, 두 번째 시도는 기술이 아니라 베끼기를 측정하게 된다.

감지 질문

이 힌트를 읽은 사람이 그 기술 없이도 다음 시도를 통과할 수 있는가? 힌트가 답, 풀이 줄, 연습문제가 측정하는 단계, 또는 맞춰야 할 앞선 숫자를 말하고 있는가?

경고 신호

“그냥 살짝 찔러 준 것일 뿐이에요” · “이미 한 번 해 봤잖아요.”

예시와 해결 방법

예시

자동 검사가 있는 실습 277개를 검토하면서, 힌트 82개를 49개 파일에서 바꿨다. 어떤 힌트는 풀이 줄을 그대로 알려 주었다(“두 번째 것이 …”). 어떤 힌트는 정답을 흔한 실수와 가르는 순서를 정해 주었다. “앞선 결과와 대조하기” 연습에서 힌트는 “2.2 수업에서 얻은 결과와 맞아야 합니다”라고 했다. 앞선 숫자를 기억하는 사람은 그 단계를 거치지 않고도 그 숫자를 입력할 수 있었다.

해야 할 일

힌트는 가장 가능성 높은 실수의 원인에 대해 쓴다(“위치는 1이 아니라 0부터 시작한다”). 이미 가르친 내용만 인용한다. “앞선 숫자와 맞아야 한다”는 답한 뒤 보여 주는 해설에 남긴다. 거기서는 두 방법이 같은 숫자를 낸다는 것이 검증이라는 것을 가르칠 수 있다. 힌트는 따로 검토하지 말고, 연습문제에서 가장 흔한 실수에 비추어 검토한다.

확인된 모델claude-opus-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
WEB-1

손상된 저장소가 다음 레코드까지 함께 무너뜨려서는 안 된다

스크립트와 파일web

사이트가 레코드를 어떤 방식으로 저장하든, 한 번의 손상된 쓰기가 그 뒤에 오는 것까지 함께 무너뜨릴 수 있다. 레코드를 줄 단위로 덧붙이면, 잘린 줄이 다음 레코드를 그 위에 붙여 버리고, “손상된 줄”을 건너뛰는 읽기 코드는 둘 다 조용히 버린다. 모든 레코드를 한 파일에 담아 읽고, 바꾸고, 통째로 다시 쓰는 방식이라면, 그 파일을 읽을 수 없게 되는 순간 새 레코드는 모두 실패하고, 아무도 지켜보지 않는 콘솔만 이를 알린다. 이것은 교훈 24의 반대쪽이다. 교훈 24에서는 파일이 비워지고, 여기서는 그 뒤에 오는 것이 사라진다.

감지 질문

저장소가 내일 손상되면, 다음 방문자의 레코드에는 무슨 일이 생기고, 그 사실은 누가 알게 되는가?

경고 신호

“손상된 줄은 건너뛰면 돼요” · “그냥 끝에 덧붙이는 거예요” · “쓰기는 원자적이니까 파일이 깨질 수 없어요”.

예시와 해결 방법

예시

첫 번째 웹 시뮬레이션의 두 실행 모두에서, 양식은 각 메시지를 JSON 한 줄로 저장했고 관리자 패널은 읽지 못하는 줄을 건너뛰었다. 파일 끝에서 줄이 잘린 상태에서 다음 메시지가 “Thanks!”라는 답을 받았고, 저장은 되었지만 관리자 패널에는 끝내 나타나지 않았다. 두 버전 중 하나에는 “손상된 줄: 건너뜀”이라는 주석이 있었다.

또 다른 예시

웹 시뮬레이션을 다시 돌렸을 때 두 실행 모두, 모든 메시지는 JSON 파일 하나에 담겼고 임시 파일에 쓴 뒤 이름을 바꾸는 방식이라 쓰는 도중 충돌이 나도 더는 피해가 없었다. 하지만 파일이 다른 방식으로 손상되면(손으로 고친 경우, 디스크가 가득 찬 경우, 잘못 복원된 경우), 새로 방문하는 사람마다 “Internal error”를 받았고, 관리자 페이지에는 아무것도 보이지 않았으며, 유일한 신호는 서버 콘솔의 스택 트레이스뿐이었다.

해야 할 일

새 레코드가 이전 레코드에 기대지 않게 한다. 줄바꿈으로 끝나는 파일에 덧붙이거나(끝나지 않으면 레코드를 줄바꿈으로 시작한다), 레코드마다 자기 파일에 저장한다. 모든 레코드를 담은 한 파일을 통째로 다시 쓰는 방식은 피한다. 읽을 때는 읽지 못한 것의 개수를 세고, 그 숫자를 소유자가 볼 수 있는 곳에 표시한다. 테스트는 저장소를 손으로 손상시킨 뒤(마지막 줄을 짧게 자르고, 파일을 잘라 낸다) 레코드를 하나 보내 확인한다.

확인된 모델claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
WEB-2

공개 양식에는 첫날부터 봇이 온다

인터페이스와 디자인web

인터넷에 열린 양식은 사람만 채우지 않는다. 자동 제출을 막는 장치가 없고, 메시지를 읽는 사람이 그것을 정리할 수 없다면, 첫 번째 쓰레기 물결이 실제 고객을 묻어 버린다.

감지 질문

내일 가짜 메시지가 천 개 도착한다면, 주인은 진짜 메시지 하나를 어떻게 찾고, 나머지는 어떻게 지우는가?

경고 신호

“작은 사이트라 아무도 공격하지 않아요” · “제한은 나중에 추가해요.”

예시와 해결 방법

예시

웹 시뮬레이션의 두 실행 모두, 문의 양식은 스크립트로부터 몇 초 만에 650개의 메시지를 받았고, 모두 “감사합니다”라는 내용이었다. 관리자에게는 페이지도, 삭제 버튼도 없었다. 관리자 페이지는 100만에서 600만 픽셀 높이로 늘어났고, 모바일에서는 메시지 본문이 화면 밖으로 밀려났다. 두 번 모두 빌더는 이것을 보류 항목으로 기록했다.

해야 할 일

처음부터 저렴한 제동 장치를 둔다. 사람은 채우지 않는 숨김 필드, 주소당 분당 제출 횟수 제한. 그리고 최신순으로 정렬된 페이지가 있는 관리자, 삭제하거나 스팸으로 표시하는 방법. 스크립트로 수백 개의 메시지를 보내고, 휴대폰으로 관리자를 열어 테스트한다.

확인된 모델claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
WEB-3

아무도 테스트하지 않은 대체 동작은 대체 동작이 아니다

인터페이스와 디자인web

method와 action이 있는 양식은 JavaScript가 실패해도 작동하는 대체 경로를 약속한다. 서버가 JavaScript가 기대하는 응답만 한다면 그 약속은 거짓이 되고, 사람은 코드만 바라보게 된다.

감지 질문

이 JavaScript 파일이 로드되지 않으면, 사람은 제출할 때 무엇을 보는가?

경고 신호

“어차피 모두 JavaScript가 있잖아요” · “혹시 몰라서 action은 남겨 둘게요.”

예시와 해결 방법

예시

웹 시뮬레이션의 두 실행 모두, 양식은 JavaScript로 제출했고 method="post"를 선언했다. JavaScript 없이 제출하자, 한 버전에서는 서버가 JSON 한 줄로 제출을 거부했고 메시지는 사라졌다. 다른 버전에서는 메시지를 저장했지만, 빈 페이지에 {"ok":true}만 보여 주었다. 두 번째 버전의 요약은 JavaScript가 없으면 제출하지 않는다고 말하고 있었다.

해야 할 일

둘 중 하나를 정하고 테스트한다. 서버가 일반 제출을 받아서 페이지로 응답하거나(감사 페이지로 리디렉션), 아니면 없는 대체 동작을 양식이 선언하지 않는다. JavaScript를 끄고 한 번 제출해 본다.

확인된 모델claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
WEB-4

버튼을 비활성화하면 포커스도 함께 사라진다

인터페이스와 디자인web

제출하는 동안 버튼을 비활성화하면 두 번 제출되는 것은 막지만, 버튼이 포커스를 잃고 브라우저는 포커스를 문서로 옮긴다. 키보드를 쓰는 사람은 알림을 본 뒤 처음부터 다시 시작해야 한다.

감지 질문

제출한 뒤, 성공하든 실패하든, 포커스는 어디에 놓이고 다음 Tab은 어디로 가는가?

경고 신호

“아무도 두 번 제출하지 못하게 비활성화해요.”

예시와 해결 방법

예시

웹 시뮬레이션의 두 실행 모두, 제출하면 버튼이 비활성화되었다. 서버가 거부한 이메일과 함께 알림이 버튼 아래에 나타났고, 포커스는 문서로 갔다. 다음 Tab은 고쳐야 할 필드와 멀리 떨어진, 페이지의 첫 번째 링크로 사용자를 데려갔다.

해야 할 일

제출이 끝나면 사람이 계속하는 데 필요한 곳에 포커스를 둔다. 오류가 있는 필드(aria-invalid와 옆의 메시지 표시)나 성공 알림에. 또는 비활성화하지 않고 aria-disabled와 플래그를 써서 두 번 제출을 막는다. 키보드만 사용해서 오류를 처리해 본다.

확인된 모델claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기
WEB-5

시도 횟수 제한이 없는 비밀번호 로그인은 가장 약한 비밀번호만큼만 안전하다

인터페이스와 디자인web

틀린 비밀번호에 매번 즉시 응답하는 로그인은 누구나 분당 수천 번 시도할 수 있게 한다. 강력한 기본 비밀번호는 소유자가 직접 비밀번호를 정하기 전까지 이 문제를 가린다. 그리고 소유자가 정한 비밀번호가 짧아도 이를 막을 장치가 없다.

감지 질문

이 로그인에는 1분 동안 틀린 비밀번호를 몇 개나 시도할 수 있고, 다섯 번째 실패 이후에는 무슨 일이 일어나는가?

경고 신호

“기본 비밀번호가 강하니까 괜찮아요” · “관리자 페이지뿐이에요”.

예시와 해결 방법

예시

웹 시뮬레이션을 다시 돌렸을 때 두 실행 모두, 관리자 페이지는 비밀번호를 요구했지만 실패한 시도를 제한하지 않았다. 틀린 비밀번호 200개를 연속으로 보내자 1초도 안 되어 200번의 거부가 돌아왔고, 차단된 것은 없었다. 기본 비밀번호는 길고 무작위였지만, 빌더의 요약은 소유자에게 새 비밀번호를 설정하는 방법을 알려 주면서도 길이를 요구하지는 않았다.

해야 할 일

반복된 실패를 늦추거나 막는다. 주소별과 계정별로, 기다리는 시간을 점점 늘리는 방식으로 적용한다. 소유자가 비밀번호를 정할 때는 최소 길이를 요구한다. 테스트는 틀린 비밀번호를 연달아 스무 번 보내고, 마지막 시도들이 거부되는지 확인한다.

확인된 모델claude-sonnet-5-5 2026-10AI가 번역함. 원어민의 검토를 기다리는 중입니다.GitHub에서 보기

같은 실수를 본 적이 있나요? /ritual share로 공유하세요.