Part 1: 코드를 더 잘 읽기 위하여
- 코드 읽기는 프로그래밍의 핵심이지만, 대부분의 전문 개발자조차 체계적으로 훈련받지 못함
- 연구에 따르면 프로그래머의 시간 약 60%가 코드를 이해하는 데 소비됨 (쓰는 것이 아님)
- 파트 1의 목표: 코드 읽기가 왜 어려운지 이해하고, 더 잘 읽을 수 있는 방법 습득
1챕터: 코딩 중 혼란 해독하기
1.1 코드의 혼란 유형 3가지
- 세 가지 프로그램(APL, Java, BASIC)의 이진 변환 예제로 혼란의 종류를 구분
- 혼란은 항상 불쾌하지만, 원인은 서로 다름 → 원인을 정확히 아는 것이 중요
혼란 유형 1: 지식 부족
- 예: APL 프로그램의
⊤연산자 → 모르면 이해 불가 - 프로그래밍 언어, 알고리즘, 도메인에 대한 사전 지식이 없는 경우
- 관련 인지 과정: 장기 기억(LTM)
혼란 유형 2: 정보 부족
- 예: Java의
Integer.toBinaryString()→ 이름으로 기능을 추측하지만 내부 동작을 모름 - 코드 실행에 필요한 정보가 현재 보이는 코드 밖(라이브러리, 다른 모듈 등)에 있음
- 관련 인지 과정: 단기 기억(STM)
혼란 유형 3: 처리 능력 부족
- 예: BASIC 프로그램의 모든 중간값을 머릿속으로 추적하는 것이 불가
- 변수 추적, 루프 실행 등 복잡한 연산을 동시에 머리에 담기 어려움
- 관련 인지 과정: 작업 기억(Working Memory)
- 종이에 중간값을 적어야 한다는 느낌 자체가 작업 기억 초과의 신호
1.2 세 가지 인지 과정
1.2.1 장기 기억
- 컴퓨터의 하드 드라이브에 비유 → 오랫동안 정보 보관
- 저장 내용 예시: Java 키워드 의미, 알고리즘 이름, 이전 경험, Java의
MAX_INT = 2147483647 - APL을 아는 사람은
⊤가 dyadic encode function임을 LTM에서 즉시 호출 → 프로그램이 자명해짐 - 프로그래밍에서 구문 지식, 알고리즘 지식, 도메인 지식 모두 LTM에 저장
1.2.2 단기 기억
- 컴퓨터의 RAM에 비유 → 잠시 정보를 임시 보관
- 용량: 최신 연구에서 2~6개 항목만 저장 가능
- 지속 시간: 약 30초 이내 → 저장 못 하면 소실
- Java 코드 읽을 때:
n이 정수라는 정보를 STM에 임시 보관하며 다음 라인 해석 - STM과 LTM은 상호작용:
mian을main으로 자동 수정하는 것은 LTM의 경험이 STM을 덮어쓴 예시
1.2.3 작업 기억
- 컴퓨터의 프로세서에 비유 → 실제 사고·연산이 일어나는 곳
- STM과 LTM은 저장 장치, 작업 기억은 처리 장치
- 트레이싱(tracing): 코드를 정신적으로 컴파일·실행하는 행위 → 작업 기억 사용
- 용량 한계: STM과 동일하게 2~6개 항목 → 인지 부하(Cognitive Load) 개념
1.3 세 인지 과정의 협력
- 세 과정은 분리된 것이 아니라 항상 함께 작동
- 정보 흐름:
- 감각 기관으로 정보 입력
- STM에 임시 저장
- LTM에서 관련 지식 탐색
- 작업 기억에서 두 정보를 결합해 사고·문제 해결
- 버그 리포트 예시: STM(새 버그 정보) + LTM(과거 actor 모델 구현 기억, off-by-one 해결법) → 작업 기억에서 통합 처리
| 혼란 유형 | 관련 인지 과정 | 비유 |
|---|---|---|
| 지식 부족 | LTM | 하드 드라이브에 파일 없음 |
| 정보 부족 | STM | RAM에 로드 안 됨 |
| 처리 능력 부족 | Working Memory | CPU 과부하 |
2챕터: 코드 속독
2.1 코드를 빠르게 읽기
- insertion sort Java 코드를 3분 보고 재현하는 연습 → STM + LTM 동시 사용 확인
- LTM의 두 가지 기여 방식:
- Java 구문 지식(for-loop 패턴,
System.out.println등)으로 빈칸 보완 - “이건 insertion sort다”라는 알고리즘 지식으로 세부 구현 추론
- Java 구문 지식(for-loop 패턴,
낯선 코드는 왜 더 어려운가
- 알고리즘 이름을 모르면 LTM의 도움을 전혀 받을 수 없음
- 의도적으로 이상한 변수명(
b,l)을 쓴 코드는 패턴 인식 불가 → 기억하기 훨씬 어려움 l과1이 시각적으로 유사 → 오인 발생, 인지 혼란 가중
2.2 기억 용량 한계 극복: 청킹
STM의 한계
- George Miller(1956), “The Magical Number Seven, Plus or Minus Two”: STM 용량 7±2
- 최신 연구 기준: 2~6개 항목
- 지속 시간: 30초 이내
- 그럼에도 사람이 많은 것을 기억할 수 있는 이유 → 청킹(Chunking)
2.2.1 청킹의 힘: de Groot의 체스 실험
- Adrian de Groot(네덜란드 수학자, 체스 선수)의 두 가지 실험:
- 실험 1: 현실적 체스 배치 기억 → 전문가 >> 일반인
- 실험 2: 무작위 체스 배치 기억 → 전문가 = 일반인 (차이 없음)
- 핵심 발견: 전문가의 STM이 더 큰 게 아님 → LTM에 저장된 패턴(청크)으로 정보를 묶는 것
- 전문가: “시칠리안 오프닝인데 나이트가 왼쪽으로 두 칸” → 4개 항목
- 일반인: 말 위치 하나하나 기억 → STM 즉시 초과
- de Groot가 명명한 개념 = 청크(Chunk): LTM의 묶음 단위, STM에서 한 슬롯 차지
2.2.2 프로그래머의 청킹 실험
- Bell Labs 연구자 Katherine McKeithen이 de Groot 실험을 프로그래밍에 적용
- 53명 대상 (초급·중급·전문가) → 30줄 ALGOL 프로그램 기억 테스트
- 일반 프로그램: 전문가 > 중급 > 초급 (명확한 차이)
- 뒤섞인 프로그램: 세 그룹 모두 비슷하게 낮음
- 교훈: 초급자는 전문가에 비해 처리 가능한 코드 양이 훨씬 적다 → 신규 팀원 온보딩 시 고려 필요
청킹 실험
abk mrtpi gbar→ 기억하기 매우 어려움 (의미 없는 글자)xzf gba krt→ 여전히 어려움 (알파벳은 알지만 단어 아님)cat loves cake→ 쉬움 → 3개 청크로 묶임, STM 용량 내
2.3 아이코닉 메모리: 눈에 보이는 것보다 더 많이 저장
감각 기억과 아이코닉 메모리
- 정보 흐름: 외부 자극 → 감각 기억(Sensory Memory) → STM → 작업 기억
- 컴퓨터 비유: 감각 기억 = I/O 버퍼
- 시각 채널의 감각 기억 = 아이코닉 메모리(Iconic Memory)
- 비유: 새해 불꽃에 글자를 쓸 수 있는 이유, 눈 감고 나서도 페이지 형태가 보이는 이유
2.3.1 George Sperling의 아이코닉 메모리 실험
- 3×3 또는 3×4 글자 그리드를 0.05초(50ms) 동안 노출
- 결과: 무작위로 선택된 한 행의 글자를 75% 확률로 기억
- 해석: **그리드 전체(9~12개)**가 아이코닉 메모리에 저장됨 → STM 용량(6개)을 초과
- 전체 재현 시: 절반 정도만 기억 → STM 한계와 일치
- 결론: 아이코닉 메모리 > STM 용량 → 모든 정보가 STM으로 이동하지 않음
아이코닉 메모리와 코드 읽기
- 코드를 보는 즉시 전체 구조가 아이코닉 메모리에 저장 → 의식하지 못해도
- 세부 사항을 놓치는 것은 실수가 아닌 뇌의 자연스러운 선택
- 활용 방법: 코드 훑어보기(Code at a Glance) 연습
- 몇 초간 코드를 보고 가린 후 질문에 답하기:
- 코드의 구조는? 깊게 중첩됐나 평평한가?
- 눈에 띄는 줄이 있나?
- 공백이나 빈 공간은 어떻게 활용됐나?
- 몇 초간 코드를 보고 가린 후 질문에 답하기:
2.3.2 기억 순서가 청킹의 단서
- 기억한 내용뿐 아니라 기억한 순서도 진단 도구
- McKeithen의 ALGOL 21개 키워드 기억 실험:
- 초급자:
TRUE IS REAL THEN FALSE(문장 형태로 묶음, 의미 없는 그룹) - 전문가:
TRUE/FALSE,IF/THEN/ELSE(프로그래밍 구조 기반 그룹)
- 초급자:
- 전문가는 코드를 의미 기반 구조로 청킹함 → 다른 방식으로 코드를 “봄”
2.4 청크 가능한 코드 작성법
디자인 패턴 사용
- Walter Tichy(카를스루에 공과대학) 연구: 디자인 패턴을 아는 프로그래머는 패턴이 적용된 코드를 유지보수하는 시간이 더 짧음
- 패턴 학습 후 유지보수 시간 감소 (특히 Observer 패턴 효과 큼)
- 결론: 디자인 패턴은 LTM에 저장된 청크 → 코드 읽기 속도 향상
주석 작성
- Martha Crosby(하와이대학) 연구: 초급자는 주석을 훨씬 많이 참조
- Quiyin Fan(2010) 연구: 개발자는 코드 이해 시 주석에 강하게 의존
- 고수준 주석(
"이 함수는 이진 트리를 순서대로 출력합니다") → 큰 코드 청크 가능 - 저수준 주석(
"i를 1 증가시킵니다") → 청킹 방해, 오히려 부담
- 고수준 주석(
비콘 포함
- 비콘: 프로그래머가 코드를 이해하는 데 도움이 되는 코드 요소 → “아하!” 순간을 만드는 힌트
- 단순 비콘(Simple Beacon): 의미 있는 변수명(
root,tree), 연산자, 구조문 - 복합 비콘(Compound Beacon): 단순 비콘들의 조합 (
self.left+self.right→ 이진 트리) - Crosby 연구: 전문가는 비콘을 적극 활용, 초급자는 그렇지 못함
- 비콘 종류: 변수명, 클래스명, 메서드명, 빈 리스트 초기화, swap 패턴 등
2.5 청킹 의도적 연습법
- 코드 재현 연습(Exercise 2.6):
- 친숙하지 않은 코드 선택 (아는 언어, 최대 50줄)
- 최대 2분 학습
- 코드 덮고 재현
- 원본과 비교 → 잘 재현한 부분 = 이미 아는 지식, 못 한 부분 = 모르는 개념
- 동료와 비교 → 상대적 숙련도 파악
- 핵심 원칙: 기억할 수 있는 것 = 알고 있는 것 → 자기 지식 수준 진단 도구
3챕터: 프로그래밍 구문을 빠르게 배우기
3.1 구문을 외워야 하는 이유
구문 지식과 청킹의 관계
- “그냥 구글링하면 되지 않나?” → 두 가지 이유로 충분하지 않음:
- 이미 아는 지식이 많을수록 코드를 더 효율적으로 청킹 가능 (2챕터 핵심)
- 인터넷 검색 자체가 집중력을 끊는 방해 요소
3.1.1 방해의 비용
- 노스 캐롤라이나 주립대학 Chris Parnin: 85명의 프로그래머의 10,000회 프로그래밍 세션 기록
- 결과:
- 이메일·동료에 의한 방해 후 코드로 돌아오는 데 평균 15분 소요
- 메서드 편집 중 방해 시 1분 내 복귀한 경우: 10%에 불과
- 복귀 후 이전 맥락을 재구성하기 위해 코드베이스 여러 곳 탐색 필요
- 결론: 구문을 찾기 위한 짧은 검색 하나도 집중 흐름을 크게 깬다
3.2 플래시카드로 구문 빠르게 배우기
기본 방법
- 한쪽: 개념(프롬프트), 반대쪽: 해당 코드
- 사용법: 프롬프트 쪽을 보고 코드를 먼저 떠올려 적은 후 → 뒤집어 확인
- 보기만 하지 말고 먼저 떠올리는 것이 핵심 (수동 학습 vs 능동 학습)
- Python list comprehension 예시 카드:
기본 컴프리헨션→[x for x in numbers]필터 포함→[x for x in numbers if x % 2 == 1]
- 디지털 앱: Anki, Cerego, Quizlet 등 → 복습 타이밍 자동 알림
3.2.1 언제 사용할까
- 매일 꾸준히 사용 → 수 주 후 구문 어휘 급증
- 구글링 전에 먼저 시도하는 습관이 중요
3.2.2 카드 추가 시점
- 새 언어/프레임워크/라이브러리 학습 시 → 새 개념 만날 때마다 즉시 추가
- 구글링하려는 순간 → 아직 모른다는 신호 → 카드 추가 후 검색
- 단, 모든 API를 외울 필요는 없음 → 자주 쓰는 것, 핵심적인 것만
3.2.3 카드 줄이기
- 카드에 정답/오답 횟수 tally 기록
- 여러 번 연속 맞춘 카드 → 제거 (이미 LTM에 안착)
- 디지털 앱은 자동으로 처리
3.3 망각과 싸우는 법
LTM의 한계
- LTM도 영구적이지 않음 → 망각 곡선(Forgetting Curve) 존재
- Hermann Ebbinghaus(독일 심리학자, 1870년대)가 자기 자신을 실험 대상으로 연구
- 1시간 후: 배운 것의 약 50% 망각
- 2일 후: 약 75% 망각
- 복습 없이는 급격히 소실
3.3.1 왜 망각하는가: 기억의 두 가지 강도
Robert & Elizabeth Bjork (UCLA 심리학 교수) 개념:
- 저장 강도 (Storage Strength): 얼마나 잘 저장됐는가
- 반복할수록 증가, 사실상 감소하지 않음
- 구구단 같은 것 → 저장 강도 매우 높음
- 인출 강도 (Retrieval Strength): 얼마나 쉽게 떠올릴 수 있는가
- 시간이 지나면 감소 → “알긴 아는데 생각이 안 나” 현상의 원인
- 연습을 통해 강화 가능
- 구문 검색의 문제: 자꾸 찾아보니 뇌가 “외울 필요 없다”고 판단 → 인출 강도가 강화되지 않는 악순환
간격 반복
- Harry Bahrick의 연구: 50개의 단어를 6그룹으로 나눠 다른 간격으로 학습
- 8주 간격으로 26번 학습 그룹 → 1년 후 76% 기억
- 2주 간격 그룹 → 1년 후 56% 기억
- 핵심: 더 오래 공부하는 것이 아니라 더 넓은 간격으로 분산해서 반복
- 한 번에 몰아서 외우면 금방 잊음 (부트캠프, 단기 집중 학습의 한계)
- 실천: 월 1회 플래시카드 복습으로도 충분히 장기 기억 유지 가능
3.4 구문을 더 오래 기억하는 법
3.4.1 인출 연습
- 단순히 보는 것이 아니라 능동적으로 기억해내는 행위 자체가 기억을 강화
- Philip Boswood Ballard(1913): 학생들에게 시를 외우게 하고 예고 없이 2일 후 재시험
- 추가 학습 없이도 10% 더 기억 → 이후에도 계속 상승
- C++ 리스트 역순 순회 코드 예시: 6가지 유사 옵션 중 맞는 것을 고르기 어려움 → 단순 노출만으로는 인출 강도 높아지지 않음
- 실천: 구글링 전에 먼저 기억하려 시도 → 실패해도 그 시도 자체가 기억을 강화
3.4.2 정교화
- 새 정보를 기존 기억과 의도적으로 연결하는 행위 → LTM 네트워크 강화
스키마
- LTM은 계층 구조(폴더-파일)가 아닌 네트워크 구조로 저장
- 새 정보를 기존 스키마에 연결할수록 쉽게 기억
- 예:
1, 3, 15, 127, 63, 31→ “이진수로 표현하면 전부 1로만 이루어진 수” → 스키마에 연결, 기억 쉬움 - Frederic Bartlett(1930년대): 기억 저장 시 기존 스키마에 맞게 변형되기도 함
정교화 방법
- 이 개념은 어떤 다른 개념을 떠올리게 하나?
- 왜 그 개념이 떠오르나? 구문 유사? 사용 맥락 유사?
- 이 개념의 대안은? 같은 목표를 달성하는 다른 방법은?
- 다른 프로그래밍 언어에도 유사 개념이 있나? 어떻게 다른가?
- 이 개념이 특정 패러다임/도메인/라이브러리에 속하나?
- 예: Python
list comprehension배울 때 → for-loop와의 관계, 다른 언어의 map/filter와 비교, 언제 쓰면 좋은지 생각 → 기억 네트워크 강화
전체 파트 1 핵심 요약
| 챕터 | 핵심 통찰 | 실천 방법 |
|---|---|---|
| 1챕터 | 혼란에는 3종류 있음 (지식/정보/처리력 부족), 뇌의 인지 과정 3개 (LTM/STM/작업기억) | 혼란의 원인을 정확히 진단하기 |
| 2챕터 | 청킹이 코드 읽기 속도를 결정함, LTM이 풍부할수록 청크 크기가 커짐 | 코드 재현 연습, 비콘·주석·디자인 패턴 활용 |
| 3챕터 | 구문 암기는 청킹 능력 향상의 핵심, 단순 노출이 아닌 인출 연습+간격 반복이 필요 | 플래시카드(Anki 등) + 월 1회 반복 + 정교화 질문 |
The Programmer’s Brain — Part 2: 코드에 대해 생각하기
파트 2 개요: 파트 1이 STM·LTM·작업기억을 다뤘다면, 파트 2는 코드를 단순히 읽는 것을 넘어 깊이 이해하고 사고하는 방법 — 변수의 역할 파악, 멘탈 모델 구축, 오개념(버그의 뿌리) 극복 — 에 집중한다.
5챕터: 코드에 대한 깊은 이해
5.1 변수의 역할 프레임워크
5.1.1 배경과 목적
- 구문 지식·변수 간 관계 파악은 이해의 첫 단계일 뿐 → 더 깊은 이해는 변수가 무슨 역할을 하는지 아는 것에서 시작
- 핀란드 동부 대학 교수 Jorma Sajaniemi: 프로그래머들은 LTM에 변수를 연결할 적절한 스키마가 없어서 변수 이해에 어려움을 겪음
- 기존 개념들은 너무 넓거나(
variable,integer) 너무 좁음(특정 변수명) → 그 중간 수준의 역할 프레임워크가 필요 - 변수의 역할(role) = 프로그램 안에서 그 변수가 무슨 일을 하는지를 나타내는 중간 수준의 추상화
5.1.2 Sajaniemi의 11가지 변수 역할
| 역할 | 설명 | 예시 |
|---|---|---|
| Fixed value | 초기화 후 값이 변하지 않음 | 상수 pi, 파일에서 읽은 설정값 |
| Stepper | 루프 내에서 값의 연속을 순서대로 밟아나감. 값의 흐름이 미리 예측 가능 | for i in range(n)의 i |
| Flag | 어떤 일이 일어났는지/상태를 나타냄 | is_set, is_error (주로 Boolean) |
| Walker | Stepper처럼 자료구조를 순회하나, 순회 방식이 미리 알려지지 않음 | 연결 리스트 탐색 포인터, 이진 트리 탐색 인덱스 |
| Most recent holder | 연속된 값들을 순회하면서 가장 최근 만난 값을 저장 | 파일의 최근 읽은 줄(line = file.readline()) |
| Most wanted holder | 특정 조건을 만족하는 최적값을 저장 (최솟값, 최댓값, 조건 충족 첫 값) | maxPrimeFactors, minimum |
| Gatherer | 순회하면서 값을 누적 집계 | sum = 0; for i: sum += list[i] |
| Container | 여러 원소를 담고 추가/제거할 수 있는 자료구조 | 리스트, 배열, 스택, 트리 |
| Follower | 다른 변수와 쌍을 이루며 이전/이후 값을 추적 | 이진 탐색의 하위 인덱스, 연결 리스트 prev 포인터 |
| Organizer | 추가 처리를 위해 값을 변환/재정렬해 임시 저장 | 문자열→문자 배열 변환, 정렬된 복사본 |
| Temporary | 아주 짧은 시간 동안만 사용하는 변수 | 두 값 교환을 위한 temp, 반복 사용 연산 결과 |
5.1.3 역할 프레임워크의 활용법
- 코드를 종이에 출력하고, 각 변수에 역할 아이콘을 직접 표시 → IDE 편집과 다른 차원의 상호작용 가능
- 변수명에 역할을 포함시키는 것도 효과적 (팀 전체가 공유할 때 특히 유용)
- 역할들의 조합이 프로그램의 패턴을 드러냄 → 예: Stepper + Most Wanted Holder = 탐색 프로그램
- 연구 결과: 역할 프레임워크를 사용한 학생이 사용하지 않은 학생보다 코드 이해 성취도가 높음
5.2 역할과 패러다임
- 역할 프레임워크는 특정 패러다임에 국한되지 않고 OOP, 함수형, 절차형 모두에서 동일하게 적용됨
- 예: Java 클래스에서
name은 Fixed value,age는 생일마다 증가하는 Stepper - 팀 공유 어휘로 활용 시 코드 이해·소통 개선 효과가 있음
5.2.2 헝가리안 표기법과의 관계
- 시스템 헝가리안: 변수 타입을 접두사로 인코딩 (
strName,lDistance) → 오늘날 안티패턴으로 간주 - 앱스 헝가리안 (Simonyi의 원래 의도): 의미론적 역할 인코딩 (
cColors= 색상 개수,rw= 행 인덱스) → 역할 프레임워크와 유사한 철학 - 잘못된 방향(타입 인코딩)이 확산된 것은 Simonyi의 글에서 “type”이라는 단어 사용이 오해를 불렀기 때문 (Joel Spolsky 분석)
- 핵심 교훈: 변수명에 역할 정보를 담는 것은 여전히 코드 가독성을 높이는 유효한 전략
5.3 프로그램에 대한 깊은 지식 획득
5.3.1 텍스트 지식 vs. 플랜 지식
- Colorado 대학 심리학 교수 Nancy Pennington의 2단계 이해 모델:
- 텍스트 구조 지식(Text structure knowledge): 키워드의 의미, 변수의 역할 등 표면적 이해
- 플랜 지식(Plan knowledge): 코드 작성자의 의도·목표, 구조와 연결 관계에 대한 이해
- 플랜 지식 없이 텍스트 지식만 있으면 → “코드가 어렵지 않아 보이는데 무엇을 하는지 모르는” 답답한 상황 발생
5.3.2 프로그램 이해의 4단계
-
Brigham Young University 교수 Jonathan Sillito가 25명의 프로그래머를 관찰해 도출:
- Focal point 찾기: 진입점(
main메서드, 오류 발생 줄, 프로파일러 지적 줄) 식별 - Focal point에서 지식 확장: 관련 변수·메서드·클래스를 찾고, 코드 슬라이스(slice) 파악 (X줄과 전이적으로 연결된 모든 줄)
- 관련 엔티티 집합에서 개념 이해: 슬라이스 안에서 많이 호출되는 메서드·핵심 클래스 목록 작성
- 여러 엔티티에 걸친 개념 이해: 자료구조·연산·제약 조건을 포함한 전체 그림 파악
- Focal point 찾기: 진입점(
-
이 4단계를 챕터 4의 6단계 순환 기법(변수·메서드·클래스 표시)과 결합하면 더 체계적인 플랜 지식 획득 가능
-
의존성 주입 프레임워크 같은 구조는 focal point가 분산되어 플랜 지식 획득을 방해하는 전형적 예
5.4 텍스트 읽기와 코드 읽기의 유사성
5.4.1 코드를 읽을 때 뇌에서 일어나는 일
- 프로그래머는 하루 업무 시간의 약 60%를 코드 읽기에 사용하나, 실제 코드 읽기 연습은 거의 안 함
- fMRI 연구 (Janet Siegmund, 2014): Java 코드 읽기 시 5개의 Brodmann 영역 활성화
- BA6, BA40 → 작업 기억 및 주의와 관련
- BA21, BA44, BA47 → 자연어 처리와 관련 (변수명을 난독화해도 활성화 → 키워드 자체를 자연어처럼 처리)
5.4.2 프랑스어를 배울 수 있다면 파이썬도 배울 수 있다
- Washington 대학 Chantel Prat 연구 (36명 대상): 프로그래밍 능력 예측 요인 분석
- 수학 능력(Numeracy) → 분산의 2% 설명 (매우 낮음)
- 언어 능력 → 17% 설명 (특히 학습 속도 예측에 강력)
- 작업기억 + 추론 능력 → 34% 설명 (가장 강한 예측 변수)
- 핵심 인사이트: 프로그래밍 능력에 수학 능력보다 언어 능력이 더 중요 → CS 교육의 통념 재검토 필요
코드 읽기 행동 연구
- Uwano 연구: 프로그래머는 코드 리뷰 시간의 처음 30% 동안 전체 줄의 70% 이상을 훑어봄 → 코드도 자연어처럼 먼저 스캔
- Busjahn 연구 (초보 14명 vs. 전문가 6명 비교):
- 초보: 자연어 80% 선형 읽기, 코드 75% 선형 읽기 → 코드도 위에서 아래로 읽으려 함
- 전문가: 비선형 읽기 → 콜 스택을 따라가며 읽는 능력은 경험을 통해 개발됨
5.5 텍스트 이해 전략을 코드에 적용
자연어 독해의 7가지 전략을 코드 읽기에 그대로 적용:
5.5.1 Prior knowledge 활성화
- 새 코드를 보기 전 **고정된 시간(10분)**을 주고 스캔 → 어떤 개념·문법 요소가 있는지 파악
- 목적: 작업 기억이 LTM에서 관련 정보를 미리 끌어오게 함
- 생소한 개념 발견 시 → 코드를 더 파고들기 전에 그 개념부터 먼저 공부할 것 (동시 학습은 인지 과부하 유발)
5.5.2 모니터링
- 코드를 읽으면서 **이해한 줄(✓)**과 **혼란스러운 줄(?)**을 실시간 표시
- 인쇄물에 아이콘 표시 or IDE의 댓글 활용
- 효과: 두 번째 독해 시 혼란스러운 부분에 집중 가능 + 도움 요청 시 구체적 소통 가능
5.5.3 중요도 판단
- 프로그램 실행에 가장 큰 영향을 미치는 줄을 의도적으로 선택 (느낌표! 표시)
- 팀에서 함께 수행하면 코드 자체뿐 아니라 팀원의 우선순위·경험을 이해하는 수단이 됨
- 어떤 줄이 중요한지에 대한 팀 내 의견 차이 → 정답 논쟁이 아니라 학습 기회로 활용
5.5.4 추론
- 모든 변수·함수·클래스 식별자 이름 목록을 작성 → 도메인 관련 이름 vs. 프로그래밍 개념 이름 분류
- 예:
Customer,Package(도메인) vs.Tree,List(프로그래밍 개념) vs.CustomerList(혼합) - 문맥 없이 이해 불가한 이름 → Sajaniemi 역할 프레임워크로 역할 추론
5.5.5 시각화
- 오퍼레이션 테이블: 각 변수/함수/클래스가 어떤 연산에 참여하는지 표로 기록
- 예:
f가a[i]와b[i]에 적용됨 →f는 함수,as/bs는 리스트임을 추론 가능
- 예:
- 이전 챕터의 상태 테이블·의존성 그래프와 함께 활용 가능
5.5.6 질문하기
- 코드를 읽으며 스스로에게 던질 깊이 있는 질문들:
- 코드의 가장 중심적인 개념 5가지는?
- 코드 작성자의 알고리즘·디자인 패턴·라이브러리 선택 이유와 가정은?
- 대안적 구현은 무엇이 있었을까?
- 이 질문들은 텍스트 지식을 넘어 플랜 지식으로 도달하게 해줌
5.5.7 요약하기
- 읽은 코드를 자연어로 요약 → 깊은 이해의 확인 + 문서화의 기회
- 요약 항목: 코드의 목표, 가장 중요한 줄, 핵심 도메인 개념, 핵심 프로그래밍 구조, 작성자의 결정들
6챕터: 프로그래밍 문제 해결 능력 향상
6.1 모델로 코드 생각하기
모델의 역할
- 모델 = 현실의 단순화된 표현. 목적: 문제에 대한 사고와 해결 지원
- 상태 다이어그램, 의존성 그래프, ER 다이어그램 등이 모두 모델
- 두 가지 이점: ① 타인과의 소통 도구 ② 복잡한 문제를 더 쉽게 사고하게 해줌
- 문제 표현 방식이 해결 전략을 결정한다 → 새와 두 기차 문제: 기차 관점으로 생각하면 복잡한 방정식 필요, 새 비행시간 관점으로 생각하면 30분×75mph = 37.5마일로 간단히 해결
6.2 멘탈 모델
멘탈 모델의 정의와 특성
- 멘탈 모델 = 문제에 대해 추론할 때 작업 기억 안에 형성되는 추상화
- Scottish 철학자 Kenneth Craik (1943)이 처음 기술: “자연 현상에 대한 정신적 축소 모형”
- 코드에서의 예: “트리를 순회한다”는 개념, “변수는 상자다”라는 비유
| 특성 | 설명 | 프로그래밍 예시 |
|---|---|---|
| 불완전함 | 모든 세부사항을 포함할 필요 없음 | “변수 = 상자” → 재할당 시 상자에 값이 쌓이는지 이해 못 할 수 있음 |
| 불안정함 | 더 배울수록 계속 변화함 | “변수 = 상자” → “변수 = 이름표”로 업데이트 |
| 복수 공존 | 서로 모순되는 모델이 동시에 존재 가능 | 파일을 “실제 종이 문서”이자 “0과 1의 배열”로 동시에 생각 |
6.2.1 멘탈 모델 상세 이해
- Princeton 심리학 교수 Philip Johnson-Laird (1983): 멘탈 모델은 추론 중 작업 기억에서 사용됨
- 테이블 배치 실험: 확정적 설명(하나의 배치만 가능) → 88% 정답, 불확정적 설명(여러 배치 가능) → 58% 정답
- 교훈: 멘탈 모델이 구체적일수록 복잡한 시스템에 대한 추론이 정확해짐
- 복잡한 코드의 멘탈 모델을 작업 기억에 구성하는 3단계:
- 지역 모델 먼저 구축 (상태 테이블, 의존성 그래프) → 인지 부하 감소
- 코드베이스의 모든 관련 객체와 관계 목록 작성
- 시스템에 대한 질문에 답하며 모델 정제 (“가장 중요한 요소는?”, “핵심 사용 시나리오는?”)
6.2.2 새로운 멘탈 모델 학습
- Dedre Gentner & Albert Stevens (1983): 범용 멘탈 모델은 LTM에 저장되어 필요 시 꺼내 쓸 수 있음
- 예: “트리 순회” 모델을 LTM에 저장 → 처음 보는 언어로 작성된 트리 코드도 이해 가능
- 멘탈 모델 플래시카드 활용법:
- 앞면: 멘탈 모델명 (예: “Observer Pattern”)
- 뒷면: 모델 설명 + 코드에 적용할 때 던질 질문
- LTM에 저장할 가치 있는 모델 예시: 자료구조(그래프, 트리, 리스트), 디자인 패턴(Observer, MVC), 아키텍처 패턴, ER 다이어그램, 상태 다이어그램
- 두 관점(작업 기억 vs. LTM)은 모순이 아니라 상호 보완: LTM에 저장된 모델이 작업 기억에서의 모델 구성을 지원함
6.3 노셔널 머신
정의와 특성
- 노셔널 머신 = 코드를 실행하는 컴퓨터를 어떻게 생각할지에 대한 올바르고 일관된 추상화
- 멘탈 모델과의 차이:
- 멘탈 모델: 무엇이든 될 수 있고, 틀리거나 불일치할 수 있음
- 노셔널 머신: 컴퓨터 동작에 대한 올바른 설명 → 내면화하면 그것이 멘탈 모델이 됨
- 유래: Sussex 대학 교수 Ben du Boulay가 1970년대 Logo 언어 교육 중 고안
- “프로그래밍 언어의 구조가 암시하는 컴퓨터의 이상화된 모델”
- 비유 예: 공장 노동자(명령 실행) = 귀(파라미터 값), 입(출력), 손(코드 실행)
노셔널 머신의 예시
- 대입을 수학 방정식처럼 생각 →
total = maximum + 12에서maximum이 변하면total도 변한다고 잘못 생각하는 오류 유발 - 계산을 수식 치환으로 생각 (
substitution notional machine) →celsius = 10이면9.0/5.0 * 10 + 32로 치환 → 정답은 맞지만 실제 컴퓨터는 역폴란드 표기법과 스택으로 계산 (부분적으로 틀리지만 유용한 모델) - 변수를 상자로 생각 → 직관적이나 “상자에 여러 값이 들어갈 수 있다”는 오개념 유발 가능
- 변수를 이름표/스티커로 생각 → 스티커는 하나에만 붙으므로 단일 값 제약을 더 잘 표현
6.3.3 노셔널 머신의 추상화 레벨
| 레벨 | 예시 |
|---|---|
| 프로그래밍 언어 | 계산을 치환으로 생각 |
| 컴파일러/인터프리터 | 변수를 상자로 생각 |
| VM/바이트코드 | — |
| 운영체제 | 스레드를 사람 간 협업으로 생각 |
- 핵심: 어떤 추상화를 감추고 어떤 것을 드러내는지 의도적으로 인식하는 것이 중요
6.4 노셔널 머신과 언어
- 일상적 프로그래밍 언어 자체가 노셔널 머신을 반영:
- “변수가 값을 담는다(holds)” → 상자 모델
- “파일이 열려 있다/닫혀 있다” → 파일을 물리적 오브젝트처럼 생각
- “함수가 값을 반환한다(returns)” → 스택 모델 암시
- 노셔널 머신은 확장 가능(expandable): 단순 변수 → 복합 타입으로, 파라미터 없는 함수 → 입력 파라미터 함수 → 반환값 있는 함수로 점진적 확장
- 그러나 충돌하는 멘탈 모델 유발 위험: “변수 = 상자” vs. “변수 = 이름표”는 공존 불가
6.4.2 NEMO 박물관 연구
- 496명 비전공자 대상, Scratch 입문 수업
- 상자 그룹 vs. 이름표 그룹 비교 결과:
- 단순 질문: 상자 그룹 우세 (시각적 직관성)
- 이중 대입 질문: 상자 그룹에서 “변수가 두 값을 저장할 수 있다”는 오개념 더 많이 발생
- 교훈: 현실 세계 비유는 유용하지만 언제나 오개념의 씨앗이 될 수 있음 → 사용하되 한계를 인식할 것
6.5 노셔널 머신과 스키마
- 노셔널 머신이 효과적인 이유 = 기존에 강한 스키마가 있는 개념을 비유로 사용하기 때문
- “변수 = 상자” → 누구나 상자에 물건을 넣고 꺼내는 것을 알고 있음 → 인지 부하 없음
- “변수 = 외발자전거” → 스키마 없음 → 도움이 안 됨
- 교육 맥락 중요성: 인도 농촌 어린이에게 컴퓨터를 설명할 때 → 코끼리(컴퓨터)와 조련사(프로그래머) 비유가 더 효과적
- 노셔널 머신 ≠ 프로그램의 의미론(Semantics): 의미론은 수학적 완전한 명세를 목표로 하지만, 노셔널 머신은 의도적 추상화와 생략이 핵심
7챕터: 오개념 — 사고의 버그
7.1 두 번째 언어를 배우는 게 첫 번째보다 쉬운 이유
전이의 두 가지 메커니즘
- 학습 중 전이(Transfer during learning): LTM의 기존 지식이 새 정보의 LTM 저장을 도움
- 학습의 전이(Transfer of learning): 완전히 새로운 상황에서 기존 지식을 적용
7.1.1 전이를 촉진하는 요소
전이의 양에 영향을 미치는 3가지 요인:
- 숙달도(Mastery): LTM에 저장된 지식을 더 잘 알수록 전이 가능성이 높아짐
- 유사성(Similarity): 두 과제가 비슷할수록 전이 가능성 증가 (이미 아는 알고리즘을 새 언어로 구현 vs. 새 알고리즘을 새 언어로 구현)
- 맥락(Context): 같은 IDE에서 두 언어를 사용하면 전이 가능성 증가 / 에피소딕 기억·감정도 영향
7.1.2 전이의 종류
| 분류 | 종류 | 설명 | 예시 |
|---|---|---|---|
| 자동화 여부 | Low-road transfer | 자동화된 기술의 전이, 의식적 인지 없이 발생 | 새 에디터에서 Ctrl-C/V 자동 사용 |
| 자동화 여부 | High-road transfer | 복잡한 기술의 의식적 전이 | “Python에서도 변수 선언이 필요하지 않을까?” |
| 거리 | Near transfer | 유사한 도메인 간 전이 | Java → Python, 미적분 → 대수 |
| 거리 | Far transfer | 매우 다른 도메인 간 전이 | Java → Prolog, SQL → JavaScript |
7.1.3 긍정적 vs. 부정적 전이
- 긍정적 전이(Positive transfer): 기존 지식이 새 학습을 도움
- 예: Java의 루프 개념(카운터, 바디, 종료 조건) → Python 루프 학습 가속
- 부정적 전이(Negative transfer): 기존 지식이 새 학습을 방해
- 예: Java 개발자가 Python에서도 변수를 항상 선언해야 한다고 가정
- 예: OOP 경험자가 함수형 언어(F#)의 함수 개념을 잘못 이해
- Dijkstra의 명언: “BASIC 교육은 마음을 망가뜨린다” → 과장이지만, 이전 언어 습관이 새 언어 학습에 간섭한다는 진실을 담고 있음
7.1.4 전이의 어려움
- 연구 결과: 전이는 자동으로 일어나지 않으며, 도메인이 충분히 유사해야 함
- 체스 실력 연구: 체스 고수도 무작위 배치에서는 초보와 기억력 차이 없음 → 체스 실력이 일반 논리 능력이나 기억력으로 전이되지 않음
- 프로그래밍도 마찬가지: 프로그래밍 교육이 일반 인지 능력 향상으로 전이된다는 연구 결과 없음
- 함의: 전문가라도 새 언어 학습 시 플래시카드 등 기초부터 다시 시작하는 것이 필요할 수 있음
7.2 오개념 — 사고의 버그
7.2.0 오개념의 정의
- 오개념(Misconception): 단순한 실수나 혼란이 아님. 다음 3조건을 동시에 만족:
- 틀렸을 것 (faulty)
- 여러 상황에서 일관되게 나타날 것 (consistent)
- 확신을 갖고 믿을 것 (held with confidence)
- 예시: “칠리 씨앗이 가장 맵다” → ① 틀림, ② 모든 종류의 칠리에 적용, ③ 확신하고 행동 (씨앗 제거)
- 버그의 진짜 원인: 단순 실수보다 오개념에 기반한 잘못된 가정이 더 근본적인 원인인 경우가 많음
7.2.1 개념적 변화로 오개념 수정
- 오개념은 “당신이 틀렸다”고 알려주는 것만으로는 고쳐지지 않음 → 새로운 멘탈 모델로 교체해야 함
- 개념적 변화(Conceptual change): 기존 개념이 새 지식에 의해 근본적으로 변화·대체·흡수되는 과정
- 이는 단순히 새 지식을 추가하는 것과 다름 → LTM의 기존 지식 자체를 바꾸는 것이므로 일반 학습보다 훨씬 어렵고 오래 걸림
- 예: Java 개발자가 Python을 배울 때 “타입을 항상 선언해야 한다”는 사실을 잊는 것은 쉽지만, 코딩 중 타입을 생각하는 습관 자체를 바꾸는 것은 시간이 필요
7.2.2 오개념 억제
- 오래된 오개념은 삭제되지 않고 LTM에 남아 있음 → 재활성화될 수 있음
- 눈사람에 스웨터 문제: 뇌가 즉각적으로 “스웨터 = 따뜻함” 모델을 활성화 → 의도적 억제(inhibition)가 필요
- 연구(히브리 대학, Galili & Bar): 학생들은 익숙한 문제에서는 올바른 물리 개념을 사용하지만, 복잡한 문제에서는 더 단순하지만 틀린 개념으로 회귀
- 오개념이 해소된 후에도 인지 부하가 높은 상황에서 재발할 위험은 항상 존재
7.2.3 프로그래밍의 대표적 오개념
Juha Sorva (Aalto 대학) 박사 논문(2012): 연구 기반 162개 오개념 목록 작성
-
오개념 #15: 대입이 방정식을 저장한다
total = maximum + 12→maximum이 나중에 바뀌면total도 자동으로 바뀐다고 믿음- 원인: 수학의 변수 개념(등식 관계) 전이 / 오개념이 매우 합리적으로 느껴짐
-
오개념 #33: while 루프는 조건이 false가 되는 즉시 종료된다
- 루프가 각 줄마다 조건을 확인하고 false가 되면 즉시 실행을 멈춘다고 믿음
- 원인: 영어 “while”의 일상적 의미 전이 (“비가 오는 동안은 책을 읽겠다” → 비가 그치면 즉시 멈춤)
-
오개념 #46: 파라미터 이름이 호출부와 시그니처에서 달라야 한다
- 함수 내부 변수와 외부 변수에 같은 이름을 쓸 수 없다고 믿음
- 원인: “변수명은 한 번만 쓸 수 있다”는 초기 학습이 함수 스코프 개념으로 전이되지 않음
- IDE의 “함수 추출(Extract Method)” 기능이 같은 이름 패턴을 자주 생성하므로 코드에도 흔히 등장
7.2.4 오개념 예방 전략
- 열린 마음 유지: 확신하더라도 틀렸을 가능성을 인식
- 공통 오개념 목록 의도적 학습: Sorva 목록 등을 활용해 현재 배우는 언어에 적용 가능한 오개념 미리 점검
- 같은 언어 조합을 배운 선배에게 조언 구하기: 언어 쌍마다 고유한 오개념 함정이 있으므로
7.2.5 코드베이스 안의 오개념 진단
- 프로그래밍 언어뿐 아니라 특정 코드베이스에 대한 오개념도 존재
- 프레임워크·라이브러리의 동작 방식, 도메인 개념, 타인의 코딩 의도에 대한 잘못된 가정
- 탐지 방법:
- 페어 프로그래밍: 다른 사람의 가정과 충돌하면 오개념 발견 가능
- 테스트 작성: “이 값은 절대 음수일 수 없다”는 가정 → 테스트로 검증 + 미래의 자신에게도 문서화
- 코드에 문서 추가: 오개념 발견 시 해당 함수·자료구조에 문서 추가 → 같은 함정 반복 방지
- 핵심: 오개념은 사라지지 않고 항상 재발할 수 있으므로 테스트와 문서로 외부화해두는 것이 중요
파트 2 전체 핵심 인사이트 요약
| 챕터 | 핵심 메시지 |
|---|---|
| 5장 | 변수의 역할(11가지)을 파악하면 코드 이해가 깊어진다. 코드 읽기는 자연어 읽기와 인지적으로 유사하므로 텍스트 독해 전략(스캔·모니터링·시각화·요약 등)을 코드에 그대로 적용할 수 있다 |
| 6장 | 문제 표현 방식이 해결 방식을 결정한다. 멘탈 모델(작업 기억)과 노셔널 머신(컴퓨터 동작의 추상화)을 의도적으로 개발하면 코드에 대한 추론 능력이 향상된다. 단, 비유와 모델은 오개념의 씨앗이 될 수 있다 |
| 7장 | 버그의 뿌리는 종종 오개념이다. 오개념은 “틀렸다”는 지적만으로는 고쳐지지 않으며 새 멘탈 모델로의 교체(개념적 변화)가 필요하다. 코드베이스 내 가정은 테스트와 문서로 외부화하라 |
📘 The Programmer’s Brain — Part 3: 더 나은 코드 작성하기
파트 3 개요: 파트1(읽기), 파트2(사고)에 이어, 파트3은 코드 쓰기에 집중. 이해하기 쉬운 코드를 작성하는 법, 나쁜 이름과 코드 스멜 회피법, 복잡한 문제 해결 능력 향상법을 다룸.
8챕터: 네이밍 잘하는 법
8.1 왜 네이밍이 중요한가
- Phil Karlton(Netscape): “컴퓨터과학에서 어려운 문제는 캐시 무효화와 이름 짓기, 딱 두 가지다” — 프로그래머의 공통된 고충을 상징하는 명언
- Feitelson(히브리대) 실험: 약 350명에게 47개 변수·함수·파라미터 이름을 짓도록 요청 → 두 개발자가 같은 이름을 선택할 확률은 중앙값 7% → 네이밍은 본질적으로 어렵다는 실증적 증거
- 이름이 중요한 4가지 이유:
- 코드베이스의 대부분이 이름: Eclipse(200만 라인 코드)의 경우 토큰의 33%, 문자의 72%가 식별자
- 코드 리뷰의 핵심 주제: Allamanis(MS Research) 분석 결과, 코드 리뷰 4건 중 1건이 네이밍 관련 의견 포함
- 가장 접근성 좋은 문서: 공식 문서와 달리 코드베이스 안에 바로 존재 → 외부 탐색 없이 즉시 참조 가능
- 비콘(Beacon) 역할: 생소한 독자가 코드 의미를 해독하는 데 도움을 주는 단서로 작동
8.1.2 네이밍에 대한 서로 다른 관점
Butler의 문법적 관점
- Simon Butler(Open University UK)가 제시한 나쁜 이름의 유형들:
| 위반 유형 | 내용 | 나쁜 예 |
|---|---|---|
| 대소문자 이상 | 올바른 대소문자 규칙 미사용 | page counter |
| 연속 언더스코어 | __ 금지 |
page__counter |
| 사전 단어 미사용 | 약어보다 완전한 단어 사용 | pag_countr |
| 단어 수 초과 | 2~4 단어 범위 권장 | page_counter_converted_and_normalized |
| 짧은 이름 | 8자 미만 금지 (i,j,k 등 예외 허용) | P, page |
| 외부 언더스코어 | 이름 시작·끝 _ 금지 |
__page_counter_ |
| 타입 인코딩 | 헝가리안 표기법 금지 | int_page_counter |
| 숫자로만 구성 | 숫자/숫자 단어만으로 구성 금지 | FIFTY |
Allamanis의 일관성 관점
- 코드베이스 전반에서 동일한 패턴을 유지하는 것이 가장 중요 → “일관되게 나쁜 것이 좋지만 불일관한 것보다 낫다”
- 도구화: Naturalize (http://groups.inf.ed.ac.uk/naturalize/) — 머신러닝으로 코드베이스에서 일관된 이름 패턴을 학습해 제안. 18개 PR 중 14개 병합 성공 (Java 전용)
8.1.3 초기 네이밍 관행의 지속성
- Lawrie(Johns Hopkins) 연구: 78개 코드베이스 186개 버전(3억 라인)을 분석
- 현대 코드는 과거보다 사전 단어 사용 비율 높아짐 → 프로그래밍 분야의 성숙 반영
- 단, 하나의 코드베이스 내에서는 네이밍 품질이 시간이 지나도 개선되지 않음
- 코드베이스 크기(대형/소형)는 네이밍 품질과 무관
- 핵심 인사이트: “식별자 품질은 프로젝트 초기에 굳어진다” → 새 프로젝트 시작 시 네이밍에 각별히 신경 써야 하는 이유
- GitHub 연구에서도 유사 패턴: 신규 기여자들은 기존 테스트를 참고해 따라하는 경향 → 초기 관행이 전파됨
8.2 네이밍의 인지과학적 측면
8.2.1 포맷이 STM을 돕는다
- STM(단기기억) 관점: 이름의 구조가 명확할수록 STM이 개별 단어를 식별하기 쉬움
nmcntravg→ 구성요소 파악에 상당한 인지 노력 필요name_counter_average→ 글자 수는 두 배이지만 인지 노력은 훨씬 적음
- Allamanis의 일관성 원칙 → 청킹(Chunking) 지원: 같은 스타일이면 매번 이름 분석에 에너지 낭비 불필요
- Butler의 4단어 제한 → 작업 기억 용량(2~6 청크)과 정확히 부합
8.2.2 명확한 이름이 LTM을 돕는다
- 이름을 읽을 때 두 가지 인지 경로가 동시에 작동:
- STM: 이름을 청크로 분해
- LTM: 이름의 단어들에 연결된 관련 지식 자동 검색 → 작업 기억으로 전달
8.2.3 식별자에 담을 수 있는 지식의 세 종류
- 도메인 지식:
customer라는 단어 → LTM에서 “구매, 주소, 이름” 등 자동 연상 - 프로그래밍 개념:
tree라는 단어 → “루트, 순회, 플래튼” 등 자동 연상 - 관례(Convention):
j→ 중첩 루프의 내부 카운터,i→ 루프 반복자,n,m→ 배열 차원
8.2.4 이름 품질 평가의 적절한 시점
- 코딩 중에는 인지 부하가 높아 좋은 이름 짓기가 어려움 →
foo,temp같은 임시 이름을 쓰는 게 인지적으로 자연스러운 반응 - 코드 리뷰가 이름 품질을 평가하기에 더 좋은 시점
- 코드 리뷰 전 체크리스트 실천법:
- 변경된 코드의 식별자들을 화이트보드나 별도 문서에 목록화
- 코드 문맥 없이도 의미가 명확한가?
- 모호하거나 불명확한 이름이 있는가?
- 혼란을 줄 수 있는 약어가 있는가?
- 유사한 이름들이 실제로도 유사한 개념을 가리키는가?
8.3 어떤 이름이 이해하기 쉬운가
8.3.1 약어 vs 완전한 단어
- Hofmeister(Univ. Passau) 실험: 72명의 C# 개발자에게 세 가지 스타일의 코드에서 버그 탐색 요청
- 완전한 단어 식별자 사용 코드: 글자·약어 식별자보다 분당 19% 더 많은 버그 발견
- 글자 vs 약어: 유의미한 차이 없음
- Lawrie 연구 (120명 전문 개발자): 완전한 단어 식별자가 이해도 거의 1점 높음 (5점 척도)
- 트레이드오프: 단어가 길수록 기억하기 어렵고 회상 시간도 더 걸림 → 음절 수가 핵심 변수
- 프리픽스/서픽스 관행 주의: 추가 정보의 이점이 기억 부담을 정당화하는지 신중하게 검토
- 결론: 명확성(완전한 단어) ↔ 간결성(약어)의 균형이 이상적인 이름의 조건
8.3.2 스네이크 케이스 vs 캐멜 케이스
- Binkley(Loyola Univ.) 실험 (135명, 프로그래머 + 비프로그래머):
- 캐멜케이스 → 정확도 51.5% 더 높음 (단, 속도는 0.5초 느림)
- 캐멜케이스 훈련을 많이 받은 사람일수록 스네이크케이스 처리 능력이 미훈련자보다 낮아짐 → 스타일에 대한 암묵적 기억이 굳어지면 다른 스타일 처리 방해
- 결론: 새 컨벤션 선택 시 캐멜케이스 권장, 단 기존 코드베이스 일관성 유지가 더 우선
단일 문자 변수의 실제 사용
- Beniamini(히브리대): C, Java, JavaScript, PHP, Perl의 GitHub 상위 200개 프로젝트(16GB+) 분석
- JavaScript에서 가장 많이 쓰는 단일 문자:
i,e,d - Perl:
v,i,j
- JavaScript에서 가장 많이 쓰는 단일 문자:
- 96명 개발자에게 단일 문자의 타입 연상 조사 결과:
- 높은 합의:
s→문자열,c→문자(char),i,j,k,n→정수 - 대부분의 문자에 대해 개발자 간 합의 낮음 → 단일 문자를 ’당연히 이해된다’고 가정하는 것은 위험
- 높은 합의:
8.4 이름이 버그에 미치는 영향
8.4.1 나쁜 이름이 있는 코드에 버그가 더 많다
- Butler(2009): Tomcat, Hibernate 등 오픈소스 Java 저장소에서 나쁜 네이밍 위치와 버그(FindBugs) 위치 비교
- 나쁜 네이밍 위치와 버그 위치 간 통계적으로 유의미한 상관관계 발견
- 인과관계 주의: 둘 다 인지 부하가 높은 복잡한 로직의 산물일 수 있음 (공통 원인)
- 실용적 함의: 코드베이스에서 나쁜 이름을 찾아 개선하는 것 → 잠재 버그 위치 발굴 + 수정 시간 단축 효과
8.5 더 나은 이름 선택 방법
8.5.1 네임 몰드
- Feitelson의 관찰: 개발자들이 같은 이름을 고르지는 않지만, 서로의 이름을 이해는 할 수 있었음 → 네임 몰드 때문
- 네임 몰드: 변수명의 요소들이 결합되는 패턴 (예:
max_benefit,max_benefit_per_month,benefits_per_month,max_monthly_benefit등 모두 다른 몰드) - 코드베이스에 다양한 몰드가 혼재할 때의 두 가지 인지적 문제:
- 인지 부하 증가: 변수명에서 핵심 개념을 찾는 위치가 매번 달라 불필요한 인지 에너지 소비
- LTM 연결 약화:
max_benefit_amount를max_interest_amount와 연결하기 쉽지만,interest_maximum이라면 LTM이 패턴을 연결하기 어려움
- 권고: 프로젝트 시작 시 팀 내에서 사용할 몰드 수를 제한해 합의. 기존 코드베이스는 현재 사용 몰드를 목록화 후 통일
8.5.2 Feitelson의 3단계 모델
- Feitelson이 연구를 기반으로 설계한 더 나은 이름을 짓기 위한 3단계:
- 이름에 포함할 개념 선택: 가장 중요한 단계 — 객체가 담는 정보와 용도를 중심으로 선택. 주석으로 설명할 필요가 느껴진다면 그 표현이 이름에 포함되어야 한다는 신호
- 각 개념을 표현할 단어 선택: 도메인에서 사용하는 단어나 코드베이스 전반의 일관된 어휘 우선. 동의어 혼란 방지를 위해 프로젝트 어휘집(Lexicon) 관리 권장
- 선택한 단어로 이름 구성 (몰드 선택): 자연어 어순 반영 권장 (
max_points>points_max), 전치사 활용으로 가독성 향상 (indexOf,elementAt)
- 3단계 모델의 효과: 100명의 새 참가자에게 모델을 교육 후 이름 짓기 → 외부 심사위원 평가 결과 모델 사용 그룹의 이름이 2:1 비율로 우수하다는 평가 획득
9챕터: 나쁜 코드와 인지 부하: 두 가지 프레임워크
9.1 코드 스멜이 인지 부하를 높이는 이유
9.1.1 코드 스멜이란?
- Martin Fowler의 1999년 저서 Refactoring 에서 처음 정의: 구조적으로 이상적이지 않은 코드의 징후
- 코드 스멜 22종 (수준별 분류):
| 수준 | 코드 스멜 | 설명 |
|---|---|---|
| 메서드 | Long method (God method) | 너무 많은 기능을 하는 긴 메서드 |
| 메서드 | Long parameter list | 너무 많은 파라미터 |
| 메서드 | Switch statements | 거대한 switch문 (다형성으로 해결 가능) |
| 클래스 | Large class (God class) | 너무 많은 책임을 가진 거대 클래스 |
| 클래스 | Lazy class | 너무 적은 기능만 하는 클래스 |
| 클래스 | Primitive obsession | 원시 타입 남용 |
| 클래스 | Data class | 데이터만 있고 메서드가 없는 클래스 |
| 클래스 | Temporary field | 불필요한 임시 필드 |
| 클래스 | Data clumps | 자주 함께 쓰이는 데이터를 하나의 구조로 묶지 않음 |
| 코드베이스 | Duplicated code (code clones) | 유사한 코드가 여러 곳에 반복 |
| 코드베이스 | Feature envy | 클래스 A의 메서드가 클래스 B를 더 많이 참조 |
| 코드베이스 | Divergent change | 하나의 수정이 여러 곳에 분산됨 |
| 코드베이스 | Shotgun surgery | 하나의 변경을 위해 여러 클래스를 수정해야 함 |
| 코드베이스 | Message chains | 메서드 체인이 지나치게 길어짐 |
| 코드베이스 | Comments | 주석이 무엇을 하는지가 아닌 왜 있는지를 설명해야 함 |
| 코드베이스 | Middle man | 너무 많은 책임을 위임만 하는 클래스 |
| 코드베이스 | Inappropriate intimacy | 클래스 간 지나친 의존 |
| 코드베이스 | Parallel inheritance | 한 클래스의 서브클래스를 만들면 다른 클래스도 따라 만들어야 함 |
| 코드베이스 | Refused bequest | 상속은 받았지만 사용하지 않는 동작 존재 |
| 코드베이스 | Speculative generality | “혹시 필요할까봐” 추가된 코드 |
| 코드베이스 | Alternative classes with different interfaces | 유사하지만 인터페이스가 다른 두 클래스 존재 |
| 클래스 | Incomplete library class | 라이브러리 클래스에 추가해야 할 메서드를 다른 클래스에 넣음 |
- 코드 스멜 ≠ 버그 보장: 하지만 스멜이 있는 코드는 없는 코드보다 오류 가능성 더 높음
- Khomh(Polytechnique Montréal) 연구: Eclipse 코드베이스 분석 → God Class는 모든 버전에서 오류 발생의 중요 요인. Large class와 Long method는 Eclipse 릴리스의 75% 이상에서 변경 빈번
9.1.2 코드 스멜이 인지를 해치는 메커니즘
- Long parameter list, Complex switch statements → 작업 기억(Working Memory) 과부하
- 작업 기억 용량 최대 약 6 청크 → 파라미터 수가 6개를 초과하면 전체를 동시에 유지 불가
- 단, 맥락에 따라 여러 파라미터가 하나의 청크로 묶일 수 있음 (예: xOrigin+yOrigin → “출발점” 청크)
- God Class, Long Method → 효율적 청킹 불가
- 의미 있는 이름의 작은 함수/클래스가 청킹의 기반 →
multiples(),minimum()이름만 봐도 “최소공약수” 패턴 인식 가능 - God Class/Long Method는 이름이 부여하는 추상화 단서가 없어 라인 바이 라인 읽기를 강요
- 의미 있는 이름의 작은 함수/클래스가 청킹의 기반 →
- Code Clones → 잘못된 청킹 (Mischunking)
foo()와 유사한goo()를 보면 뇌가 자동으로foo()에 대한 LTM 정보를 끌어옴- 체스의 “시실리안 오프닝” 변형처럼 미묘한 차이를 무시하고 같은 범주로 묶어버림 → 오개념(Misconception) 발생, 이는 오랫동안 지속될 수 있음
9.2 나쁜 이름이 인지 부하에 미치는 영향
9.2.1 언어적 안티패턴
- Arnaoudova(Washington State Univ.)가 정의: 코드의 언어적 요소(이름)와 실제 역할 사이의 불일치
- 6가지 카테고리:
- 메서드가 이름보다 더 많은 일을 함
- 메서드가 이름보다 적은 일을 함
- 메서드가 이름과 반대되는 일을 함
- 식별자 이름이 실제보다 더 많은 것을 담고 있다고 암시
- 식별자 이름이 실제보다 더 적은 것을 담고 있다고 암시
- 식별자 이름이 실제와 반대를 암시
- 실제 발생 빈도 (7개 오픈소스 프로젝트 분석):
- setter이면서 값도 반환하는 경우: 11%
- 메서드명과 주석이 반대 설명을 하는 경우: 2.5%
is로 시작하지만 Boolean이 아닌 경우: 무려 64%
- 도구: LAPD (Linguistic Anti-Pattern Detector) — Eclipse Checkstyle 플러그인 (Java 전용)
9.2.2 인지 부하 측정 방법
-
Paas Scale (Fred Paas, 에라스무스 대학): 9단계 자가 보고식 척도 (매우 매우 낮은 노력 ~ 매우 매우 높은 노력)
- 단일 문항이라 단순하지만 바이오메트릭과 상관관계 높아 실용적으로 유효
-
눈 기반 측정:
- 눈 깜빡임 빈도(Blink rate): 인지 부하가 높을수록 덜 깜빡임 → 뇌가 더 많은 시각 정보를 얻으려 함
- 동공 크기(Pupil size): 어려운 과제일수록 동공이 커짐
-
피부 기반 측정: 피부 온도, 땀 → 인지 부하의 지표
-
뇌 기반 측정:
- fMRI: 정밀하지만 움직임 제약으로 실제 코딩 환경과 거리 있음
- EEG: 뇌파 전위 변화로 뉴런 활동 측정
- fNIRS (기능적 근적외선 분광법): 헤드밴드 착용 → 뇌 혈중 산소화 측정으로 인지 부하 감지. fMRI보다 현실적인 실험 환경 제공
-
Nakagawa(나라 첨단과학기술대원, 2014): fNIRS로 쉬운 코드 vs 복잡하게 만든 코드 읽기 시 비교 → 10명 중 8명에서 복잡한 코드 읽을 때 산소화 혈류 증가 → 인지 부하 수치화 가능 실증
9.2.3 언어적 안티패턴과 인지 부하
- Fakhoury(Arnaoudova 지도) 2018년 연구: 15명이 오픈소스 코드 스니펫 읽기 (4종류: 언어적 안티패턴 / 구조적 불일치 / 둘 다 / 아무것도)
- 아이트래커: 언어적 안티패턴이 있는 코드 부분을 훨씬 오래 응시
- fNIRS: 언어적 안티패턴이 있는 코드에서 평균 산소화 혈류 유의미하게 증가 → 인지 부하 상승 실증
- 흥미로운 발견: 구조적 불일치(들여쓰기 누락, 잘못된 형식 등)에 대해서는 참가자들이 불편함을 표했지만, 인지 부하 증가의 통계적 증거는 없었음 → 언어적 안티패턴이 더 근본적인 문제
9.2.4 언어적 안티패턴이 혼란을 일으키는 메커니즘
- 메커니즘 1 — 잘못된 LTM 활성화:
retrieveElements()를 보면 LTM이 “리스트 반환” 관련 정보를 자동 로드 → 실제로 단일 객체를 반환해도 이미 정렬/필터/슬라이스가 가능하다는 오개념 형성 - 메커니즘 2 — 잘못된 청킹(Mischunking):
isValid를 보면 뇌가 즉시 Boolean이라고 가정, 더 이상 파헤치지 않음 → 실제로 정수 리스트인 경우 오개념 발생 및 오랫동안 지속
10챕터: 복잡한 문제를 더 잘 해결하는 법
10.1 문제 해결은 독립적인 인지 능력이 아니다
- 일반적 오해: “문제 해결 능력”은 전이 가능한 범용 스킬 → 실제로는 사전 지식에 강하게 의존
- 체스에서 수학으로, 혹은 범용 문제 해결 도메인에서 다른 도메인으로의 지식 전이는 거의 일어나지 않음
- 전문가들은 문제를 “해결”하는 것이 아니라 “재현(Recreate)” — 이전에 작동했던 유사 솔루션을 기억에서 꺼냄
- 따라서 더 나은 문제 해결자가 되려면 → LTM을 직접 강화해야 함
10.2 LTM의 기억 유형과 문제 해결의 관계
기억의 분류 체계
기억 (Memory)
├── 절차적(Procedural) / 암묵적(Implicit) 기억
│ 예: 자전거 타기, 터치타이핑, ctrl+z 자동 실행
└── 선언적(Declarative) / 명시적(Explicit) 기억
├── 일화적(Episodic) 기억
│ 예: 과거에 tree 자료구조로 계층 문제 해결했던 경험
└── 의미적(Semantic) 기억
예: Java for-loop 문법, a² + b² = c²
- 프로그래밍에서 세 가지 기억이 모두 사용됨:
- 의미적 기억: Java for-loop 문법 기억
- 일화적 기억: 과거에 트리로 비슷한 문제 해결한 경험 기억 → 전문가가 특히 의존
- 절차적 기억: 타이핑, 단축키, 브레이크포인트 설정 등 자동화된 동작
- **직관(Intuition)**도 사실상 유사 문제를 풀었던 암묵적 일화 기억의 발현
- 부정적 전이(Negative transfer): 강한 암묵적 기억은 새 언어 학습을 방해할 수 있음
- 예: Java → Python 전환 시 자꾸 중괄호를 입력하거나
foreach를 사용하는 현상
- 예: Java → Python 전환 시 자꾸 중괄호를 입력하거나
10.3 자동화: 암묵적 기억 만들기
- 자동화: 어떤 스킬을 생각 없이 실행할 수 있는 수준에 도달한 상태 → 인지 자원 소모 없이 실행
- 자동화된 스킬 = 게임에서 새 능력이 잠금 해제되는 것과 유사 → 더 복잡한 상위 문제 풀 수 있게 됨
- 핵심 원리: 암묵적 기억이 많을수록 인지 부하 여유가 늘어나 더 큰 문제에 집중 가능
- 암묵적 기억 vs 명시적 기억의 생성 방식:
- 명시적 기억: 의도적 주의로 생성 (플래시카드 등)
- 암묵적 기억: 반복(Repetition) 으로 생성
10.3.1 암묵적 기억 형성의 3단계
- 인지 단계(Cognitive Phase): 새 정보를 명시적으로 분리하고 생각해야 함. 스키마 형성/갱신 — 예: “리스트는 0부터 시작”을 처음 배울 때 의식적으로 계산
- 연상 단계(Associative Phase): 반복을 통해 패턴이 나타남. 효과적인 행동은 기억되고 비효율적인 행동은 버려짐 — 예: “원소 인덱스 = 원하는 번호 - 1”로 단순화됨
- 자율 단계(Autonomous Phase) = 절차 단계: 스킬이 완성됨. 어떤 맥락에서도 즉시, 무의식적으로 실행 가능 → 더 이상 인지 부하를 차지하지 않음
- 의의: 자율 단계에 도달한 스킬은 인지 부하를 전혀 소모하지 않으므로, 그 여유 용량으로 더 복잡한 문제에 집중 가능
10.4 코드와 설명을 통한 학습
워크드 예제 효과
- Sweller & Cooper (호주) 실험: 9학년 두 그룹에게 대수 방정식 제시
- 그룹 1: 방정식 + 워크드 예제(단계별 풀이 레시피) 제공
- 그룹 2: 방정식만 직접 풀기
- 결과: 그룹 1이 그룹 2보다 5배 빠르게 풀었고, 새로운 문제에서도 더 좋은 성과
- 이 효과는 수학, 음악, 체스, 스포츠, 프로그래밍 등 다양한 영역에서 재현됨
10.4.1 세 번째 인지 부하: 생산적 부하
- 인지 부하의 3가지 종류:
- 내재적 부하(Intrinsic load): 문제 자체의 고유한 복잡성
- 외재적 부하(Extraneous load): 문제 표현 방식의 불필요한 복잡성
- 생산적 부하(Germane load): 정보를 LTM에 저장하는 데 필요한 인지 자원
- 핵심 메커니즘: 작업 기억이 가득 찰 경우 → LTM에 저장할 여유(Germane load)가 없음 → 아무리 열심히 코딩해도 기억이 남지 않음
- “힘든 코딩 세션 후 무엇을 했는지 기억 못하는 이유”가 바로 이 때문
- 워크드 예제를 사용하면: 내재적+외재적 부하가 낮아 → 생산적 부하가 남아 LTM에 저장 가능 → 일반화 가능한 규칙 학습
- Paul Kirschner(네덜란드 심리학자): “전문가처럼 행동한다고 전문가가 되는 게 아니다” → 코딩만 많이 한다고 실력이 느는 것이 아님을 시사
10.4.2 워크드 예제를 실생활에 적용하는 방법
- 동료와 함께 코드 읽기: 코드 읽기 클럽(https://code-reading.org/) 결성 → 서로 코드와 설명 교환하며 학습. 챕터 5의 코드 요약 기법을 활용해 설명 작성 후 교환
- GitHub 탐색: 자신이 사용하는 라이브러리의 소스코드를 읽음. 도메인을 어느 정도 아는 코드베이스 선택 → 외재적 부하(모르는 개념) 최소화, 프로그래밍 자체에 집중
- 블로그 포스트 / 도서 활용: 특정 문제 해결 과정을 설명한 글, 또는 코드와 설명이 함께 있는 책 (예: The Architecture of Open Source Systems, 500 Lines or Less) 적극 활용
📌 파트 3 핵심 인사이트 통합 요약
| 주제 | 핵심 원칙 |
|---|---|
| 네이밍 | 완전한 단어가 이해를 돕고, 일관된 몰드가 LTM을 지원한다 |
| 네이밍 시점 | 코딩 중이 아닌 코드 리뷰 시 이름 품질을 검토하라 |
| 코드 스멜 | 구조적 문제는 인지 부하를 높이는 인지적 원인이 있다 |
| 언어적 안티패턴 | 이름과 실제 동작의 불일치가 구조 문제보다 인지 부하에 더 큰 영향 |
| 문제 해결 | 범용 기술이 아닌 도메인 특화 LTM 강화가 핵심 |
| 학습법 | 직접 문제를 많이 푸는 것보다 코드+설명(워크드 예제)을 읽는 것이 더 효과적 |
Part 4: 코드 협업하기
파트 개요: 지금까지 개인 개발자에 초점을 뒀다면, 파트 4는 팀 관점으로 전환 — 플로우 상태 진입법, 인지 친화적 대형 시스템 설계, 신규 개발자 온보딩을 다룬다.
11챕터: 코드 작성 행위
11.1 프로그래밍 중 다양한 활동
- 영국 연구자 Thomas Green, Alan Blackwell, Marian Petre의 인지적 표기법 차원 (CDN, Cognitive Dimensions of Notation) 프레임워크가 5가지 활동을 정의
- 각 활동은 서로 다른 메모리 시스템에 부담을 줌
5가지 프로그래밍 활동 개요
| 활동 | 주요 작업 | 부담 메모리 |
|---|---|---|
| 탐색 (Searching) | 버그 위치·메서드 호출·변수 초기화 위치 찾기 | 단기기억(STM) |
| 이해 (Comprehension) | 코드 기능 이해 (평균 58% 시간 소요) | 작업기억(WM) |
| 전사 (Transcription) | 명확한 계획을 코드로 그냥 옮기기 | 장기기억(LTM) |
| 증분 (Incrementation) | 새 기능 추가 (탐색+이해+전사 혼합) | 3가지 모두 |
| 탐험 (Exploration) | 방향이 불명확한 스케치형 코딩 | 3가지 모두 (특히 WM) |
11.1.1 탐색
- 버그 위치, 메서드 호출 위치, 변수 초기화 위치 등을 찾는 활동
- STM에 가장 부담 → 이미 탐색한 경로, 아직 탐색 안 한 경로, 탐색 대상을 동시에 기억해야 함
- 대응책: 탐색 대상·다음 탐색 위치·발견한 것을 메모로 외부화
- 코드에 “이 메서드를 읽은 이유” 같은 빵 부스러기(breadcrumb) 주석 남기기 → 나중에 같은 탐색을 재개할 때 도움
11.1.2 이해
- 코드 기능을 이해하는 활동 (오래 전 내가 쓴 코드 또는 타인의 코드)
- 개발자는 평균 58%의 시간을 기존 소스코드 이해에 씀
- 이해 방법: 코드 읽기, 테스트 실행, 리팩터링(이해를 쉽게 만들기 위한)
- 작업기억에 가장 부담 → 아직 다 이해하지 못한 코드에 대해 추론해야 함
- 대응책: 코드 모델을 그려서 매번 새로운 정보로 업데이트 → 뇌가 아닌 외부 소스에서 정보 인출
11.1.3 전사
- 구체적인 계획이 이미 있고 그것을 코드로 옮기는 활동 (“그냥 코딩”)
- LTM에 가장 부담 → 구문 구성을 상기해야 함
- 가장 순수한 형태에서는 단순히 코딩 외에 아무것도 하지 않음
11.1.4 증분
- 새 기능 추가 = 탐색 + 이해 + 전사의 혼합
- 3가지 메모리 시스템 모두에 부담 → 전문 프로그래머가 가장 자주 하는 작업임에도 가장 어려움
- 개인의 언어·코드베이스 친숙도에 따라 어느 시스템이 더 부담받는지가 달라짐
- 대응책: 증분 작업을 작은 하위 작업으로 분리 → “먼저 탐색, 그 다음 이해, 마지막으로 코드 추가” 순서로 명시적으로 수행
11.1.5 탐험
- 방향이 불명확한 상태에서 코드로 스케치하는 활동
- 코드 작성, 실행, 테스트, 읽기, 리팩터링이 빠른 연속으로 발생
- 작업기억에 특히 부담 → 즉흥적으로 계획과 설계를 만들면서 코딩
- 대응책: 설계 방향이나 결정을 거친 메모로 기록 → 메모가 흐름을 방해한다는 느낌이 들더라도 정신적 공간을 확보함
11.1.6 디버깅은 왜 없나?
- 디버깅은 사실 5가지 활동의 혼합 — 탐험 + 탐색 + 이해의 연속, 그 후 코드 작성
- 별도 활동이 아닌, 기존 5개 활동의 조합으로 설명 가능
11.2 프로그래머의 인터럽션
인터럽션의 빈도와 심각성
- Rini van Solingen (Delft 공대 교수)의 연구: 인터럽션은 매번 15~20분 소요, 개발자 시간의 **약 20%**를 인터럽션에 씀
- Chris Parnin의 연구 (86명 프로그래머, 10,000 프로그래밍 세션 기록): 평균 프로그래머는 하루에 방해받지 않는 2시간 연속 세션이 단 1회
- Microsoft 연구: 개발자의 **62%**가 인터럽션 후 복귀가 심각한 문제라고 인식
11.2.1 프로그래밍 작업에는 워밍업이 필요하다
- Takao Nakagawa (나라 과학기술 대학원)의 fNIRS(기능성 근적외선 분광) 연구:
- 참가자 10명 중 9명에서 작업 중 인지 부하의 큰 변동 발생 → 프로그래밍은 항상 어렵지 않음
- 인지 부하가 가장 높은 시점은 작업 중간 → 워밍업과 쿨다운 구간이 존재함을 시사
- 전문 프로그래머가 “몰입 상태”에 진입하기 전 워밍업 시간이 필요하다는 것은 현장에서도 공통적으로 인식됨
- 큰 프로그래밍 작업 내에서 하위 활동을 명시적으로 구분하면 도움
11.2.2 인터럽션 후 무슨 일이 생기나?
- Parnin 연구: 인터럽션 후 코드 편집을 재개하는 데 약 15분 소요
- 메서드 편집 중 인터럽션 발생 시, 1분 이내에 작업 재개에 성공하는 경우는 10%에 불과
- 복귀 시 개발자들의 행동:
- 여러 위치를 탐색하여 문맥 재구성
- 로드블록 리마인더(roadblock reminder): 컴파일 에러를 유발하는 임의 문자 삽입 → 코드를 미완성 상태로 두지 않기 위한 장치
- 최후 수단으로 현재 버전과 마스터 간 소스 diff 사용
11.2.3 인터럽션에 더 잘 대비하는 법
기법 1: 멘탈 모델 저장하기
- 메모, 모델 그리기, 리팩터링 같은 기법들 → 인터럽션 복구에도 유용
- Nakagawa의 결과: 워밍업 구간은 대부분 멘탈 모델 구축에 쓰임 → 모델을 코드 외부에 저장하면 복구 시간 단축
- 주석의 가치 재평가:
- “코드가 자기 자체를 설명해야 한다(self-documenting)“는 통념 존재
- 하지만 코드는 설계자의 사고 과정을 거의 표현하지 못함
- John Ousterhout (The Philosophy of Software Design): “주석의 목적은 설계자의 마음속에 있었지만 코드로 표현될 수 없었던 정보를 담는 것”
- Fred Brooks (The Mythical Man-Month): 주석은 항상 코드와 함께 존재하기 때문에 프로그램 이해 과정에서 가장 중요
- 잠깐 인터럽션을 미룰 수 있다면 (Slack 메시지, 대기 가능한 동료 등) → 최신 멘탈 모델을 코드 주석으로 브레인 덤프하라
기법 2: 예비 기억 지원하기
- 예비 기억(Prospective Memory): 미래에 무언가를 해야 한다는 것을 기억하는 능력 → 계획·문제 해결과 밀접히 연관
- 개발자들의 예비 기억 지원 방법:
- TODO 주석: GitHub에서 “to-do” 포함 코드 결과 1억 3,600만 건 → 오랫동안 해결되지 않는 경우 다반사
- 의도적 컴파일 에러 삽입
- 포스트잇·자신에게 이메일 보내기 (단, 코드베이스와 단절)
- Chris Parnin이 만든 Visual Studio 플러그인: 코드에 to-do 항목 추가 + 만료 날짜 설정 기능
기법 3: 서브골 레이블링
-
문제를 어떤 작은 단계로 나눌 수 있는지 명시적으로 기록하는 방법
-
예시 (텍스트 파싱·재구성 작업):
# 텍스트를 파싱하고 파스 트리 받기 # 파스 트리 필터링 # 트리를 다시 텍스트 형식으로 평탄화 -
Georgia State University의 Lauren Margulieux 교수 연구: 서브골 제공 시 프로그래머는 이를 사용해 해결책을 정신적으로 구조화
-
서브골의 추가 용도:
- 코드에 남겨진 주석이 나중에 문서화 역할
- 시니어가 서브골을 설계하고 다른 프로그래머가 구현하는 협업 구조에도 활용 가능
11.2.4 언제 프로그래머를 방해해야 하나?
- 이중 작업 측정(Dual-Task Measure): 원래 작업 수행 중 화면에 나타나는 문자 A를 클릭하는 2차 작업 → 2차 작업 응답 속도로 인지 부하 측정
- Brian P. Bailey (일리노이대 컴퓨터공학 교수) 연구 (2001):
- 인터럽션 발생 시 작업 완료 시간 증가
- 인터럽션된 작업을 더 어렵다고 인식
- 작업 중 인터럽션받은 그룹이 후에 받은 그룹보다 더 짜증·불안 수준이 높음
- 2006년 후속 연구: 인터럽션받은 사람은 오류율 2배 증가
- 결론: 인터럽션은 인지 부하가 낮은 순간(예: 작업 완료 후)에 발생할 때 훨씬 덜 해롭다
- FlowLight (Manuela Züger, 취리히대 박사): 컴퓨터 타이핑 속도·마우스 클릭으로 개발자의 몰입 상태 감지 → 빨간 점멸/빨간 상시/초록 신호
- 12개국 400명 이상 참가자 대상 현장 연구: 인터럽션 46% 감소
- 현재 상업 제품으로 판매 중 (https://emea.embrava.com/pages/flow)
11.2.5 멀티태스킹에 대한 몇 가지 생각
- 멀티태스킹의 한계: 깊은 인지 작업에서는 멀티태스킹이 불가능하다는 압도적인 증거
- 단, 자동화(autonomous) 단계에 도달한 작업들은 동시에 수행 가능 (예: 뜨개질하며 읽기)
- 어려운 단락을 읽을 때 음악을 끄고 싶어지는 것이 이 현상의 증거
멀티태스킹 연구 결과
- Annie Beth Fox (2009): 문자 메신저를 사용하며 텍스트 읽은 그룹 → 이해도는 동일하나 시간 50% 더 소요
- Paul Kirschner (2010, 약 200명 학생): 헤비 Facebook 사용자는 공부 시간은 동일하지만 성적 평균 유의미하게 낮음 (특히 즉시 답장하는 학생)
- 온라인 메시징하며 작업 시 학생 본인은 성과에 만족하지만, 파트너는 훨씬 낮게 평가 → Slack 채팅하며 코딩은 생산성에 좋지 않음
12챕터: 대형 시스템 설계 및 개선
12.1 코드베이스의 속성 검토
- 코드베이스는 기술적 관점(무엇을 할 수 있는가)과 인지적 관점(당신의 뇌에 무엇을 하는가) 모두로 살펴볼 수 있음
- CDN → **CDCB(Cognitive Dimensions of CodeBases)**로 확장: 코드베이스가 얼마나 이해하기 쉽고, 변경하기 쉽고, 정보를 찾기 쉬운지를 인지적으로 평가
12.1.1 인지적 차원
1. 오류 유발성
- 언어나 코드베이스가 실수를 유발하기 쉬운 정도
- JavaScript 등 동적 타입 언어 → 타입 불명확으로 오류 유발 쉬움
- Haskell 등 강한 타입 시스템 → 오류 유발성 낮음
- Stefan Hanenberg 연구: Java vs Groovy 비교 → 타입 시스템이 오류 발견 및 수정 속도를 실제로 향상시킴, IDE 지원·문서화로 개선해도 정적 타입이 우세
- 코드베이스 자체도 비일관적 관례, 문서 부족, 모호한 이름으로 오류 유발 가능
2. 일관성
- 유사한 것들이 얼마나 유사하게 표현되는가
- 이름 구조, 파일 레이아웃, 함수 호출 방식의 일관성
- 예시: 내장 함수(print())와 사용자 정의 함수(print_customer())는 호출 방식이 동일 → 일관성의 좋은 예
- 비일관적 코드베이스 → 더 높은 인지 부하, 정보 탐색 시간 증가
3. 확산성
- 동일한 기능을 표현하는 데 얼마나 많은 공간이 필요한가
- Python의 for 루프(2줄, 7개 청크) vs C++의 for 루프(3줄, 9개 청크)
- 같은 언어 내에서도 차이 가능 → 리스트 컴프리헨션은 일반 for 루프보다 확산성이 낮음
- 확산성이 낮다고 무조건 좋지는 않음 — 가독성·이해도와의 균형이 중요
4. 숨겨진 의존성
- 의존 관계가 사용자에게 얼마나 보이는가
- 예시: JavaScript가 별도 파일에 있는 HTML 버튼 제어 → 어디서 호출되는지 보이지 않음
- 함수가 호출하는 것은 보이지만, 어디서 호출되는지는 보이지 않는 경우가 흔함
- 현대 IDE는 이를 드러낼 수 있지만 여전히 마우스 클릭·단축키 필요
- 대응: 더 상세한 문서화, 새 의존성 채택·문서화 정책 수립
5. 잠정성
- 도구를 사용하는 동안 얼마나 자유롭게 생각할 수 있는가
- 종이·화이트보드 → 최고의 잠정성 (불완전한 코드, 주석, 틀린 코드도 자유롭게)
- 타입·어서션·사후조건이 매우 엄격한 코드베이스 → 낮은 잠정성
- 잠정성은 학습에도 중요 → 초보자에게 불완전한 아이디어 표현이 필요함
6. 점성
- 시스템에서 변경을 가하기가 얼마나 어려운가
- 동적 타입 언어 → 변경 용이 (타입 정의 변경 불필요)
- 비모듈화된 대규모 코드 블록 → 변경 용이 (한 곳만 바꾸면 됨)
- 컴파일·테스트 실행 시간도 점성에 영향
7. 점진적 평가
- 불완전하거나 불완벽한 코드를 부분적으로 실행·확인할 수 있는 정도
- Smalltalk: 최초로 라이브 프로그래밍을 지원, 실행 중에도 코드 변경 가능
- Scratch(어린이 언어): 재컴파일 없이 코드 변경 가능
- 설계 시 점진적 평가를 높이는 방법: 선택적 파라미터 제공 (기본값으로 먼저 실행, 이후 파라미터 하나씩 변경)
- Idris의 hole 시스템: 부분 코드 실행 후 컴파일러가 가능한 해결책을 제안
8. 역할 표현성
- 코드의 각 부분이 프로그램에서 어떤 역할을 하는지 얼마나 쉽게 알 수 있는가
- 예시: 파라미터 없는 함수도
file.open()처럼 괄호를 붙임 → 함수임을 표시 - 신택스 하이라이팅: 변수와 키워드를 다른 색으로 → 역할 표현성 향상
is_setvsset: Boolean 반환 함수에is_접두사 → 역할 명확화- 언어적 안티패턴(9장 내용)이 있으면 역할 표현성 저하
9. 매핑 근접성
- 코드가 문제가 해결되는 도메인에 얼마나 가까운가
- APL → 벡터 계산 도메인에 탁월한 매핑 근접성
- COBOL → 비즈니스·금융 도메인에 좋은 매핑 근접성
- Java·Python·JavaScript → 범용이므로 매핑 근접성 낮지만 유연성이 장점
- 코드베이스 수준:
executeQuery()<findCustomers()(후자가 도메인에 더 가까움) - 도메인 주도 설계(DDD): 코드의 구조·식별자가 비즈니스 도메인과 일치해야 한다는 철학 → 매핑 근접성 향상 추구
10. 어려운 정신 작업
- 시스템이 사용자에게 요구하는 외부 정신 작업의 난이도
- Haskell → 모든 함수의 타입 시그니처 추론 필요
- C++ → 포인터를 사용해야 하는 많은 상황
- 어려운 정신 작업이 나쁜 것만은 아님: 타입 시스템의 엄격함은 오류 감소, 포인터는 성능·메모리 효율 향상
- 코드베이스 수준의 예:
- 많은 파라미터를 순서대로 암기해야 하는 경우 → STM 부담
execute(),control()같은 정보 없는 이름 → LTM 부담- 두 데이터 소스를 다른 포맷으로 가져와 세 번째 포맷으로 변환 → WM 부담
11. 이차 표기법
-
공식 명세에는 없지만 추가 의미를 부여할 수 있는 가능성
-
가장 흔한 예: 주석 (프로그램 동작을 바꾸지 않지만 이해를 도움)
-
Python의 명명 파라미터(named parameters): 함수 호출 시 파라미터 이름을 함께 전달 → 실행 방식은 동일하나 역할 표현성 향상
move(angle=90, power=100) # 이차 표기법의 예
12. 추상화
- 사용자가 내장 추상화만큼 강력한 자체 추상화를 생성할 수 있는가
- 대부분의 언어: 함수·객체·클래스 생성 가능 → 내장 함수와 동일한 방식으로 동작
- 라이브러리·프레임워크: 서브클래스 생성 허용 여부가 추상화 수준을 결정
13. 가시성
- 시스템의 다양한 부분을 얼마나 쉽게 볼 수 있는가
- 코드베이스에서 어떤 클래스가 있는지 파악이 어려울 수 있음 (여러 파일 분산)
- API 반환 타입: 문자열 < JSON 파일 < 객체 (후자로 갈수록 데이터 형태가 더 보임)
12.1.2 CDCB로 코드베이스 개선하기
- 각 차원의 목록을 체크리스트처럼 사용
- 모든 차원이 모든 코드베이스에 중요하지는 않음
- 정기적으로(예: 연 1회) 각 차원을 검토하고 코드베이스 상태를 평가 권장
- 높은 점성 → 개발자들이 구조적 변경보다 복잡한 패치를 선호하게 됨
- 어려운 정신 작업을 요구하는 오픈소스 코드베이스 → 유지보수자가 줄어들 가능성
12.1.3 설계 기동과 트레이드오프
- 설계 기동(Design Maneuver): 특정 차원을 개선하기 위해 코드베이스를 변경하는 것
- 타입 추가 → 오류 유발성 개선
- 도메인 용어에 맞게 함수명 변경 → 매핑 근접성 개선
- 하나의 차원 개선이 다른 차원에 영향을 주는 경우가 많음
주요 트레이드오프
| 차원 A | vs | 차원 B | 설명 |
|---|---|---|---|
| 오류 유발성 ↓ | ↔ | 점성 ↑ | 타입 추가 시 오류 감소, 하지만 변경 시 추가 작업 증가 |
| 잠정성·점진적 평가 ↑ | ↔ | 오류 유발성 ↑ | 불완전한 코드 허용이 그대로 남겨질 위험 증가 |
| 역할 표현성 ↑ | ↔ | 확산성 ↑ | 명명 파라미터·타입 주석이 역할을 명확히 하지만 코드 길이 증가 |
12.2 차원과 활동의 관계
12.2.1 차원이 각 활동에 미치는 영향
| 차원 | 도움이 되는 활동 | 방해가 되는 활동 |
|---|---|---|
| 오류 유발성 | 증분 | — |
| 일관성 | 탐색, 이해 | 전사 |
| 확산성 | 탐색 | — |
| 숨겨진 의존성 | — | 탐색 |
| 잠정성 | 탐험 | — |
| 점성 | — | 전사, 증분 |
| 점진적 평가 | 탐험 | — |
| 역할 표현성 | 이해 | — |
| 매핑 근접성 | 증분 | — |
| 어려운 정신 작업 | — | 전사, 증분, 탐험 |
| 이차 표기법 | 탐색 | — |
| 추상화 | 이해 | 탐험 |
| 가시성 | 이해 | — |
- 탐색 시: 숨겨진 의존성(해로움), 확산성(해로움), 이차 표기법(유익)
- 이해 시: 낮은 가시성(해로움), 역할 표현성(유익)
- 전사 시: 일관성은 보통 좋으나, 새 코드를 기존 스타일에 맞추는 추가 노력 유발
- 증분 시: 매핑 근접성(유익, 도메인 관점 유지), 높은 점성(해로움)
- 탐험 시: 잠정성·점진적 평가(유익), 어려운 정신 작업·추상화(해로움, 인지 부하↑)
12.2.2 예상 활동에 맞게 코드베이스 최적화
- 코드베이스의 생애 주기에 따라 주요 활동이 바뀜
- 오래되고 안정적인 라이브러리 → 탐색이 주 → 탐색에 유리한 차원 최적화
- 새로운 앱 → 증분·전사가 주 → 해당 차원 최적화
- 시간이 지남에 따라 코드베이스의 특성에 맞게 설계 기동 재적용 필요
13챕터: 신규 개발자 온보딩
13.1 온보딩 프로세스의 문제점
흔한 실패 패턴
- 시니어 개발자가 신규 개발자에게 한꺼번에 너무 많은 정보 전달 → 인지 부하 과부하
- 새로운 팀원, 도메인, 워크플로우, 코드베이스를 동시에 소개
- 시니어는 “매우 간단한” 과제(작은 버그 수정·기능 추가)를 부여
- 신규 개발자는 높은 인지 부하로 인해 실패
- 근본 원인: 시니어가 신규 개발자 작업기억의 처리 용량을 초과시킴
- 도메인/언어에 대한 청크 부재 + 자동화된 기술 미흡
- 결과: 팀리더는 신규 개발자가 능력이 없다고 오판, 신규 개발자는 프로젝트가 너무 어렵다고 오판
전문성의 저주
- 어떤 기술을 충분히 습득하면 그 기술을 배우는 것이 얼마나 어려웠는지를 필연적으로 잊게 됨
- “별로 어렵지 않아”, “사실 꽤 쉬워”, “사소한 거야” → 이런 말이 나오는 순간이 전문성 저주의 순간
13.2 전문가와 초보자의 차이
전문가의 특징
- LTM에 저장된 방대한 관련 기억 → 작업기억이 효과적으로 인출
- 전략적 기억(테스트 먼저 작성하기 등), 에피소드 기억(서버 재부팅 시도 등)
- 코드·오류 메시지·테스트·문제·해결책을 효과적으로 청킹 → “큐를 비우는 코드”를 한눈에 파악
초보자의 특징
- “Array index out of bounds”가 전문가에겐 1개 개념이지만 초보자에겐 3개 별개 요소 → 더 높은 인지 부하
- 코드를 줄 단위로 읽어야 하는 경우가 많음
- 많은 “능력 없어 보이는 동료” 상황이 실은 과부하된 초보자임
13.2.1 초보자의 행동 심층 분석 — Neo-Piagetism
Piaget의 원래 모델
| 단계 | 연령 | 특징 |
|---|---|---|
| 감각운동기 (Sensorimotor) | 0–2세 | 계획·전략 없음, 감각과 행동만 |
| 전조작기 (Preoperational) | 2–7세 | 가설 형성하지만 불안정하게 사용 |
| 구체적 조작기 (Concrete Operational) | 7–11세 | 구체적 상황에서 추론 가능, 일반화는 어려움 |
| 형식적 조작기 (Formal Operational) | 11세 이상 | 형식적 추론 가능 |
프로그래밍을 위한 Neo-Piagetian 모델
| 단계 | 프로그래밍 행동 | 교육 시사점 |
|---|---|---|
| 감각운동기 | 프로그램 실행을 올바르게 추적(trace) 불가, 비일관적 이해 | 실행 모델 이해가 우선; 다른 부분 설명은 무의미 |
| 전조작기 | 여러 줄 코드 결과를 추적 테이블로 예측 가능; 귀납적 추론, 코드 의미 설명 어려움 | 다이어그램 비효율적; 추측 기반 행동이 많음; 플래시카드로 코드 어휘 확장 |
| 구체적 조작기 | 친숙한 청크 인식, 필요 시에만 추적; 연역적 추론; 전략 반성은 어려움 | 다이어그램이 비로소 유용해짐; 전략 고집(하루 종일 같은 방법으로 버그 수정 시도) 주의 |
| 형식적 조작기 | 논리적·일관적·체계적 추론; 자기 행동 반성 가능 (디버깅에 필수) | 스스로 코드베이스 탐색 가능; 도움 요청 가능 |
- 핵심 통찰: Neo-Piagetism의 단계는 도메인 특정적 → Python 전문가도 Haskell에서는 감각운동기로 돌아갈 수 있음
- 새 개념 학습 시 일시적으로 낮은 단계로 회귀 가능 (예: Python 가변 인자 함수 학습 시)
- 단계는 이산적이지 않고 연속적
13.2.2 구체적 개념과 추상적 개념의 차이
- 전문가는 추상적·일반적 용어로 설명하는 경향 (“가변 인자 함수는 다양한 수의 인자를 받을 수 있다”)
- 하지만 구체적 세부 사항(어떻게 접근하는지, 이름은 어떻게 주는지, 한계가 있는지)을 빠뜨림
- 초보자는 추상과 구체 양쪽이 모두 필요
의미 파동 — Karl Maton
이상적인 설명은 파동 형태를 따름:
- 추상적 출발: 개념의 용도·이유 (“가변 인자는 필요한 만큼 인자를 쓸 수 있어서 유용”)
- 언패킹(Unpacking): 구체적 세부 사항으로 내려감 (Python에서
*사용, 인자가 리스트로 구현됨) - 리패킹(Repacking): 다시 추상 수준으로 올라와 LTM에 통합 (“C++는 가변 인자를 지원하지만 Erlang은 지원하지 않음”)
3가지 안티패턴
- 높은 평탄선(High Flatline): 추상적 설명만 → 신택스를 모르면 나중에 많이 배워야 함
- 낮은 평탄선(Low Flatline): 구체적 세부사항만 → 왜 필요한지 모르면 의미가 없음
- 하향 에스컬레이터(Downward Escalator): 추상→구체는 가지만 리패킹 시간을 주지 않음 → 새 지식을 LTM에 통합 못 함
- 리패킹을 지원하는 방법: 신규 개념과 이전 지식 간의 공통점을 명시적으로 묻기
13.3 더 나은 온보딩 프로세스를 위한 활동
가장 중요한 원칙: 온보딩하는 사람의 인지 부하를 의도적으로 관리하는 것
- 인지 과학 용어의 공유 언어 구축: “이 코드를 읽으면서 인지 부하가 너무 높아요”, “저는 Python에 대한 청크가 부족한 것 같아요” → 막연한 “헷갈려요”보다 훨씬 구체적·효율적
13.3.1 프로그래밍 활동을 하나씩 제한하기
- 온보딩 시 신규 개발자는 최소 4가지 활동을 동시에 수행 요청받음 (탐색·이해·탐험·증분)
- 해결책: 5가지 활동 각각에 해당하는 과제를 개별적으로 설계하고 순서대로 수행
| 활동 | 온보딩 예시 과제 |
|---|---|
| 탐험 | 코드베이스를 전체적으로 훑어보기 |
| 탐색 | 특정 인터페이스를 구현하는 클래스 찾기 |
| 전사 | 미리 준비된 계획을 기반으로 특정 메서드 구현 |
| 이해 | 특정 메서드를 자연어로 요약 |
| 증분 | 기존 클래스에 기능 추가 (계획 수립 포함) |
- 활동들은 서로 이어지게 설계 가능 (예: 클래스 탐색 → 그 클래스의 메서드 전사 → 클래스 증분)
- 도메인 학습과 언어 개념 학습을 교대로 배치 가능 (기존 지식에 따라)
13.3.2 온보딩 대상자의 기억 지원하기
LTM 지원: 관련 정보 미리 설명하기
- 신규 개발자 도착 전 기존 팀이 준비 → 코드 작업 중 처음 접하는 것보다 훨씬 효과적
- 준비 자료:
- 코드에서 자주 등장하는 도메인 개념 문서화 (플래시카드 제작 권장)
- 사용하는 라이브러리·프레임워크·데이터베이스·외부 도구 목록화
- “Laravel로 만든 웹앱을 Jenkins로 Heroku에 배포해요” → 개별 도구를 모르면 문장 전체가 의미 없음
- 도메인 학습과 코드 탐색을 분리: 별도로 개념을 익히고 나서 코드를 탐색 → 큰 차이 발생
- 신규 개발자가 없어도 이 개념 목록 자체가 기존 개발자에게도 유용
STM 지원: 작고 집중된 과제 준비하기
- 흔한 실수: 신규 개발자에게 “codebase를 파악하기 위해” 간단한 기능 구현 요청
- 실제로는 탐색+이해+증분을 동시에 요구 → STM 과부하
- 이해가 구현보다 더 좋은 첫 번째 과제
- 기존 클래스 요약 작성
- 특정 기능 실행에 관여하는 모든 클래스 목록 작성
- 구현 과제를 주고 싶다면: 관련 코드를 미리 준비해 탐색 부담 제거 (4장의 리팩터링 기법 활용)
작업기억 지원: 다이어그램 그리기
- 작업기억 지원 기법 (4장) → 온보딩에도 적용 가능
- 단, 절대적 초보자에게 다이어그램은 비효율적일 수 있음 → 다이어그램이 도움이 되는지 자주 확인, 도움 안 되면 포기
13.3.3 코드를 함께 읽기
5장에서 개인 코드 읽기 기법으로 제안했던 7가지 기법 → 팀 온보딩에도 적용 가능
| 기법 | 온보딩 적용 방식 |
|---|---|
| 활성화 (Activating) | 읽기 세션 전 관련 개념 복습 → 코드 탐색 중 발견하는 것보다 효율적 (예: MVC 패턴을 미리 소개) |
| 중요도 파악 (Determining Importance) | 초보자는 핵심과 비핵심 구분이 어려움 → 팀이 가장 중요한 코드 라인 지정, 또는 이전 세션의 하이라이트 문서 공유 |
| 추론 (Inferring) | 암묵적 규칙(예: “배송에는 반드시 주문이 1개 이상 포함”) 명시적으로 언급, 또는 문서화 |
| 모니터링 (Monitoring) | 신규 개발자에게 정기적으로 요약·도메인 개념 정의·프로그래밍 개념 상기 요청 → 이해 수준 추적 |
| 시각화 (Visualizing) | 레벨에 따라: 온보더가 다이어그램을 제공(작업기억 지원) 또는 신규 개발자가 직접 그리게 함(이해 심화) |
| 질문하기 (Questioning) | 신규 개발자 레벨에 따라: 온보더가 질문하고 신규 개발자가 답, 또는 그 반대; 추론 유도하되 인지 부하 항상 모니터링 |
| 요약하기 (Summarizing) | 함께 읽은 코드 요약 작성 → 코드베이스에 문서로 커밋 (신규 개발자 첫 pull request로 좋음, 무섭지 않고 작업기억 부담도 적음) |
핵심 인사이트 총정리
- 5가지 활동 인식: 현재 자신이 탐색·이해·전사·증분·탐험 중 어디에 있는지 알면, 적합한 메모리 지원 전략을 선택할 수 있다
- 인터럽션은 예방보다 관리: 완전 차단은 불가능 → 멘탈 모델 저장·예비 기억 지원·서브골 레이블링으로 복구 비용을 줄여라
- 코드베이스는 인지적으로도 설계된다: CDN/CDCB 차원을 정기적으로 검토하고 가장 자주 발생하는 활동에 맞게 설계 기동을 적용하라
- 초보자는 느린 전문가가 아니다: 신호 처리 방식 자체가 다르다 → Neo-Piagetian 단계에 맞춘 피드백·과제·설명이 필요하다
- 온보딩은 인지 과학이다: 인지 부하 관리, 의미 파동을 따른 설명, 활동 분리, 기억 시스템별 지원이 온보딩 효율을 극적으로 높인다