- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며 — 왜 지금 이 이야기인가
- 답과 이해는 다르다
- 추상화 너머를 보는 가치
- 이해의 다섯 층위 — 복사에서 창조까지
- 디버깅 — 이해가 드러나는 순간
- 통제와 소유권 — 이해가 주는 것
- 학습으로서의 이해 — 우회로의 가치
- 팀 차원의 이해 — 개인을 넘어서
- 균형 — 언제 추상화에 기대도 되나
- LLM과 이해의 건강한 관계 — 증폭기로 쓰기
- 실무에 적용하기 — 이해를 쌓는 습관
- 함정과 비판적 시각
- 자주 나오는 질문
- 마치며 — 이해라는 기쁨을 지키기
- 참고 자료
들어가며 — 왜 지금 이 이야기인가
2026년의 GeekNews와 Hacker News에는 한동안 같은 정서의 글들이 번갈아 올라왔습니다. 핵심은 이렇게 요약됩니다. "LLM이 코드를 대신 써 주는 시대에, 우리는 정말로 무언가를 이해하고 있는가, 아니면 그저 답을 받아 적고 있는가."
한 개발자(binaryigor)가 쓴 "이해의 기쁨(the joy of understanding)"에 관한 글이 특히 많은 공감을 얻었습니다. 요지는 간단합니다. 검색과 LLM은 우리에게 즉각적인 답을 주지만, 그 답을 진짜로 이해하는 것은 별개의 일이며, 그 이해야말로 엔지니어링의 기쁨이자 힘의 원천이라는 것입니다.
이 주장이 지금 울림을 갖는 이유는 분명합니다. AI 코딩 도구가 보편화되면서, 우리는 어느 때보다 빠르게 "작동하는 코드"에 도달할 수 있게 됐습니다. 그런데 동시에, 그 코드가 왜 작동하는지를 점점 덜 이해하게 되는 위험도 커졌습니다. 작동하지만 이해하지 못하는 코드. 이것이 2026년 엔지니어가 마주한 새로운 형태의 부채입니다.
이 글은 LLM을 거부하자는 러다이트 선언이 아닙니다. 오히려 LLM이라는 강력한 도구를 쓰면서도 어떻게 이해의 깊이를 잃지 않을 것인가, 그리고 왜 그 깊이가 여전히 결정적으로 중요한가에 관한 이야기입니다. 추상화 너머를 보는 것의 가치, 디버깅에서 드러나는 이해의 차이, 학습으로서의 이해, 그리고 언제 추상화에 안심하고 기대도 되는지의 균형까지 차례로 다룹니다.
흥미로운 점은, 이런 정서가 LLM 회의론자가 아니라 오히려 LLM을 적극적으로 쓰는 사람들 사이에서 퍼졌다는 것입니다. 도구를 깊이 써 본 사람일수록, 그 도구가 무엇을 주고 무엇을 빼앗는지를 더 선명하게 느낍니다. 빠른 답을 충분히 누려 본 다음에야, 답만으로는 채워지지 않는 무언가가 있다는 것을 깨닫게 되는 셈입니다. 이 글의 출발점도 거기에 있습니다.
답과 이해는 다르다
빠른 답의 함정
먼저 "답"과 "이해"를 구분해 봅시다. 이 둘은 같아 보이지만 전혀 다른 것입니다.
답 (Answer) 이해 (Understanding)
------------------- -------------------------
- 즉각적 - 시간이 걸림
- 복사 가능 - 전이 가능 (다른 문제에 적용)
- 표면적으로 작동 - 왜 작동하는지 앎
- 맥락이 바뀌면 무력 - 맥락이 바뀌어도 재구성 가능
- 검색/LLM이 줌 - 스스로 만들어야 함
답은 휘발성이 강합니다. 똑같은 문제가 다시 와도, 답만 받았던 사람은 다시 검색해야 합니다. 반면 이해한 사람은 그 답을 재생산할 수 있고, 더 중요하게는 약간 다른 문제에도 그 이해를 적용할 수 있습니다.
LLM 시대의 위험은, 답에 도달하는 비용이 거의 0으로 떨어지면서 이해를 건너뛰려는 유혹이 극대화된다는 점입니다. 예전에는 답을 찾는 과정 자체에 이해가 일부 섞여 들어왔습니다. 문서를 읽고, 예제를 따라 하고, 실패하면서 우리는 어쩔 수 없이 조금씩 이해했습니다. 그런데 LLM은 그 과정을 통째로 압축해 버립니다. 질문하면 작동하는 코드가 나옵니다. 이해라는 우회로를 거치지 않아도 목적지에 도착합니다.
작동하지만 이해 못 하는 코드
여기서 새로운 종류의 코드가 생깁니다. "작동하지만 작성자가 이해하지 못하는 코드." 이것은 단순히 복사한 코드와도 다릅니다. 적어도 스택오버플로에서 복사할 때는 "이 답이 내 문제에 맞는가"를 잠깐이라도 판단해야 했습니다. LLM은 내 맥락에 맞춰 코드를 생성해 주기 때문에, 그 판단의 필요성마저 줄여 버립니다.
이런 코드의 문제는 평상시에는 드러나지 않습니다. 작동하니까요. 문제는 항상 경계 상황에서 터집니다. 부하가 몰릴 때, 입력이 예상을 벗어날 때, 의존성이 업데이트될 때. 그때 우리는 자신이 작성한 코드 앞에서 낯선 사람이 됩니다.
추상화 너머를 보는 가치
추상화는 거짓말을 한다
소프트웨어는 추상화의 탑입니다. 우리는 함수를 호출하고, 그 함수는 라이브러리를 호출하고, 라이브러리는 시스템콜을 부르고, 시스템콜은 커널로, 커널은 하드웨어로 내려갑니다. 각 층은 아래층의 복잡함을 숨겨 줍니다. 이것이 추상화의 축복입니다.
그런데 유명한 격언이 있습니다. "모든 비자명한 추상화는 어느 정도 새어 나온다(All non-trivial abstractions, to some degree, are leaky)." 추상화는 평소에는 아래층을 완벽히 숨기는 척하지만, 결정적인 순간에 그 거짓말이 드러납니다.
당신의 코드
|
[ ORM ] <- "그냥 객체를 저장할 뿐"
|
[ SQL ] <- 사실은 쿼리가 생성됨 (N+1 문제!)
|
[ 인덱스/플래너 ] <- 사실은 풀스캔이 일어남
|
[ 디스크 I/O ] <- 사실은 랜덤 I/O로 느려짐
ORM은 "객체를 저장할 뿐"이라고 말하지만, 그 아래에서는 SQL이 생성되고, 인덱스가 쓰이거나 안 쓰이고, 디스크 I/O가 발생합니다. 성능 문제가 터졌을 때, ORM이라는 추상화만 아는 사람은 막막합니다. 반면 그 아래 SQL과 인덱스를 이해하는 사람은 새어 나온 추상화의 틈을 들여다보고 문제를 고칠 수 있습니다.
한 층 아래를 아는 것의 복리 효과
깊이 이해한다는 것은 모든 것을 안다는 뜻이 아닙니다. 보통은 "내가 매일 쓰는 추상화의 한 층 아래"를 아는 것으로 충분합니다. 그리고 이 "한 층 아래"의 지식은 복리로 불어납니다.
- 웹 프레임워크를 쓴다면, HTTP의 한 층 아래(요청/응답, 헤더, 상태 코드)를 알라.
- ORM을 쓴다면, SQL과 인덱스를 알라.
- 컨테이너를 쓴다면, 리눅스의 네임스페이스와 cgroup을 알라.
- 가비지 컬렉션 언어를 쓴다면, 메모리 할당과 GC의 동작을 알라.
각 층을 한 단계만 더 깊이 이해해도, 추상화가 새어 나오는 순간 당황하지 않게 됩니다. 그리고 이런 이해들은 서로 연결되어, 시간이 지날수록 시스템 전체를 보는 직관으로 자랍니다. 이것이 이해의 복리입니다.
이해의 다섯 층위 — 복사에서 창조까지
같은 코드, 다른 깊이
"이해한다"는 말은 사실 한 가지가 아닙니다. 같은 코드를 두고도 사람마다 이해의 깊이가 다릅니다. 다섯 층위로 나눠 보면 자기 위치를 점검하기 좋습니다.
층위 5: 창조 - 이 패턴을 새 문제에 적용/변형할 수 있다
층위 4: 평가 - 이 코드의 약점과 대안을 비판할 수 있다
층위 3: 설명 - 왜 이렇게 작동하는지 남에게 설명할 수 있다
층위 2: 추적 - 입력이 어떻게 출력으로 변하는지 따라갈 수 있다
층위 1: 복사 - 작동하는 코드를 가져다 붙일 수 있다
LLM은 우리를 순식간에 층위 1(복사)에 올려놓습니다. 작동하는 코드가 즉시 손에 들어옵니다. 그런데 진짜 가치는 층위 3 이상에서 나옵니다. 설명할 수 있어야 디버깅하고, 평가할 수 있어야 LLM의 제안을 거부하고, 창조할 수 있어야 새 문제를 풉니다.
구체적인 예 — 디바운스 함수
흔한 디바운스 함수를 예로 들어 봅시다.
// debounce — 마지막 호출 후 일정 시간 지나야 실제 실행
function debounce(fn, delay) {
let timer = null;
return function (...args) {
clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
- 층위 1(복사): 이 코드를 붙여 넣고 작동하면 만족한다.
- 층위 2(추적): 호출이 연달아 오면 timer가 매번 취소되고 다시 설정되는 흐름을 따라간다.
- 층위 3(설명): 왜 클로저로 timer를 가둬야 하는지, apply로 this를 보존하는 이유를 설명한다.
- 층위 4(평가): 즉시 실행 옵션(leading edge)이 없다는 약점, 취소 메서드가 없다는 한계를 짚는다.
- 층위 5(창조): 같은 클로저 원리로 쓰로틀(throttle)을 직접 만들고, 두 패턴의 차이를 설명한다.
LLM은 층위 5의 코드도 즉시 줄 수 있습니다. 그러나 그 코드를 받아 층위 4로 평가하지 못하면, 우리는 그것이 내 상황에 맞는지조차 모른 채 쓰게 됩니다. 이해의 층위를 올리는 일은 LLM을 더 잘 쓰기 위한 일이기도 합니다.
디버깅 — 이해가 드러나는 순간
장애 앞에서 갈리는 두 사람
이해의 가치가 가장 극적으로 드러나는 순간은 장애입니다. 새벽 3시, 프로덕션이 죽었습니다. 로그는 모호하고, 에러 메시지는 추상화의 가장 윗층에서만 나옵니다. 여기서 두 부류의 엔지니어가 갈립니다.
답만 모아 온 엔지니어는 에러 메시지를 그대로 검색창이나 LLM에 붙여 넣습니다. 운이 좋으면 비슷한 사례가 나오고, 운이 나쁘면 그렇지 않습니다. 이 사람은 시스템의 정신 모델이 없기 때문에, 검색 결과가 자기 상황에 맞는지조차 판단하기 어렵습니다.
이해한 엔지니어는 다릅니다. 머릿속에 시스템의 정신 모델이 있습니다. "이 증상이라면 여기 아니면 저기다. 둘 중 하나를 배제하려면 이 로그를 보면 된다." 가설을 세우고, 검증하고, 좁혀 갑니다. LLM을 쓰더라도, 그것은 자기 가설을 검증하는 도구이지 가설 그 자체를 대신하지 못합니다.
답 수집형 디버깅 이해 기반 디버깅
---------------- -----------------------
에러 메시지 -> 검색 증상 -> 정신 모델 -> 가설
결과 붙여넣기 -> 시도 가설 -> 검증 실험 설계
안 되면 또 검색 결과로 가설 좁히기
운에 의존 체계적 수렴
정신 모델은 검색되지 않는다
핵심은 이것입니다. 정신 모델은 검색되지 않습니다. LLM은 일반적 지식을 줄 수 있지만, "지금 당신의 시스템이 어떻게 생겼는가"에 대한 모델은 당신만 가질 수 있습니다. 그리고 그 모델은 평소에 깊이 이해해 두지 않으면 위기의 순간에 갑자기 생겨나지 않습니다.
장애 대응은 평소 이해의 잔고를 인출하는 일입니다. 평소에 답만 받아 적었다면, 위기에 인출할 잔고가 없습니다. 평소에 이해를 쌓아 뒀다면, 위기에 그 이해가 당신을 구합니다.
짧은 사례 — 같은 증상, 다른 결말
구체적인 가상의 사례로 차이를 그려 봅시다. 어느 API의 응답 지연이 갑자기 늘었습니다. 평소 200밀리초이던 p99가 3초로 치솟았습니다. 두 엔지니어가 같은 증상을 마주합니다.
증상: p99 지연 200ms -> 3s 급등, 에러율은 정상
[ 답 수집형의 경로 ]
1. "API latency spike" 검색
2. 일반론(캐시 추가, 인덱스 추가) 적용 시도
3. 효과 없음 -> 또 검색
4. 무작위 변경 반복, 운에 맡김
[ 이해 기반의 경로 ]
1. 정신 모델: 요청 -> 커넥션풀 -> DB -> 외부 API
2. 에러율 정상 + 지연만 증가 -> 자원 고갈 가설
3. 커넥션풀 사용률 확인 -> 100% 포화 발견
4. 원인: 외부 API 느려짐 -> 커넥션 점유 -> 풀 고갈
5. 대응: 타임아웃 단축 + 풀 격리 (벌크헤드)
두 경로의 차이는 지식의 양이 아니라 정신 모델의 유무입니다. 이해 기반 엔지니어는 "에러율은 정상인데 지연만 늘었다"는 단서 하나에서 자원 고갈을 의심합니다. 이것은 커넥션풀이라는 추상화의 한 층 아래(풀이 고갈되면 어떻게 되는가)를 이해하기에 가능한 추론입니다. 답만 모으는 사람에게 이 단서는 그냥 또 하나의 검색어일 뿐입니다.
흥미로운 점은, 이해 기반 엔지니어도 LLM을 씁니다. "커넥션풀 벌크헤드 패턴 예시를 보여줘"처럼요. 차이는 LLM을 가설 검증과 구현 가속에 쓰느냐, 가설 자체를 대신하게 하느냐입니다. 정신 모델이 있는 사람에게 LLM은 증폭기이고, 없는 사람에게 LLM은 목발입니다.
통제와 소유권 — 이해가 주는 것
이해는 권력이다
깊은 이해가 주는 가장 큰 선물은 통제(control)와 소유권(ownership)입니다. 이해하지 못한 코드 위에서 우리는 늘 불안합니다. 무언가를 바꾸려 할 때마다 "이게 어디에 영향을 줄지 모르겠다"는 공포가 따라옵니다. 그래서 손대지 못하고, 회피하고, 우회합니다. 코드가 우리를 지배합니다.
반대로 이해한 코드 위에서 우리는 자유롭습니다. 변경의 파급을 예측할 수 있고, 자신 있게 리팩터링하고, 대담하게 최적화합니다. 코드를 우리가 지배합니다. 이 차이는 단순한 생산성의 차이가 아니라, 일에서 느끼는 주체성과 즐거움의 차이입니다.
도구에 끌려가지 않기
LLM 시대에 이 통제의 문제는 더 첨예해집니다. 도구가 강력할수록, 우리는 도구에 끌려갈 위험도 커집니다. LLM이 제안한 코드를 그대로 받아들이는 일이 반복되면, 어느 순간 우리는 자기 코드베이스의 운전대를 도구에 넘겨준 상태가 됩니다.
도구에 끌려가지 않는다는 것은 LLM을 안 쓴다는 뜻이 아닙니다. LLM이 준 것을 이해하고, 비판하고, 필요하면 거부할 능력을 유지한다는 뜻입니다. 제안을 받되, 그것이 왜 맞는지(혹은 틀린지)를 판단할 수 있어야 합니다. 그 판단력은 결국 깊은 이해에서 나옵니다. 이해가 없으면 우리는 도구의 제안을 평가할 기준이 없고, 평가할 수 없으면 그저 따를 수밖에 없습니다.
도구에 끌려가는 관계 도구를 부리는 관계
------------------- -------------------------
제안 -> 무비판 수용 제안 -> 이해 -> 비판 -> 채택/거부
이해 없이 통합 이해 위에 통합
문제 시 무력 문제 시 직접 고침
운전대를 넘김 운전대를 쥠
학습으로서의 이해 — 우회로의 가치
빠른 길이 항상 좋은 길은 아니다
이해의 또 다른 측면은 학습입니다. 무언가를 깊이 이해하려고 씨름하는 과정 자체가 우리를 성장시킵니다. 답을 받아 적기만 하면 이 성장의 기회를 놓칩니다.
여기에 미묘한 역설이 있습니다. LLM은 "빠른 길"을 줍니다. 그런데 학습에서는 빠른 길이 항상 좋은 길은 아닙니다. 인지과학에는 "바람직한 어려움(desirable difficulties)"이라는 개념이 있습니다. 적당한 어려움을 겪으며 스스로 답에 도달하는 과정이, 답을 즉시 받는 것보다 더 깊고 오래 가는 학습을 만든다는 것입니다.
직접 막혀 보고, 가설을 세워 보고, 틀려 보고, 마침내 "아하" 하는 순간을 겪는 것. 이 우회로가 바로 이해를 만듭니다. LLM이 이 우회로를 없애 주는 것은 때로 축복이지만, 학습의 맥락에서는 저주가 될 수 있습니다.
의도적으로 이해를 선택하기
그래서 LLM 시대의 학습은 의도적인 선택을 요구합니다. 모든 것을 LLM에 묻지 않고, 어떤 것은 일부러 스스로 씨름하기로 선택하는 것입니다.
실무적인 구분을 제안합니다.
LLM에 맡겨도 되는 것 스스로 이해해야 하는 것
------------------- -------------------------
- 익숙한 보일러플레이트 - 핵심 도메인 로직
- 일회성 스크립트 - 자주 디버깅할 영역
- 잘 아는 영역의 반복 - 처음 배우는 기술의 기초
- 문법/API 기억의 보조 - 시스템의 정신 모델
이미 이해한 영역에서는 LLM이 손가락의 연장이 됩니다. 빠르게 가도 좋습니다. 하지만 처음 배우는 것, 앞으로 깊이 다룰 핵심 영역에서는 일부러 우회로를 택해 스스로 이해를 쌓는 것이 장기적으로 이깁니다.
팀 차원의 이해 — 개인을 넘어서
이해는 개인의 것만이 아니다
지금까지 이해를 개인의 능력으로 다뤘지만, 팀에서는 이해가 공유 자산이 됩니다. 한 사람만 핵심 시스템을 이해하면, 그 사람이 휴가를 가거나 퇴사하는 순간 팀 전체가 멈춥니다. 이것을 흔히 버스 팩터(bus factor)라고 부릅니다. 버스 팩터가 1이라는 것은 한 사람이 사라지면 시스템이 미궁이 된다는 뜻입니다.
버스 팩터 1 (위험) 버스 팩터 3+ (건강)
------------------- -------------------------
핵심 이해가 한 명에 집중 이해가 여러 명에 분산
그 사람 부재 시 마비 누가 빠져도 대응 가능
지식이 머릿속에만 있음 문서/페어링으로 외부화
LLM도 그 맥락을 모름 공유된 정신 모델 존재
LLM 시대에 이 문제는 미묘하게 악화될 수 있습니다. 각자 LLM과 일대일로 일하면, 코드는 생기지만 팀의 공유 이해는 자라지 않을 수 있습니다. 예전에는 막혔을 때 옆 사람에게 물으며 자연스럽게 지식이 퍼졌는데, 이제는 LLM에 물으면 그 대화가 개인 안에 갇힙니다.
이해를 외부화하는 습관
그래서 팀 차원에서는 이해를 의도적으로 외부화하는 습관이 중요해집니다.
[ ] 핵심 시스템에 대한 "왜 이렇게 만들었나"를 문서로 남기는가? (ADR 등)
[ ] 페어링/코드리뷰에서 코드뿐 아니라 정신 모델을 공유하는가?
[ ] LLM과의 유용한 대화를 팀이 볼 수 있게 정리해 두는가?
[ ] 한 사람만 아는 영역(버스 팩터 1)을 식별하고 분산하는가?
특히 "왜 이렇게 만들었나"를 기록하는 것이 중요합니다. 코드는 "무엇을" 하는지 보여주지만, "왜" 그렇게 했는지는 보여주지 않습니다. 그 "왜"가 바로 정신 모델의 핵심이고, 그것이 사라지면 후임자는 코드는 읽어도 이해는 잃습니다. 좋은 설계 결정 기록(ADR)은 미래의 팀에게 이해를 물려주는 가장 확실한 방법입니다.
균형 — 언제 추상화에 기대도 되나
모든 것을 이해할 수는 없다
여기서 균형이 중요합니다. "깊이 이해하라"는 말을 "모든 것을 밑바닥까지 이해하라"로 받아들이면 마비됩니다. 현대 소프트웨어는 누구도 전체를 이해할 수 없을 만큼 거대합니다. 우리는 끊임없이 추상화에 기대야 하고, 그것은 잘못이 아니라 필수입니다.
문제는 "언제 이해를 멈추고 추상화를 믿어도 되는가"입니다. 몇 가지 실용적 기준을 제안합니다.
- 빈도: 자주 마주치고 자주 디버깅할 영역일수록 깊이 이해할 가치가 크다. 일 년에 한 번 건드리는 영역은 추상화에 기대도 좋다.
- 위험: 실패의 비용이 큰 영역(보안, 결제, 데이터 무결성)일수록 이해의 가치가 크다.
- 새어 나옴: 추상화가 새어 나오는 빈도가 높은 영역(성능, 동시성)일수록 한 층 아래를 알 가치가 크다.
- 핵심성: 내 일의 핵심 도메인일수록 이해해야 한다. 주변부는 신뢰할 만한 추상화에 맡겨도 된다.
깊이 이해할 가치
높음 +----------------------------------+
| 핵심 도메인 로직 | 보안/결제 |
| 자주 디버깅 영역 | 성능 병목 |
+----------------------------------+
| 잘 아는 반복 | 일회성 스크립트 |
낮음 | 안정적 라이브러리| 주변부 글루코드 |
+----------------------------------+
낮음 높음
추상화에 기대도 좋음
신뢰할 만한 추상화의 조건
추상화에 안심하고 기댈 수 있는 조건도 있습니다. 잘 만들어진 추상화는 새어 나오는 빈도가 낮고, 새어 나올 때 명확한 신호를 주며, 문서와 커뮤니티가 그 경계를 잘 설명합니다. 표준 라이브러리, 검증된 프로토콜, 성숙한 프레임워크가 이런 부류입니다. 이런 추상화 위에서는 매번 밑바닥을 파지 않아도 됩니다.
반대로 새로 만든 내부 추상화, 검증되지 않은 라이브러리, 자주 새어 나오는 성능 경계는 더 깊은 이해를 요구합니다. 균형의 핵심은 "어떤 추상화는 믿어도 되고 어떤 추상화는 의심해야 하는가"를 분별하는 안목이며, 그 안목 자체도 결국 경험과 이해에서 나옵니다.
LLM과 이해의 건강한 관계 — 증폭기로 쓰기
이해를 강조한다고 LLM을 멀리하라는 뜻은 아닙니다. 오히려 이해가 깊을수록 LLM을 더 강력하게 쓸 수 있습니다. 둘의 건강한 관계는 다음과 같이 그려집니다.
이해가 없을 때 이해가 있을 때
------------------- -------------------------
LLM 출력 = 최종 답 LLM 출력 = 초안/가설
검증 불가 -> 그냥 믿음 검증 가능 -> 비판/수정
프롬프트도 막연함 정확한 프롬프트 작성 가능
틀려도 모름 틀리면 즉시 알아챔
도구가 운전 내가 운전, 도구가 가속
핵심은 이해가 LLM의 입력과 출력 양쪽을 개선한다는 것입니다. 입력 쪽에서는, 이해가 깊어야 정확한 질문을 던질 수 있습니다. "이거 왜 안 돼요"보다 "커넥션풀이 고갈된 것 같은데 벌크헤드로 격리하는 패턴을 보여줘"가 훨씬 나은 답을 끌어냅니다. 출력 쪽에서는, 이해가 있어야 받은 답을 평가하고 교정할 수 있습니다. 즉 이해는 LLM을 대체하는 것이 아니라 LLM의 가치를 배가시키는 증폭기입니다.
이것이 "이해 vs LLM"이라는 구도가 잘못된 이유입니다. 진짜 구도는 "이해 + LLM" 대 "LLM만"입니다. 이해를 갖춘 사람이 LLM을 쓰면 가장 빠르고, 이해 없이 LLM만 쓰면 가장 위험합니다.
실무에 적용하기 — 이해를 쌓는 습관
이해는 거창한 결심이 아니라 작은 습관으로 쌓입니다. 하루에 30분씩 추상화의 밑바닥을 파라는 것이 아니라, 평소 흐름 속에 작은 마찰을 끼워 넣는 것입니다. 코드를 머지하기 직전, 에러를 검색하기 직전, 그 한순간에 "잠깐, 이게 왜 이렇지"를 묻는 습관 하나가 시간이 지나면 큰 차이를 만듭니다. 일상에서 실천할 수 있는 방법을 정리합니다.
[ 한 층 아래 보기 ]
[ ] 매일 쓰는 추상화 중 하나를 골라 그 한 층 아래를 이해했는가?
[ ] LLM이 준 코드의 "왜"를 최소 한 번은 스스로 설명해 봤는가?
[ 직접 씨름하기 ]
[ ] 핵심 영역에서는 LLM에 묻기 전에 먼저 가설을 세워 봤는가?
[ ] 막혔을 때 즉시 답을 받기보다 잠시 스스로 추론해 봤는가?
[ 정신 모델 만들기 ]
[ ] 내 시스템의 데이터 흐름을 종이에 그려 본 적이 있는가?
[ ] 장애 시 어디를 먼저 볼지에 대한 정신 모델이 있는가?
[ 가르치며 검증하기 ]
[ ] 이해한 것을 동료에게 설명할 수 있는가? (못 하면 아직 모르는 것)
[ ] LLM의 설명을 받되, 내 말로 다시 정리해 봤는가?
특히 마지막 항목, "가르치며 검증하기"를 강조하고 싶습니다. 무언가를 진짜 이해했는지 가장 확실하게 검증하는 방법은 남에게 설명해 보는 것입니다. LLM에게 설명을 시키는 것과, 내가 LLM이나 동료에게 설명하는 것은 정반대의 일입니다. 전자는 답을 받는 것이고 후자는 이해를 증명하는 것입니다.
이해를 방해하는 흔한 함정
좋은 습관만큼이나 나쁜 습관을 아는 것도 중요합니다. 이해를 갉아먹는 흔한 함정들을 정리합니다.
함정 대신 할 일
------------------------- -------------------------
작동하면 바로 다음으로 넘어감 왜 작동하는지 한 번 짚고 넘어감
에러를 통째로 LLM에 붙여넣음 먼저 에러를 스스로 읽고 가설을 세움
추상화를 절대 의심하지 않음 가끔 한 층 아래를 들여다봄
복사한 코드를 변형 없이 씀 내 맥락에 맞게 다시 써 봄
이해한 척하고 넘어감 설명해 보고 막히는 곳을 확인함
이 함정들의 공통점은 "지금 당장 편한 길"이라는 것입니다. 그래서 의지력만으로는 피하기 어렵습니다. 대신 작은 의례를 만드는 것이 효과적입니다. 예를 들어 "LLM이 준 코드는 머지 전에 한 문장으로 요약 주석을 단다" 같은 규칙은, 그 한 문장을 쓰는 과정에서 최소한의 이해를 강제합니다. 이해는 거창한 결심이 아니라 이런 작은 마찰을 의도적으로 설계하는 데서 자랍니다.
함정과 비판적 시각
이 글의 주장에도 반론이 있습니다. 균형을 위해 정리합니다.
- 이해 물신주의의 위험: "모든 것을 깊이 이해하라"는 태도가 과하면 생산성을 해칩니다. 마감이 있는 실무에서 모든 추상화를 밑바닥까지 파는 것은 사치일 수 있습니다. 이해는 목적이 아니라 더 나은 일을 위한 수단입니다.
- 추상화의 본질적 가치: 추상화는 우리가 거인의 어깨에 서게 해 줍니다. 매번 밑바닥부터 이해하려 들면 인류는 진보하지 못합니다. 적절한 무지(productive ignorance)는 협업과 분업의 토대입니다.
- 이해의 환상: 깊이 이해했다고 믿는 것이 실제 이해를 보장하지 않습니다. 정신 모델은 종종 틀리고, 틀린 정신 모델은 차라리 없는 것보다 위험할 수 있습니다. 이해는 겸손과 검증을 동반해야 합니다.
- 세대와 도구의 변화: 어셈블리를 모르는 고급 언어 개발자가 한때 비판받았지만 지금은 정상입니다. LLM 위에서 일하는 새 세대가 다른 종류의 이해(시스템 조합, 검증, 평가)를 발전시킬 수도 있습니다. "우리 때는 이해했는데"라는 향수는 경계해야 합니다.
- 이해와 속도의 트레이드오프 부정의 위험: 깊은 이해가 항상 옳다는 식의 주장은, 실제로 빠른 답이 충분히 좋은 수많은 상황을 무시합니다. 모든 코드가 새벽 3시 장애의 주인공이 되지는 않습니다.
- 이해의 유효기간: 깊이 이해해 둔 것도 기술이 바뀌면 낡습니다. 특정 프레임워크의 내부를 완벽히 이해했는데 그 프레임워크가 사라지면, 그 이해의 상당 부분은 무용해집니다. 그래서 어떤 이해는 휘발성이 있고, 더 근본적인 층(자료구조, 네트워크, OS)일수록 오래 가는 이해라는 점도 함께 고려해야 합니다.
- 개인차 무시의 위험: 이해가 학습에 좋다는 일반론이, 모든 사람·모든 맥락에 같은 강도로 적용되지는 않습니다. 어떤 사람은 빠른 답을 먼저 받고 거꾸로 이해하는 방식이 더 잘 맞습니다. "바람직한 어려움"도 너무 크면 좌절만 남깁니다. 이해의 방법은 한 가지가 아닙니다.
이 반론들은 타당하며, 글의 핵심 주장과 모순되지 않습니다. 요점은 "항상 깊이 파라"가 아니라 "어디를 깊이 파고 어디를 추상화에 맡길지 분별하라, 그리고 그 분별 자체가 이해에서 나온다"는 것입니다.
자주 나오는 질문
Q1. LLM이 다 해 주는데 왜 굳이 이해해야 하나요?
LLM이 "잘 풀리는 경우"에는 이해가 없어도 됩니다. 문제는 잘 안 풀리는 경우입니다. LLM이 틀린 답을 자신 있게 줄 때, 미묘한 버그를 심을 때, 처음 보는 장애가 터질 때. 그때 이해는 LLM 출력을 평가하고 교정하는 유일한 기준이 됩니다. 이해는 평소가 아니라 예외 상황을 위한 보험입니다.
Q2. 모든 것을 이해하려면 시간이 너무 많이 들지 않나요?
맞습니다. 그래서 "모든 것"이 아니라 "한 층 아래"와 "핵심 영역"만 깊이 파라는 것입니다. 빈도·위험·새어 나옴·핵심성 기준으로 선별하면, 이해에 드는 시간은 무한이 아니라 관리 가능한 투자가 됩니다.
Q3. 주니어 개발자에게도 같은 조언이 유효한가요?
특히 주니어에게 더 중요합니다. 경력 초반은 정신 모델의 토대를 쌓는 시기입니다. 이때 LLM에 모든 것을 의존하면 토대 없이 출력만 조립하는 습관이 굳습니다. 주니어일수록 일부러 우회로를 택해 스스로 씨름하는 비중을 높이는 것이 장기적으로 이깁니다.
Q4. 이해와 속도, 둘 다 잡을 수는 없나요?
장기적으로는 이해가 속도를 만듭니다. 단기에는 이해가 비용처럼 보이지만, 이해한 영역에서는 디버깅과 변경이 훨씬 빨라지므로 시간이 지날수록 이해가 속도로 전환됩니다. 둘은 단기에는 트레이드오프, 장기에는 같은 방향입니다.
Q5. "이해했다"는 것을 어떻게 확인하나요?
설명해 보는 것이 가장 확실합니다. 동료에게, 혹은 빈 화면에 글로 설명해 보십시오. 막히는 지점이 곧 아직 이해하지 못한 지점입니다. 이것이 흔히 말하는 "고무오리 디버깅"이 효과적인 이유이기도 합니다.
마치며 — 이해라는 기쁨을 지키기
LLM은 엔지니어링의 많은 부분을 바꿉니다. 답에 도달하는 비용은 극적으로 낮아졌습니다. 하지만 답과 이해는 여전히 다른 것이고, 이해가 주는 것 — 통제, 소유권, 위기 대응력, 그리고 일에서 느끼는 깊은 만족 — 은 LLM이 대신 주지 못합니다.
정리하면 다음과 같습니다.
- 답은 휘발성이 강하고 이해는 전이됩니다. LLM 시대의 위험은 답에 도달하는 비용이 0이 되면서 이해를 건너뛰려는 유혹이 커진다는 것입니다.
- 추상화는 새어 나옵니다. 매일 쓰는 추상화의 한 층 아래를 아는 것만으로도, 위기의 순간에 당황하지 않습니다.
- 정신 모델은 검색되지 않습니다. 장애 대응은 평소 이해의 잔고를 인출하는 일입니다.
- 이해는 통제와 소유권을 주고, 도구에 끌려가지 않게 합니다. LLM을 부리되 끌려가지 않으려면 판단력이, 그 판단력에는 이해가 필요합니다.
- 그러나 모든 것을 이해할 수는 없습니다. 빈도, 위험, 새어 나옴, 핵심성을 기준으로 어디를 깊이 팔지 분별하는 것이 진짜 지혜입니다.
이해의 기쁨은 효율의 반대편에 있는 사치가 아닙니다. 그것은 우리가 도구를 부리는 주체로 남을 수 있게 하는 근본 능력이자, 이 일을 사랑하는 이유 그 자체입니다. LLM이 더 강력해질수록, 역설적으로 그 기쁨을 의식적으로 지키는 일이 더 중요해집니다.
마지막으로 한 가지 실천을 제안하며 글을 맺겠습니다. 다음에 LLM이 코드를 줬을 때, 그것을 그대로 머지하기 전에 딱 한 가지만 자신에게 물어보십시오. "이 코드가 왜 작동하는지, 그리고 어떤 경우에 깨지는지 내가 설명할 수 있는가?" 이 질문에 "예"라고 답할 수 있다면 빠르게 가도 좋습니다. "아니오"라면, 그곳이 바로 잠시 멈춰 이해를 쌓아야 할 지점입니다.
이 작은 질문 하나가 답만 모으는 사람과 이해를 쌓는 사람을 가릅니다. 그리고 시간이 지나면, 그 질문을 던져 온 사람만이 새벽 3시의 장애 앞에서 침착할 수 있고, 도구의 제안을 비판할 수 있으며, 자기 코드의 진정한 주인으로 남을 수 있습니다. 이해는 느린 길처럼 보이지만, 결국 가장 멀리 가는 길입니다.
참고 자료
- GeekNews — 이해의 기쁨(the joy of understanding) 관련 논의
- Hacker News
- Joel on Software — The Law of Leaky Abstractions
- Peter Norvig — Teach Yourself Programming in Ten Years
- Bjarke Roune / Make It Stick — Desirable Difficulties (인지과학 학습 원리)
- Julia Evans (b0rk) — Debugging and mental models
- The Pragmatic Programmer (Hunt and Thomas)
- Dan Luu — Files are hard (추상화 너머의 복잡함 사례)