URL: https://www.youtube.com/watch?v=8xBJPa_480Q
날짜: 2026-08-31
채널: Pragmatic Engineer
Video ID: 8xBJPa_480Q
메타데이터
- 원문 제목: Why performant code matters (but gets widely ignored), with Casey Muratori
- 콘텐츠 유형: YouTube 심층 다이제스트
- 핵심 인물: Casey Muratori, Gergely Orosz
- 주제: 소프트웨어 성능, CPU·어셈블리, 아키텍처, 게임 엔진, AI 개발
- 원문 URL: https://www.youtube.com/watch?v=8xBJPa_480Q
- 발행일: 2026-08-31
1계층 — 핵심 질문과 한 문장 답
핵심 질문
왜 많은 개발자와 조직은 성능을 중요하게 말하면서도 실제 설계와 개발 과정에서는 성능을 뒤로 미루며, 성능 좋은 소프트웨어를 만들려면 무엇을 먼저 배워야 하는가?
핵심 답
성능 문제의 주된 원인은 마지막에 찾아 고칠 수 있는 작은 핫스팟(hotspot)이 아니라, 하드웨어의 가능성을 모른 채 선택한 아키텍처와 직렬 의존성(serial dependency chain)이다. 좋은 최적화는 프로파일러의 큰 막대부터 줄이는 일이 아니라 시스템이 이론적으로 낼 수 있는 성능과 현재 성능의 차이를 계산하고, 그 차이를 설명할 수 있는 구조를 만드는 일이다. 이를 위해 모든 개발자가 CPU의 기본 동작과 어셈블리 읽기를 익히고, 직접 측정 가능한 근거로 통념을 검증해야 한다.
핵심 근거
- 300ms를 넘지 않는 동작을 경쟁력으로 내세우는 제품이 등장할 만큼 많은 업무용 소프트웨어의 기준선이 이미 지나치게 느리다.
- Bun은 npm보다 10배·20배·50배 빠르다는 과감한 비교로 개발자의 관심을 끌었고, Linear는 Jira와 대비되는 300ms 수준의 반응성을 제품 차별점으로 삼았다.
- Python의 단순한
A + B는 C의 같은 연산보다 대략 100배 많은 CPU 명령을 거칠 수 있으므로, 숫자 규모를 모르면 언어와 라이브러리 선택의 비용을 판단하기 어렵다. - 순차적인 네트워크 요청을 수십만 줄의 코드에 퍼뜨리면 나중에 성능 전문가를 불러도 구조를 거의 줄일 수 없고, 병렬화 가능한 아키텍처로 다시 써야 한다.
- Uncle Bob의 특정 다형성 기반 리팩터링 패턴은 단순한 테이블·switch 구현보다 1.5배에서 15배 느릴 수 있으며, 핵심 비용은 가상 함수 호출 하나보다 컴파일러 최적화를 막는 구조다.
2계층 — 대주제 지도
- 성능을 측정하는 기준의 전환: 프로파일러 순위가 아니라 이론적 하드웨어 상한과 실제 결과의 차이를 기준으로 삼는다.
- 아키텍처와 최적화 가능성: 핫스팟은 우연히 생기지 않으며, 처음부터 나중에 최적화할 수 있는 데이터 흐름과 의존성 구조를 설계해야 한다.
- 기계 수준의 문해력: 어셈블리 읽기, 캐시·분기 예측·실행 유닛 이해가 언어와 프레임워크를 넘어선 엔지니어링 판단을 가능하게 한다.
- 좋은 코드와 좋은 엔지니어: 가독성·유지보수성·성능은 보통 함께 갈 수 있고, 검증되지 않은 프로그래밍 통념을 따르지 않는 태도가 중요하다.
- 게임 산업의 사례: 게임 엔진의 상품화는 제작의 기술 장벽을 낮췄지만 공급 과잉과 마케팅 의존을 낳았고, 플랫폼 전환의 결과를 보여주는 선행 사례가 되었다.
- AI와 인간의 자율성: AI 코딩 도구의 효과는 코드 생성량보다 누가 방향과 품질을 결정하는지, 그리고 개발자가 자율적으로 도구를 선택하는지에 달려 있다.
3계층 — 대주제별 심층 해설
3.1. 성능 무관심은 기술적 무지가 아니라 경제·조직 구조의 산물이다
3.1.1. 사용자가 구매자가 아니면 느림이 구매 조건이 되지 않는다
-
엔터프라이즈 소프트웨어의 구매 구조
- HR 관리 시스템 같은 제품은 실제 사용자가 구매 결정을 내리지 않는 경우가 많다. 고위 의사결정자는 가격, 컴플라이언스, 법적 책임, 계약 조건을 보고 선택하며, 직원이 사람 기록을 열 때 30초씩 기다리는지는 구매표의 핵심 칸이 되지 않는다.
- 사용자는 느린 소프트웨어에 불만을 품어도 구매권과 교체권이 없으므로 시장의 성능 압력이 약해진다.
-
독점과 네트워크 효과
- 소셜 네트워크처럼 사용자가 이미 모여 있는 시장에서는 더 빠른 제품만으로 기존 사업자를 밀어내기 어렵다. X, Threads, Bluesky, Facebook, Instagram, TikTok 같은 서비스는 네트워크 효과와 영향력 있는 사용자의 분포를 함께 확보해야 한다.
- 성능은 강력한 차별화 요소일 수 있지만, 채택 전략과 네트워크 효과를 대신하지는 못한다.
-
변화의 신호
- 최근에는 File Pilot, Blick 같은 제품이 기존 제품보다 빠르다는 점을 전면에 내걸고 traction을 얻고 있다. 개발자 도구에서도 Bun이 npm보다 10배·20배·50배 빠르다고 주장하면서 성능을 제품의 첫인상으로 만들었다.
- 성능을 말하는 사람이 지난 10년 동안 늘었고, 실제로 성능을 중심으로 시장에 진입하는 제품도 보이므로 분위기가 조금씩 바뀌고 있다.
3.1.2. 300ms와 1초는 컴퓨터 관점에서 이미 긴 시간이다
- 300ms는 사람의 반응을 기준으로 보면 짧아 보이지만, 현대 컴퓨팅에서 한 번의 연산 예산으로는 매우 길다. Linear가 어떤 동작도 300ms를 넘기지 않겠다고 내세운 사실 자체가 시장의 기준선이 얼마나 낮아졌는지를 보여준다.
- 네트워크 패킷이 데이터센터 사이를 10ms 이하로 이동하는데, 애플리케이션의 단순한 동작이 몇 초씩 걸리는 상황이 생긴다. 물리적 거리를 왕복한 패킷보다 로컬 소프트웨어가 느리다는 뜻이다.
- “10배나 100배 빠르다”는 주장이 과장처럼 들리는 이유는 개발자가 기준선과 하드웨어의 이론적 처리량을 머릿속에 갖고 있지 않기 때문이다. 실제로는 수십 배의 격차가 흔하다.
3.1.3. 벤치마크도 무엇을 측정하는지 모르면 틀릴 수 있다
- Turbopuffer의 Simon Ericson이 만든 Napkin Math는 AWS 데이터센터 간 1바이트·기가바이트·테라바이트 전송, SSD와 NVMe 쓰기 같은 연산에 걸리는 대략적인 시간을 비교하는 프로젝트다.
- Shopify에서 데이터베이스 벤더를 고를 때 팀이 직접 만든 벤치마크를 돌려 2초인 제품과 10초인 제품을 비교했지만, 이론적 파일 시스템 한계와 맞지 않는 결과였다. 실제로는 벤치마크가 측정 대상을 잘못 잡고 있었다.
- 성능 측정은 숫자를 수집하는 행위가 아니라, 숫자가 하드웨어와 시스템 모델에 맞는지 확인하는 추론 과정이다.
3.2. 진짜 최적화는 프로파일러의 큰 막대를 줄이는 일이 아니다
3.2.1. 이론적 상한에서 출발한다
-
통상적인 오해
- 흔히 프로파일을 실행하고, 가장 큰 부분을 찾고, 코드를 고치고, 통계가 개선됐는지 확인하는 순서를 최적화라고 생각한다.
- Casey Muratori는 이 방식이 작은 개선(improvement)을 찾는 절차일 수는 있어도 최적화(optimization)의 본질은 아니라고 설명한다.
-
상한과 격차
- 먼저 시스템이 수행해야 할 연산을 나열하고, 하드웨어가 이론적 최고점에서 처리할 수 있는 양을 계산한다.
- 현재 성능과 이론적 최대치 사이의 delta를 측정하고, 하드웨어 지식으로 설명할 수 없는 차이를 줄인다.
- 이론적 최대치는 실제로 항상 도달할 수 없으므로, 캐시·메모리·분기·동시성·입출력 같은 현실적 요인으로 남은 격차를 설명할 수 있어야 한다.
-
지역 최솟값과 전역적 최적화
- 프로파일러에서 눈에 띄는 부분만 조금씩 고치면 현재 상태 주변의 local minimum에 머물 수 있다.
- 최적화는 “지금보다 나아졌는가”가 아니라 “이 기계가 이 문제에서 합리적으로 낼 수 있는 성능에 얼마나 가까운가”를 묻는 작업이다.
3.2.2. 이론적 모델은 새로운 하드웨어 현상을 발견하게 한다
- 새로운 CPU나 GPU를 다룰 때 기존 지식만으로는 충분하지 않다. 데이터 경로, 네트워크 백플레인, 드라이버, 코어 구조가 이전 세대와 다를 수 있다.
- 실제 성능이 이론 모델에서 크게 벗어나면 이상 현상을 의심할 수 있다. Casey는 Intel 칩의 레지스터 이름 변경과 RAT(register alias table)처럼 기존에 몰랐던 내부 동작을 마이크로벤치마크로 발견한 경험을 들었다.
- “왜 이 숫자가 나오지?”라는 질문을 가능하게 하는 기준선이 있어야 새 하드웨어의 성질을 학습할 수 있다.
3.3. 어셈블리 읽기는 저수준 전문가가 되기 위한 의식이 아니라 컴파일러 결과를 확인하는 방법이다
3.3.1. 고수준 코드는 CPU가 받는 명령이 아니다
- C, Rust, Haskell, OCaml, JavaScript 같은 코드는 컴파일러나 런타임에 주는 입력이다. 소스만 봐서는 CPU가 실제로 어떤 일을 하게 될지 알 수 없다.
- 컴파일러가 내놓은 어셈블리를 보면 CPU가 실행하도록 요청받은 명령을 직접 확인할 수 있다. 최적화의 핵심은 어셈블리를 직접 작성하는 능력보다 컴파일러가 만든 결과를 읽고 예상과 비교하는 능력이다.
- 직접 어셈블리를 작성할 일은 드물고, 테스트 목적이나 컴파일러를 특정 출력으로 유도하기 어려운 경우에 제한적으로 쓰인다.
3.3.2. 필요한 명령어 집합은 생각보다 작다
-
학습 범위
- 웹 개발에 필요한 JavaScript 라이브러리, DOM, CSS, React의 개념 수와 비교하면 실제 성능 분석에 반복해서 등장하는 x64 어셈블리 명령은 약 20~30개 정도로 좁힐 수 있다.
- 컴파일러가 거의 내보내지 않는 레거시 명령까지 전부 익힐 필요는 없다.
-
활용 범위
- CPU 회사가 새 프로세서를 발표하며 공개하는 실행 유닛·파이프라인 도식도 어셈블리를 읽으면 어떤 연산이 어떤 경로로 흐르는지 해석할 수 있다.
- “HTML에서 div를 수직 중앙 정렬할 수 있다면 어셈블리도 배울 수 있다”는 비유처럼, 낯설 뿐 언어 자체가 방대한 것은 아니다.
3.3.3. CPU를 이해할 때 봐야 할 세 축
-
데이터 이동
- load/store 유닛, L1·L2·L3 캐시와 일부 CPU의 L0 캐시, 캐시의 단위와 정책을 이해한다.
- 데이터 배치와 접근 패턴만 바꿔도 성능이 크게 달라진다. 이는 핫스팟을 고치는 문제보다 훨씬 오래 남는 아키텍처 결정이다.
-
명령 흐름
- 분기 예측 실패(branch misprediction), 명령어 캐시(i-cache) 미스, 코드 흐름의 예측 가능성을 이해한다.
- 분기 예측기는 복잡해지고 있지만, 어떤 코드 흐름에서 비용이 생기는지 범주 수준으로 판단할 수 있다.
-
실행 유닛과 스케줄링
- 부동소수점 곱셈, 정수 덧셈, 나눗셈 같은 연산의 처리량과 지연시간을 본다.
- 어셈블리 명령이 마이크로옵(micro-operation)으로 분해되고 여러 실행 유닛으로 분배되는 흐름을 알면 CPU 도식에서 대략적인 처리량을 읽을 수 있다.
3.4. “성급한 최적화”는 작은 구현에만 미루고, 구조적 결정을 미루지 말라는 뜻으로 제한해야 한다
3.4.1. 나중에 고쳐도 되는 최적화
- 해시 테이블 구현처럼 주변 아키텍처가 이미 안정적이고, 느린 부분이 하나의 국소적인 루틴으로 분리되어 있다면 최적화 작업을 뒤로 미뤄도 된다.
- 버블 정렬처럼 명백히 순진한 구현을 나중에 더 나은 알고리즘으로 바꿀 수 있고, 그 변경이 데이터 흐름이나 외부 계약을 바꾸지 않는다면 먼저 제품을 확인하는 선택이 합리적이다.
- 이 판단에는 “나중에 같은 인터페이스 안에서 고칠 수 있다”는 확신과, 실제로 느릴 때만 작업하겠다는 측정 계획이 함께 있어야 한다.
3.4.2. 나중에 고칠 수 없는 최적화
- 수십만 줄의 코드가 모두 “서버에 요청 → 응답 대기 → 계산 → 다음 서버 요청”의 형태라면, 문제는 특정 함수가 아니라 전체 데이터 흐름에 퍼진 직렬 의존성이다.
- A가 끝나야 B를 시작하고 B가 끝나야 C를 시작하는 가장 긴 의존성 사슬은 멀티스레딩, 네트워크 요청 묶음, 지연 숨기기로 쉽게 짧아지지 않는다.
- 처음부터 각 작업에서 필요한 서버 요청을 모아 먼저 보내고, 반드시 필요한 경우에만 의존성 사슬을 만드는 규칙을 두었다면 대기 시간을 줄일 수 있다.
- 이런 구조는 프로파일러에 하나의 거대한 핫스팟으로 나타나지 않는다. 나중에 성능 전문가가 들어와서 함수 몇 개를 다시 쓰는 방식으로 복구할 수 없고, 때로는 전체 재작성보다 새로 만드는 편이 빠르다.
3.4.3. 최적화 가능한 코드베이스는 우연히 생기지 않는다
- 팀의 모든 아키텍처 결정자는 성능을 알아야 한다. 하위 단계의 개발자가 나중에 코드 최적화를 수행할 수 있도록 데이터 배치, 요청 경계, 실행 모델을 열어 두어야 한다.
- “핫스팟은 나중에 정리하면 된다”는 전략은 코드베이스가 애초에 핫스팟 형태로 최적화될 수 있다는 보장이 있을 때만 유효하다.
- Uber가 Python·Node.js에서 Java로 백엔드를 옮긴 사례, AI 기업들이 Python 웹 서버를 Rust나 Go로 옮기는 사례는 언어 자체보다 초기 확장 구조와 스레딩 모델이 문제였을 가능성을 보여준다. 공개 기술 블로그는 실제 판단의 모든 이유를 보여주지 않을 수 있으므로, 언어 교체를 성능의 단일 원인으로 해석하면 안 된다.
3.5. 성능 문해력은 한두 달의 집중 학습으로도 설계 판단을 바꾼다
3.5.1. 학습 경로
- CPU가 처리하는 기본 명령과 레지스터를 훑는다.
- 간단한 C·Rust·Python 코드를 각각 컴파일하거나 실행해 어셈블리와 타이밍을 비교한다.
- CPU의 캐시·분기 예측·실행 유닛 도식을 읽고, 이론적 처리량을 대략 계산한다.
- 몇 가지 마이크로벤치마크를 직접 작성해 예상과 실제의 차이를 확인한다.
- 한두 달 동안 작은 사례를 반복해 “이 작업은 100배의 비용을 감당할 수 있는가?”라는 질문을 습관으로 만든다.
3.5.2. Python과 C의 100배 차이가 주는 판단
- 단순한
A + B를 Python으로 실행하면 C의 같은 연산보다 대략 100배 많은 CPU 명령을 수행할 수 있다. Python 자체가 나쁘다는 뜻이 아니라 동적 객체·타입·런타임 관리가 추가 비용을 만든다는 뜻이다. - 많은 데이터에 같은 연산을 반복해야 한다면 Python 코드 한 줄의 편리함을 그대로 반복하는 대신, C로 작성된 라이브러리 호출이나 Cython 같은 컴파일 경계를 사용해야 한다.
- 핵심은 특정 언어를 숭배하는 일이 아니라, 100배의 비용을 지불해도 되는 위치인지 미리 아는 것이다. 드물게 실행되는 경로라면 괜찮지만, 대량 반복의 중심에 두면 구조가 무너진다.
3.5.3. 충분히 좋은 성능의 기준
- 대부분의 제품은 이론적 최대치에 붙기 위해 코드 가독성과 변경 가능성을 희생할 필요가 없다.
- 아키텍처와 데이터 흐름을 올바르게 선택하면 보통 이론적 성능에서 2배 안팎까지 접근할 수 있으며, 이는 100배 느린 소프트웨어보다 이미 약 50배 나은 위치다.
- 이 정도의 개선은 특정 CPU에 맞춘 손수 작성한 어셈블리보다 설계 감각과 기준선 이해에서 나온다.
3.6. 게임 산업은 기술 장벽 완화의 이득과 공급 과잉을 동시에 보여준다
3.6.1. Casey의 경력과 Windows 게임의 출발점
- Casey는 Digital Equipment Corporation에서 PDP-11과 VAX를 다루던 아버지의 영향으로 약 7세였던 1982년 무렵 프로그래밍을 배웠다.
- Microsoft 인턴 시절 Chris Hecker가 비공식적으로 추진한 Wing 프로젝트를 접했다. 당시 Windows는 게임에 필요한 빠른 픽셀 쓰기와 더블 버퍼링을 제공하기 어려웠고, Wing은 Windows에서 빠른 블리팅(blit)을 가능하게 하는 스컹크웍스 프로젝트였다.
- Wing은 훗날 DirectX로 이어지는 계보의 출발점이 되었고, Casey는 이 경험을 통해 게임 개발자와 도구 제작자들을 만났다.
- 이후 Gas Powered Games, Rad Game Tools에서 캐릭터 애니메이션 시스템을 만들었고, 독립 회사 Molly Rocket에서 교육 콘텐츠와 게임 관련 작업을 이어갔다. The Witness에서는 이동 시스템 같은 일부 프로그래밍 문제를 도왔다.
3.6.2. 엔진이 없던 시절의 두 가지 위험
-
엔진 위험
- 예전 게임 스튜디오는 렌더링 엔진, 레벨 편집기, 경로 탐색, 도구를 직접 만들어야 했다. Doom·Quake·Build 엔진처럼 재사용 가능한 사례가 생기기 전까지 스튜디오의 기술 자산은 회사의 핵심 경쟁력이었다.
- ID Software와 Bullfrog처럼 엔진 기술력 자체로 살아남은 회사도 있었고, 소비자가 곧 사용할 하드웨어보다 훨씬 빠른 개발 장비를 쉽게 살 수 없었으므로 기술적 위험은 컸다.
-
게임성 위험
- 엔진과 편집 도구가 완성되기 전에는 최종 게임을 제대로 플레이해 볼 수 없었다. 어떤 게임이 재미있는지 검증하기도 어려웠다.
- 이 문제를 줄이기 위해 스튜디오 전체가 가능한 한 빠르고 투박하게 하나의 vertical slice를 만들고, 실제로 재미있는지 확인한 뒤 나머지 자산과 일정을 확장하는 방식이 자리 잡았다.
3.6.3. 라이선스 엔진의 양면성
- Unreal Engine, Unity, Godot 같은 엔진은 기술팀을 꾸릴 수 없던 사람도 게임을 만들 수 있게 했다. 예술적 표현의 문을 넓히고 더 많은 좋은 게임이 나왔다는 점은 분명한 순효과다.
- 그러나 진입 장벽이 낮아지면서 Steam에는 매년 수만 개에서 10만 개에 가까운 게임이 쏟아졌고, 좋은 게임이라는 사실만으로는 자연스럽게 발견되기 어려워졌다.
- 제품 품질은 기본 조건이 되고, 마케팅·유통·발견 가능성을 설계하는 일이 판매의 필수 조건이 되었다. 아주 작은 게임이 우연히 발견되는 일은 여전히 있지만, 그 확률을 사업 전략으로 삼을 수는 없다.
- 오래된 게임도 시청각적으로 충분히 좋아 보이고 Fortnite·Minecraft·League of Legends·Dota 같은 라이브 서비스가 사용자의 시간을 붙잡기 때문에, 새 게임은 다른 신작뿐 아니라 과거의 모든 좋은 게임과 제한된 여가 시간을 놓고 경쟁한다.
3.6.4. GTA 6의 개발 기간은 단순한 게임 제작 기간이 아니다
- Grand Theft Auto 5의 온라인 부문은 수십억 달러 규모의 수익을 만든 대표적인 라이브 서비스였고, GTA 6은 단순한 후속 타이틀이 아니라 그 수익원을 교체하는 사업적 사건이다.
- 새 게임이 기존 게임을 잠식하면서도 더 적은 수익을 내면 안 되므로, 싱글플레이어 품질뿐 아니라 온라인 운영과 라이브 서비스 구조를 함께 준비해야 한다.
- Rockstar와 Take-Two 입장에서 GTA 6은 검색 서비스의 재출시에 가까운 규모이며, 오랜 개발 기간은 기술적 지연만으로 설명되지 않는다.
3.7. 깨끗한 코드, 테스트, AI는 모두 “무엇을 위해 만드는가”라는 질문으로 돌아온다
3.7.1. Clean Code 논쟁의 핵심은 가상 호출 비용이 아니라 최적화 여지다
- Casey가 비판한 특정 Clean Code 규칙은 다형성을 항상 선호하고, 런타임 타입을 알지 못하게 하며, 작은 함수로 잘게 나누는 패턴을 무조건 권장한다.
- 작은 함수 자체는 문제가 아니다. 함수가 정적으로 알려져 있고 컴파일러가 인라이닝할 수 있다면, 여러 조각을 합치고 중복을 제거하며 SIMD 벡터화까지 수행할 수 있다.
- 하지만 C++의 가상 함수가 많아 컴파일러가 런타임에 어떤 클래스가 들어올지 알 수 없으면, 컴파일러가 전체 경로를 접고 넓히는 최적화를 수행할 수 없다.
- 비용은 가상 함수 호출 명령 하나가 느려서만 생기는 것이 아니다. 분기 예측, 스택 사용, 코드 경로 확장, 컴파일러가 포기한 최적화가 합쳐진 결과이며, 특정 사례에서 단순한 table·switch 구현보다 1.5배에서 15배 느려질 수 있다.
- 유지보수 가능한 코드와 빠른 코드는 대체로 대립하지 않는다. 가독성·이름·중복 제거를 유지하면서 컴파일러가 다시 조립할 문을 닫지 않는 설계가 가능하다.
3.7.2. 좋은 코드는 기계의 요구와 사람의 이해 사이의 교차점이다
- 좋은 코드는 컴퓨터가 문제를 풀기 위해 실제로 해야 할 일을 가능한 한 직접적으로 표현한다.
- 유클리드 거리 같은 계산은 곳곳에 흩어놓지 않고 이름 붙은 함수로 모은다. 컴파일러가 그 조각들을 효율적인 실행 코드로 재조립할 수 있도록 경계를 설계한다.
- 27개의 팩토리, 8,000개의 마이크로서비스 같은 과도한 추상화가 좋은 아키텍처라는 이름으로 추가되면 읽기·변경·실행 속도가 동시에 나빠질 수 있다.
- 이론적 최대치를 마지막 1%까지 짜내는 특수한 상황에서는 코드가 어려워질 수 있지만, 대부분의 제품은 그 지점과 거리가 멀다. 흔한 목표는 최적화 가능성을 보존한 채 충분히 빠르고 읽기 쉬운 코드다.
3.7.3. 테스트 주도 개발보다 테스트 전략이 중요하다
- 테스트는 운영에서 발견하기 어렵거나 비용이 큰 버그를 줄여 총 개발 시간을 절약한다면 가치가 있다. Casey는 Rad Game Tools에서 핵심 루틴의 회귀 테스트를 운영한 경험을 들었다.
- 반대로 테스트가 개발을 자동으로 이끌어야 한다는 원칙에는 동의하지 않는다. 테스트 작성·유지 비용, 코드 변경 시 테스트 수정 비용, 테스트 때문에 필요한 변화를 포기하는 비용을 모두 계산해야 한다.
- 어떤 프로젝트는 광범위한 테스트가 맞고, 어떤 프로젝트는 적은 테스트가 맞다. 좋은 엔지니어링은 테스트 개수의 보편적 목표가 아니라 프로젝트별 비용과 위험을 근거로 전략을 선택하는 일이다.
3.7.4. 좋은 소프트웨어 엔지니어는 한 종류가 아니다
- 범용 해결사: 낯선 코드베이스의 지형을 빠르게 파악하고, 이상한 코드가 있어도 필요한 패치를 만들어 실제 문제를 해결한다.
- 깊은 전문 연구자: 한 문제를 8개월 동안 파고들어 기존에 없던 알고리즘이나 돌파구를 만든다.
- 공통 특성: 역할은 달라도 작동 원리를 깊이 파고드는 호기심, 기계 수준의 이해, 실제로 검증된 방법을 선호하는 태도는 겹친다.
- 통념에 대한 회의: “Google 발표자가 항상 memset을 호출하라고 했다”, “if 문을 절대 쓰지 말라” 같은 말을 근거 없이 받아들이지 않고, 코드량·성능·변경 가능성에 실제 이득이 있는지 반복 가능한 실험으로 확인한다.
3.7.5. AI 코딩 도구의 효과는 아직 평가하기 이르다
- Casey는 Molly Rocket의 미공개 프로젝트와 교육 작업에서 AI 코딩 도구를 사용하지 않는다. 생산성·저작권·윤리 평가를 끝낸 뒤 거부한 것이 아니라, 직접 프로그래밍하는 일이 그 프로젝트의 목적이기 때문에 도구 선택의 대상이 아니었다.
- 가구 자동화가 IKEA를 만들었다고 해서 수제 목공이 사라지지 않는 것처럼, 자동화가 전통적 손작업의 가치를 완전히 없애지는 않는다. Casey는 자신이 대량 생산 공장을 관리하는 사람보다 직접 만드는 장인 쪽에 가깝다고 설명한다.
- 현재 AI 코딩 도구는 인간이 설정하고, 사용 방식과 검증 루프를 설계하고, 결과를 받아들일지 판단해야 하는 도구다. 도구를 켜면 Fortnite를 5,000명이 아니라 5명이 자동으로 출시하는 정도의 외부적으로 명백한 변화는 아직 관찰되지 않는다.
- 사용법이 정착되고 모델이 더 좋아지는 데 적어도 6개월에서 1년이 더 필요할 수 있다. 반대로 전사적으로 10% 생산성이 올랐다면 큰 성과라도 외부에서 알아보기 어렵다.
3.7.6. 자율성은 AI 경험의 방향을 바꾼다
- 업무 선택과 방법에 자율성이 높은 사람은 하기 싫었던 반복 작업을 AI에게 맡기므로 AI를 긍정적으로 경험하기 쉽다.
- 관리자가 AI 사용량과 산출량을 강제하면, 개발자는 자신이 잘하던 일을 빼앗기고 AI가 자신의 직업을 대체하기 위한 훈련 데이터가 된다고 느낄 수 있다.
- “내가 AI를 사용해 일을 하는가, AI가 나를 사용해 일을 하는가”라는 질문은 도구 도입의 심리적·조직적 효과를 압축한다. AI를 평가할 때 기능뿐 아니라 업무 자율성, 의사결정권, 실험 공간을 함께 봐야 한다.
3.7.7. 책보다 논문과 참고문헌의 연쇄가 지식의 밀도를 높인다
- 특정 책 한 권을 추천하기보다 Google Scholar에서 자신의 작업 영역과 관련된 논문을 찾고, 좋은 논문의 참고문헌을 따라가며 역사와 기법을 연쇄적으로 읽는 방법이 권장된다.
- 논문을 읽으면 현재 널리 쓰는 방법이 어떻게 발견됐는지, 자신이 몰랐던 기술이 무엇인지, 어떤 가정이 실제로 검증되었는지를 확인할 수 있다.
- AI는 관심 분야에 맞는 논문을 찾고 기술 기록을 훑는 보조 도구가 될 수 있지만, 무엇을 공부할지 선택하고 내용을 판단하는 책임은 독자에게 남는다.
4계층 — 실행 프레임, 결론 및 시사점
4.1. 성능 문제를 다루는 7단계
- 작업을 원자적 연산으로 분해한다: 데이터 이동, 계산, 분기, 네트워크, 저장을 한 덩어리로 보지 않는다.
- 하드웨어 상한을 계산한다: 캐시·메모리·코어·네트워크가 낼 수 있는 대략적인 최고치를 먼저 적는다.
- 현실의 격차를 설명한다: 현재 측정값이 상한과 다른 이유를 캐시 미스, 분기, 대기, 직렬성, 런타임 비용으로 분해한다.
- 구조적 병목을 먼저 찾는다: 단일 함수의 핫스팟인지, 병렬화할 수 없는 데이터 흐름인지 구분한다.
- 컴파일 결과를 확인한다: 소스 코드의 의도와 실제 어셈블리·실행 경로가 일치하는지 본다.
- 통념을 재현 가능한 실험으로 검증한다: 특정 패턴이 더 읽기 쉽고 빠르다는 주장을 실제 코드와 측정으로 확인한다.
- 충분한 목표에서 멈춘다: 이론적 최고치의 마지막 1%가 제품 가치보다 큰 복잡성을 요구하면, 유지보수 가능한 성능 수준을 선택한다.
4.2. 팀 설계에 적용하는 질문
- 이 요청 흐름은 나중에 병렬화할 수 있는가, 아니면 긴 직렬 의존성으로 굳어지는가?
- 데이터가 어떤 순서와 단위로 메모리에 놓이며, 캐시 지역성(locality)을 얻는가?
- 프레임워크·라이브러리·언어가 추가하는 10배·100배 비용을 어느 경로에서 지불해도 되는가?
- 추상화가 컴파일러의 인라이닝·벡터화·분기 최적화를 막고 있지는 않은가?
- 벤치마크가 실제 사용자 작업을 측정하는가, 아니면 잘못된 대상을 빠르게 재고 있는가?
- 지금 미뤄도 되는 국소 루틴과 지금 결정하지 않으면 다시 써야 하는 아키텍처를 구분했는가?
- AI 도입이 개발자의 자율성·판단권을 키우는가, 아니면 사용량과 산출량을 감시하는 수단이 되는가?
4.3. 결론
성능 좋은 소프트웨어를 만드는 핵심은 특정 언어를 선택하거나 모든 코드를 어셈블리로 다시 쓰는 데 있지 않다. 하드웨어가 할 수 있는 일의 규모를 알고, 데이터와 요청의 의존성을 설계하며, 컴파일러와 런타임이 실제로 수행하는 작업을 확인하는 데 있다. 성급한 최적화라는 문구는 작은 구현을 뒤로 미루는 데 쓸 수 있지만, 잘못된 실행 모델·직렬 네트워크·과도한 추상화 같은 구조적 선택을 면죄해 주지 않는다.
성능과 유지보수성은 보통 같은 방향에 있다. 단순하고 이름이 분명하며 중복이 적고, 나중에 데이터 배치와 실행 경로를 개선할 문이 열려 있는 코드가 사람에게도 읽기 쉽고 기계에도 빠르다. 게임 엔진의 상품화가 기술 장벽을 낮춘 뒤 시장을 공급 과잉으로 몰고 간 사례처럼, AI 코딩 도구도 구현량만 늘리면 발견·품질·방향성이라는 새로운 병목을 만든다. 인간의 역할은 사라지는 것이 아니라 무엇을 만들 가치가 있는지 결정하고, 결과를 검증하며, 직접 만들고 싶은 영역을 선택하는 쪽으로 이동한다.
4.4. 핵심 시사점
- 개발자 교육: 모든 개발자가 CPU의 기본, 어셈블리 읽기, 간단한 타이밍 측정, 캐시와 분기 예측의 개념을 익히면 아키텍처 오류를 초기에 줄일 수 있다.
- 리더십: 성능을 마지막 QA 항목으로 두지 말고, 설계 리뷰에서 이론적 상한·직렬성·데이터 배치·측정 방법을 질문해야 한다.
- 제품 전략: 성능은 기능 목록이 아니라 제품 포지셔닝이 될 수 있지만, 빠르다는 주장에는 사용자 작업과 재현 가능한 기준선이 따라야 한다.
- 조직 설계: AI 도입의 성과를 측정할 때 생성 코드 줄 수보다 자율성, 판단 품질, 검증 속도, 실제 사용자 가치가 늘었는지 봐야 한다.
- 개인 학습: 한두 달 동안 작은 CPU 실험을 반복하고, 업무 영역의 논문과 참고문헌을 읽으며, “왜 이 코드가 이만큼 느린가”를 설명하는 습관을 만든다.
주요 발언
“최적화는 이론적 최대치와 우리가 얻은 결과 사이의 격차를 줄이는 일입니다.”
“프로파일에서 큰 부분을 찾아 고치는 것만으로는 local minimum을 찾는 데 그칠 수 있습니다.”
“어셈블리를 쓸 필요는 거의 없지만, 읽는 능력은 반드시 필요합니다.”
“수직으로 div를 중앙 정렬할 수 있다면 어셈블리도 배울 수 있습니다.”
“코드베이스는 우연히 최적화 가능한 핫스팟 구조가 되지 않습니다. 처음부터 그렇게 설계해야 합니다.”
“성급한 최적화를 미룰 수 있는 것은 나중에 같은 구조 안에서 고칠 수 있을 때뿐입니다.”
“좋은 코드는 기계가 해야 하는 일을 가능한 한 직접적으로 표현하면서도 사람이 이해할 수 있게 나눈 코드입니다.”
“테스트가 개발을 이끌어야 하는 것은 아닙니다. 테스트 전략은 프로젝트의 비용과 위험을 보고 결정해야 합니다.”
“사람마다 좋은 소프트웨어 엔지니어의 모습은 다르지만, 실제로 작동하는 것을 확인하려는 태도는 공통적입니다.”
“왜 인간이 직접 프로그래밍하는지 묻는다면, 인간이 직접 만들고 싶어 하기 때문이라고 답하겠습니다.”
“AI를 사용해 일을 하는지, AI가 나를 사용해 일을 하는지 물어야 합니다.”
데이터와 수치
- 10배·20배·50배: Bun이 npm과 비교해 내세운 성능 향상 주장으로, 과감한 숫자가 개발자의 주의를 끌었다.
- 300ms: Linear가 동작 반응성을 설명할 때 사용한 기준이며, 현대 컴퓨팅의 단일 작업 예산으로는 긴 편이다.
- 10ms 이하: 데이터센터 사이 네트워크 패킷이 이동하는 사례로 언급된 지연시간이다.
- 2초 대 10초: Shopify 내부에서 데이터베이스 선택 벤치마크가 내놓았던 수치지만, 잘못된 대상을 측정한 결과였다.
- 약 100배: Python의 단순한
A + B가 C의 같은 연산보다 더 많은 CPU 명령을 필요로 할 수 있는 규모다. - 약 2배: 아키텍처를 올바르게 선택한 일반적인 코드가 이론적 최대치에서 남길 수 있는 대략적인 거리다.
- 약 50배: 100배 느린 코드와 2배 이내의 코드 사이에서 생기는 상대적 개선 폭이다.
- 약 20~30개: 실무에서 성능 분석을 위해 우선 익힐 만한 x64 어셈블리 명령의 좁은 부분집합이다.
- 1.5배~15배: 특정 다형성 기반 Clean Code 패턴이 table·switch 구현보다 느려진 측정 범위다.
- 3년: Casey가 성능에 관한 문제의식을 공유하기 시작한 뒤 대화가 이어진 대략적인 기간이다.
- 수십 년·수만 명: Microsoft가 막대한 프로그래밍 자원과 시간을 보유해도 코드량만으로 매력적인 제품을 보장할 수 없다는 대비에 사용된 규모다.
- 수만 개~10만 개: 엔진 장벽이 낮아진 뒤 매년 시장에 쏟아지는 Steam 게임의 규모로 언급된 범위다.
- 수십억 달러: Grand Theft Auto 5 온라인이 만들어 낸 사업적 규모를 설명하는 수치다.
- 5~6개월: AI 코딩 도구가 현재처럼 널리 usable하다고 판단하기까지의 짧은 기간으로 대화에서 언급된 범위다.
- 6개월~1년: AI 코딩 도구가 신뢰할 수 있는 개발 프로세스로 정착할 때까지 더 관찰해야 할 수 있는 기간이다.
핵심 요약 (20줄)
성능 기준선을 모르면 수십 배 느린 소프트웨어도 정상처럼 보이므로 하드웨어의 이론적 처리량부터 알아야 한다.
최적화는 프로파일의 큰 막대를 조금 줄이는 일이 아니라 이론적 최대치와 실제 성능의 설명되지 않은 격차를 줄이는 일이다.
벤치마크는 숫자를 뽑는 데서 끝나지 않고 측정 대상이 하드웨어 모델과 맞는지 검증해야 의미 있는 근거가 된다.
어셈블리 읽기는 직접 명령을 작성하는 기술보다 컴파일러가 CPU에 실제로 요청한 작업을 확인하는 능력에 가깝다.
20~30개 명령만 익혀도 반복적으로 등장하는 x64 실행 경로와 CPU 도식을 해석할 수 있어 학습 장벽이 낮다.
캐시와 분기 예측과 실행 유닛을 이해하면 데이터 배치와 코드 흐름이 만드는 성능 차이를 설계 단계에서 판단할 수 있다.
성급한 최적화는 국소적인 해시 루틴처럼 나중에 같은 구조 안에서 고칠 수 있는 작업에만 제한적으로 적용해야 한다.
직렬 의존성은 네트워크 요청과 계산을 순서대로 묶어 전체 아키텍처를 재작성하게 만들므로 초기 설계에서 먼저 제거해야 한다.
Python과 C의 차이는 단순한 덧셈에서도 약 100배의 명령 규모로 나타날 수 있어 반복 계산의 경계를 신중히 정해야 한다.
좋은 코드는 기계가 해야 할 일을 직접 표현하면서 사람이 이해할 이름과 조각으로 나누고 컴파일러의 최적화 여지를 남긴다.
Clean Code의 성능 문제는 가상 호출 하나보다 런타임 타입 불확실성이 컴파일러의 인라이닝과 벡터화를 막는 데서 커진다.
테스트 전략은 테스트 개수의 보편 법칙이 아니라 작성·유지 비용과 운영 버그 비용을 비교해 프로젝트별로 결정해야 한다.
좋은 엔지니어는 역할이 달라도 작동 원리를 깊이 파고들고 검증되지 않은 프로그래밍 통념을 실험으로 의심한다.
게임 엔진의 상품화는 제작 기술의 장벽을 낮췄지만 Steam의 공급 과잉을 낳아 품질만으로 발견되기 어려운 시장을 만들었다.
GTA 6의 긴 개발 기간은 새 게임 제작뿐 아니라 수십억 달러 규모의 GTA 5 라이브 서비스를 교체하는 사업적 위험을 반영한다.
AI 코딩 도구는 아직 인간이 설정하고 검증하는 도구이며, 전사적인 생산성 효과와 최선의 사용법을 판단하기에는 시간이 짧다.
업무 자율성이 높으면 AI가 하기 싫은 일을 덜어주는 도구가 되지만 강제 사용 환경에서는 직업 위협과 동기 저하를 키울 수 있다.
10% 생산성 향상은 조직 전체에 일어나도 외부에서 쉽게 관찰되지 않으므로 코드 생성량만으로 AI 성과를 단정할 수 없다.
논문 읽기와 참고문헌 추적은 새로운 기법과 발견의 역사를 익히고 자신의 기술 선택을 검증하는 고밀도 학습 방법이다.
성능과 장인정신은 특정 언어 숭배가 아니라 하드웨어를 이해하고 직접 만들 가치가 있는 것을 선택하는 태도에서 함께 강화된다.
