# 코드를 직접 타이핑하라

> Clean Markdown view of GeekNews topic #29677. Use the original source for factual precision when an external source URL is present.

## Metadata

- GeekNews HTML: [https://news.hada.io/topic?id=29677](https://news.hada.io/topic?id=29677)
- GeekNews Markdown: [https://news.hada.io/topic/29677.md](https://news.hada.io/topic/29677.md)
- Type: GN+
- Author: [neo](https://news.hada.io/@neo)
- Published: 2026-05-20T09:03:57+09:00
- Updated: 2026-05-20T09:03:57+09:00
- Original source: [haskellforall.com](https://haskellforall.com/2026/05/type-out-the-code)
- Points: 1
- Comments: 1

## Topic Body

- **코드를 직접 타이핑**하고 기억으로 다시 만드는 훈련은 복사보다 이해와 기억을 더 엄격하게 검증해 줌
- **Freecoding**은 구문, 타입, 이름을 머릿속에 유지한 채 문자 단위로 코드를 작성하는 능력이며 도구 시대에도 필요함
- **구문**은 고수준 사고를 방해하는 잡음이 아니라, 정밀한 의미를 압축해 더 높은 수준의 사고를 가능하게 함
- **타입과 스키마**를 느슨하게 조회만 하면 시스템 설계가 흐려지고, 타입 모델을 이해하지 못하면 `as any` 같은 회피가 늘어남
- **이름 기억**과 선행 작업 이해가 부족하면 에이전트가 중복 구현을 만들기 쉽고, 출력과 테스트 검토도 어려워짐

---

### 코드를 직접 타이핑해야 하는 이유
- Zed Shaw의 “Learn X the hard way” 과정은 예제를 복사·붙여넣기하지 말고 직접 입력하라고 권했고, 최근에는 연습을 끝낸 뒤 삭제하고 기억으로 다시 만들어보는 방식을 더 강하게 권장함
- 능동적으로 내용을 생성하면 같은 내용을 수동적으로 소비할 때보다 이해가 좋아지는 현상은 인지심리학에서 [**생성 효과**](https://en.wikipedia.org/wiki/Generation_effect)로 불림
- Richard Feynman의 “내가 만들 수 없는 것은 이해하지 못한다”는 말처럼, 기억을 바탕으로 코드를 다시 만드는 훈련은 이해와 기억을 동시에 시험함
- 에이전트 코딩 시대에도 개발 도구를 쓰지 말아야 한다는 뜻은 아니지만, 때때로 도구의 편의 없이 **문자 단위로 코드**를 써보는 능력을 길러야 함
- 이런 훈련은 구문, 타입, 이름처럼 프로그래밍의 세부 요소를 머릿속에 유지해 “freecoding”할 수 있게 만드는 데 초점을 둠

### Freecoding과 머릿속 세부 지식
- **Freecoding**은 기억을 바탕으로 코드를 직접 작성할 수 있는 능력이며, 구문·타입·이름 같은 기본 요소를 머릿속에 유지해야 가능함
- ## 구문과 구조
  - 키워드, 문장부호, 언어 구성요소에 익숙해야 함
  - 단순한 문법 암기가 아니라, 코드의 형태를 정확히 떠올리는 능력과 연결됨
- ## 타입과 스키마
  - 타입 시스템과 데이터 모델에 익숙하고 편안해야 함
  - 프로젝트의 테이블, 컬럼, 관계, 타입 구조를 매번 조회하는 수준에 머무르면 시스템 수준 설계가 어려워짐
- ## 이름
  - 함수, 메서드, 클래스, import, 파일, 패키지 이름을 정확히 떠올릴 수 있어야 함
  - 프로젝트와 의존성이 바뀌면 이 지식도 함께 최신 상태로 유지해야 함
  - 머릿속에 떠올린 코드를 일정 수준의 정밀도로 타이핑하지 못한다면, 실제로는 그 내용을 명확히 이해한 것이 아니라 이해한다고 착각한 상태에 가까움
  - 영어는 코드만큼 정밀한 언어가 아니며, 충분히 상세한 명세는 결국 코드에 가까워진다는 별도 글 [A sufficiently detailed spec is code](https://haskellforall.com/2026/03/a-sufficiently-detailed-spec-is-code)와도 연결됨

### 구문은 고수준 사고를 가능하게 함
- IDE나 코딩 에이전트가 구문을 맞춰줄 수 있어도, 구문을 직접 다루는 능력은 여전히 중요함
- 괄호를 맞추는 데 어려움을 겪는다면, 다른 사람의 논리적 전제와 결론을 유창하게 연결하는 능력에도 의문이 생길 수 있음
- 세부 사항을 무시하는 태도는 단어의 의미를 명확히 따지기보다 분위기로 소통하는 **기능적 비문해성**과 이어질 수 있음
- LLM 프롬프트 예시는 겉보기에는 그럴듯하지만, 자세히 읽으면 서로 반대되는 지시를 동시에 포함함
  - “위에 나열된 skill에 포함되지 않은 외부 도구나 대안을 제안하지 말라”
  - “작업이 사용 가능한 skill을 넘어서는 능력을 요구하면 그렇게 말하라”
- 작은 문법·철자·구조를 정확히 다루는 능력과 큰 그림을 정확히 이해하는 능력은 분리되지 않음
- **구문**은 고수준 사고를 방해하는 세부사항이 아니라, 더 높은 수준의 사고를 압축하고 가능하게 하는 정신적 도구임
- 자연어 설명보다 타입 표기가 더 정밀하고 간결할 수 있음
  ```text
  x는 객체의 배열이며, 각 객체에는 문자열을 저장하는 필수 domain 속성과 숫자를 저장하는 선택적 port 속성이 있다
  ```
  ```ts
  x : { domain: string, port?: number }[]
  ```

### 타입과 스키마는 시스템 설계의 핵심 단서
- Fred Brooks는 [The Mythical Man-Month](https://en.wikipedia.org/wiki/The_Mythical_Man-Month)에서 테이블을 보여주면 흐름도 없이도 대개 구조가 명확해진다고 말함
- 데이터베이스를 사용한다면 프로젝트의 테이블, 컬럼 이름, 관계를 앞뒤로 꿰고 있어야 함
- 이 정보를 필요할 때마다 느슨하게 조회하는 대신, 사전에 파악하고 머릿속에 유지해야 효과적인 **시스템 수준 설계**가 가능함
- 이런 노력을 하지 않으면 생각이 혼란스러운 만큼 데이터베이스 스키마도 중복·유사 데이터가 많은 비정규화 구조가 되기 쉬움
- Rust나 Haskell 같은 강한 타입 언어 경험은 타입에 대한 강한 정신 모델의 이점을 잘 드러냄
- 정확한 “정신적 타입 검사기”나 “정신적 borrow checker”를 기르는 훈련은 약한 타입 언어를 사용할 때도 도움이 됨
- 이런 추상적 추론 근육을 쓰지 않으면 [**불가능한 상태를 표현 불가능하게 만들기**](https://www.awwsmm.com/blog/make-invalid-states-unrepresentable) 같은 데이터 모델링 기본도 놓치기 쉬움
- 타입이 어떻게 맞물리는지 이해하지 못하면 TypeScript 코드에 `as any`를 흩뿌리게 됨
- 정상 경로에서 타입을 생각하는 불편함을 감당하지 못하면, 타입 오류를 디버깅하는 비정상 경로는 더 견디기 어려움
- Haskeller나 Rustacean이 항상 더 나은 코드를 쓴다는 뜻은 아니지만, 다른 조건이 같다면 타입에 유창한 것이 도움이 됨

### 이름을 기억해야 재사용할 수 있음
- 프로젝트나 의존성에서 자주 쓰는 함수, 메서드, 클래스, import, 패키지, 파일 이름은 쉽게 떠올릴 수 있어야 함
- 이는 이미 만들어진 것, 즉 **선행 작업(prior art)** 에 익숙해야 한다는 더 일반적인 원칙의 특수한 형태임
- 많은 사람이 코딩 에이전트에 기대는 이유는 원하는 기능을 이미 수행하는 재사용 가능한 선행 작업을 모르기 때문이며, 그 결과 에이전트에게 바퀴를 다시 만들게 함
- [SaaS boilerplate projects](https://github.com/topics/saas-boilerplate)의 존재를 모르면 에이전트가 처음부터 스캐폴딩해야 한다고 생각하기 쉬움
- 이 목적을 위해 만들어진 검증된 오픈소스 프로젝트를 복제하는 것이 에이전트에게 같은 작업을 요청하는 것보다 더 빠르고, 싸고, 신뢰할 수 있음
- 누군가 LLM이 몇 년 안에 브라우저 전체를 만들 수 있을 것이라고 예측했을 때, Chromium을 포크하면 이미 오늘 가능하며 수정과 유지보수도 더 쉽다는 반론이 가능함
- 같은 프로젝트나 회사 내부의 코드 재사용에도 이름 기억은 중요함
- 무엇을 찾아야 하는지 모르면 동료의 작업 위에 쌓아 올릴 수 없음

### 에이전트 출력 검토에는 사람의 이해가 필요함
- 에이전트는 이름 탐색과 코드 생성에 도움을 줄 수 있지만, 출력물을 의미 있게 검토할 수 있는지가 새 문제가 됨
- 기존 기능을 모르면 에이전트가 기능을 중복 구현하는지 판단하기 어려움
- 에이전트보다 코드를 더 못 이해하는 상태에서는 에이전트 출력의 품질도 제대로 검토하기 어려움
- 에이전트에게 테스트 생성을 요청할 수는 있지만, 생성된 테스트를 면밀히 살피지 않으면 테스트 자체가 의미 없는 코드가 될 수 있음
- 실제 예시는 구현 코드를 호출하지 않고 배열과 문자열에 직접 `some`이나 `includes`를 적용해 기대값만 확인하는 테스트였음
  ```ts
  describe("abort detection logic", () => {
    it("detects aborted stopReason in messages", () => {
      const messages = [
        { role: "assistant", stopReason: "aborted", content: [] },
      ];
      const isAborted = messages.some((m: any) => m.stopReason === "aborted");
      expect(isAborted).toBe(true);
    });
  
    it("detects abort in error string", () => {
      const error = "The operation was aborted";
      const isAborted = error.includes("abort");
      expect(isAborted).toBe(true);
    });
  
    it("does not false-positive on normal errors", () => {
      const error = "Network timeout";
      const isAborted = error.includes("abort");
      expect(isAborted).toBe(false);
    });
  
    it("does not false-positive on normal stop reasons", () => {
      const messages = [
        { role: "assistant", stopReason: "stop", content: [] },
      ];
      const isAborted = messages.some((m: any) => m.stopReason === "aborted");
      expect(isAborted).toBe(false);
    });
  });
  ```
- 소프트웨어 개발에는 일상적인 마찰이 많고, 이름을 기억하는 작은 마찰을 넘지 않기로 선택하면 테스트를 검토하는 더 큰 마찰도 넘지 않게 됨
- 코딩 에이전트는 사용자의 지시를 주요 맥락으로 삼기 때문에, 지적으로 게으른 사용자는 에이전트도 비슷하게 게으른 방향으로 몰고 갈 수 있음

### 끈기와 숙련은 분리되지 않음
- [**Eustress**](https://en.wikipedia.org/wiki/Eustress)는 유익한 스트레스이며, 새롭고 어려운 일을 하도록 자신을 밀어붙이면 작은 불편에 대한 내성이 생기고 더 큰 불편도 넘을 수 있게 됨
- 항상 불편을 피하면 무력감과 좌절이 커지는 악순환으로 내려감
- 한 영역에서 정밀성, 기억, 구조적 사고를 기르면 다른 영역의 능력도 함께 좋아짐
- LLM이 훈련 데이터에서 일반화하듯, 인간도 한 영역에서 기른 습관과 능력을 다른 영역으로 일반화함
- 소프트웨어 개발은 본질적으로 편안한 영역을 정기적으로 벗어나는 일을 포함하며, 관련 글 [Software engineers are not (and should not be) technicians](https://haskellforall.com/2024/07/software-engineers-are-not-and-should)와 같은 맥락에 있음

## Comments



### Comment 57872

- Author: neo
- Created: 2026-05-20T09:03:58+09:00
- Points: 1

###### [Lobste.rs 의견들](https://lobste.rs/s/zotppg/type_out_code) 
- 전적으로 동의함. 연습문제를 끝낸 뒤 **방금 한 것을 지우고 기억만으로 다시 해보는 것**은 정말 중요함  
  막히면 단서를 보되, 방금 한 과정을 최대한 기억에서 재구성하려는 습관만큼 중요한 게 많지 않음

- **커밋 메시지와 문서**는 직접 타이핑하는 게 좋음  
  프로그래머들은 이런 글쓰기를 싫어해서 “LLM이 써주면 되지”라고 하기 쉽지만, 직접 쓰면 사용자 경험과 구현 결정을 한곳에서 마주하게 됨. “X를 하려면 `-Y`를 넘긴다… 잠깐, 이게 최선인가?” “이건 Y로 X를 고친다… 그런데 Z로도 가능하지 않나?” 같은 검토가 생김
  - 이걸 **튜토리얼 주도 개발**이라고 부르곤 함. 나중에 사용자 경험을 생각하는 대신, 원하는 사용자 경험에서 출발해 튜토리얼을 쓰고 거꾸로 작업하는 방식임

- “괄호 균형 맞추기를 어려워한다면, 남의 논리적 전제와 결론을 얼마나 유창하게 연결할 수 있을지 의심된다”는 대목에서 웃었는데, 잠깐 뜨끔했음  
  변명하자면 함수가 가끔 너무 거대해질 때가 있음

- 이해하지 못한 **바이브코딩 쓰레기**를 고치는 것도 실제로는 배우기 좋은 방법임. 타이핑을 많이 하게 되고, 진공 상태가 아니라 실제 맥락 안에서 작업하게 됨
  - 최근에 어느 정도 돌아가지만 별로 좋지 않은 걸 바이브코딩으로 만들었고, 코드는 정말 엉망이었음  
    그걸 손으로 다시 작성하면서 지난 8개월 동안 녹슬어가던 프로그래밍 감각을 다시 익히는 기회로 삼았음. 재작성 결과가 마음에 들고 실제로 더 잘 동작함. LLM은 여전히 설명하거나 막힌 부분을 푸는 데 유용하지만, 코드베이스 전체를 내가 안다는 느낌이 훨씬 좋음
  - 경우에 따라 다름. 돼지에 립스틱을 다시 칠해도 결국 **돼지**인 경우가 있음

- “나열된 능력에 없는 외부 도구나 대안을 절대 제안하지 말라. 작업에 사용 가능한 능력을 넘어서는 기능이 필요하면 그렇게 말하라”는 프롬프트가 왜 서로 반대되는 지시인지 잘 모르겠음  
  “제공된 능력만으로는 이걸 할 수 없습니다”라고 말하는 건 두 지시와 모두 일관됨. 마지막 문장이 “필요한 능력이 무엇인지 말하라”였다면 충돌하겠지만, 현재 문장만 보면 모순이 보이지 않음
  - 맞는 해석 같지만, 프롬프트 작성자는 LLM이 단순히 “죄송합니다, 다른 능력이 필요하지만 말할 수 없습니다”가 아니라 **무엇이 필요한지** 말하길 의도했을 가능성이 큼. 물론 정말 문장 그대로 의도했을 수도 있음
  - “제공된 능력만으로는 할 수 없습니다”라는 응답은 두 번째 지시와 일관되지 않는다고 봄  
    두 번째 문장은 모델이 필요한 외부 도구나 대안의 존재를 부정으로 암시하는 게 아니라, **구성적으로 존재를 긍정**하라고 지시하는 것으로 읽힘

- “기능적으로 명료하게 표현하지 못하는 사람들은 거의 예외 없이 맞춤법이나 문법적으로 올바른 문장 작성도 어려워한다”는 말은 **난독증**이 있거나 단지 다르게 사고하는 사람들에 대한 꽤 거친 편견으로 보임  
  물론 맞춤법이나 문법을 못 쓴다고 해서 곧바로 기능적으로 명료하지 않다는 역도 주장한 건 아니겠지만, 어느 쪽이든 관용적이지 않은 표현임  
  더 건설적으로 보자면, 노드 편집기를 생각해볼 수 있음. 노드 기반 시스템은 현재 구현들에 문제가 많지만, 잘 만들면 프로그램 작성 방식을 통제해서 일부 구문 오류를 아예 걸러낼 수 있음. 예를 들어 어떤 노드가 문자열을 받는다면 숫자를 넘길 수 없음. 빌드 시점이나 실행 시점에 제약을 강제해서가 아니라, 애초에 숫자를 그 자리에 “말할 수 없게” 만들기 때문임. 잘못된 반복 범위, 인자 개수 오류, 괄호 불균형 같은 것도 구조상 틀릴 수 없게 만들 수 있음  
  어떤 제약을 구조적으로 강제하는 도구로 소프트웨어를 작성한다고 해서 그 제약을 이해하지 못한다는 뜻은 아님. 단지 그 종류의 오류에서 실수로 잘못 입력할 걱정을 덜어준다는 뜻임. 함수의 중괄호 개수나 논리 블록의 들여쓰기 같은 구문 세부사항을 도구가 챙겨주지 않을 때 답답함을 느낀다고 해서, 왜 그 구문을 신경 써야 하는지 이해하지 못한다는 뜻도 아님  
  노드 시스템을 예로 든 이유는 LLM의 “던져놓고 잊기”나 뇌를 끄는 바이브코딩 요소를 제거하고, **구문 문제**만 분리해 보여주기 때문임. LLM을 빼고 보면 구문에 초점을 맞추는 주장은 꽤 약해짐  
  글의 나머지에는 동의하지만, 구문 능력을 누군가의 코드 이해력이나 좋은 코드 작성 능력의 근본 지표처럼 보는 건 매우 잘못된 방향이라고 봄
  - 맞춤법이나 문법적으로 올바른 문장을 못 쓴다고 해서 기능적으로 명료하지 않다고 말하려는 건 아님  
    선의의 피드백이라는 점도 이해하고, 방어적으로 보이고 싶지는 않음. 그런 관용 없는 주장처럼 들리지 않도록 표현하려고 노력했다고 생각하지만, 같은 내용을 더 잘 전달할 다른 문구나 구성이 있다면 열려 있음  
    다만 그 요지를 아예 삭제하고 싶지는 않음. 전달하려는 핵심은 사람이 정신적 불편함을 [경험적으로 회피](https://en.wikipedia.org/wiki/Experiential_avoidance)하기 시작할 때 보통 **맞춤법과 문법**이 가장 먼저 무너진다는 것임. 난독증이 있는 사람들이 그 과정에서 피해를 보지 않도록 주장을 조정할 방법은 있을 것 같음
