Tech Digest는 개발, 기술, 제품, 오픈소스, 스타트업에 관한 아티클을 읽고 개인적으로 이해한 내용을 기록합니다. 이 활동을 통해 더 많은 사람들이 도움을 받을 수 있었으면 해서 블로그도 공유를 시작합니다.
읽은 글
AI가 코드를 쓰는 시대, 인간이 코드를 쓰는 것도 가치가 있다.
- 현재 엔지니어의 역할은 코드를 직접 쓰는 것이 아니라, AI 에이전트가 잘 작동할 수 있는 소프트웨어 팩토리(인프라)를 구축하는 것
- 잘 다듬어진 테스트와 프롬프트만 있으면 AI는 충분히 좋은 변경을 만들 수 있어서, 인간이 직접 코드를 쓰는 것이 무의미해 보일 수 있다. 하지만 필자는 여전히 직접 코드를 쓰는 것이 유용하다고 주장한다
- 가장 큰 이유는 영어를 거치지 않고 직접 실행 환경에서 생각할 수 있기 때문
- 영어는 계산/알고리즘을 정확하게 표현하기에 부적합하다
- 생성된 코드만 읽고 승인하는 방식으로는 소유감(ownership)이 약해지고, Slop(엉성한 코드)을 놓치기 쉽다
- 자신이 다루기 어려운 코드는 AI에게도 어렵다
- 인간이 직접 코드를 정리하고 일관된 원칙을 부여하면, 결과적으로 AI(소프트웨어 팩토리) 전체가 더 잘 작동한다
- AI 에이전트는 컴파일러가 아니라, 신입 인턴에 가깝다
- 불완전한 코드 + 모호한 지시를 받아 안전한 변경만 만들려는 경향이 강함
- 이로 인해 기존의 나쁜 결정(예: 잘못된 아키텍처)을 래 퍼(기존 코드나 기능을 감싸는 새로운 코드 layer를 만드는 것)와 인디렉션(직접 하지 않고, 간접적으로 거쳐서 하는 것, 중간 단계를 추가하는 행위)으로 감싸며 더 복잡하게 만든다
- 인간이 직접 코드를 쓰며 불필요한 부분을 과감히 삭제하고 탐색해야 더 나은 설계가 나온다
- AI 덕분에 소프트웨어 개발 환경은 크게 향상되었다. 하지만 세세한 디테일에 주의를 기울이고, 전체 그림과 연결짓기 위해서는 직접 손을 움직여 코드를 경험하는 과정이 여전히 필요하다
나는 왜 객체 설계를 포기하고 스프레드시트처럼 코딩하기 시작했나
- 많은 개발자는 애플리케이션이 커지면 MVC, MVVM, DI 등의 수많은 디자인 패턴을 도입하려 한다. 그러나 저자는 이런 접근이 코드의 의도와 실제 동작 사이에 수많은 추상화 층을 만들어내, 결과적으로 실행 시에야 전체 모습을 파악할 수 있는 복잡한 객체 그래프를 낳는다고 지적함. 이로 인해 버그 추적이나 사양 변경 시 코드의 ‘고고학적 발굴 조사’를 강요당하는 현상에 강한 의문을 제기한다.
- 이에 저자가 선택한 대안은 전통적인 객체 중심 설계(요소를 클래스에 쪼개는)가 아니라, 데이터를 중심으로 한 명시적 데이터 흐름 모델이었다. 모든 로직을 ‘셀(변수)‘과 ‘계산(데이터 간의 의존 관계)‘으로 구성된 프로그램(시트) 단위로 정의하며, Excel의 스프레드시트에서처럼 데이터 간 의존성(영향 범위)을 코드상에서 명시적으로 기술하는 방향으로 틀었다.
- 이 접근의 핵심은 애플리케이션의 구성 단위를 ‘상태와 행동을 가진 객체’에서 ‘명시적으로 연결된 데이터의 처리 과정’으로 재구성 했다. 전통적인 설계에서는 어떤 객체의 변화가 다른 곳에 전달되기 위해 옵저버 패턴이나 이벤트 버스 같은 복잡한 배선이 필요했다. 그러나 입력과 출력을 데이터로서 미리 선언함으로써, 코드들이 서로를 숨겨서 참조하는 ‘보이지 않는 결합’을 근본부터 배제하게 했다.
- 게다가 UI의 자동 생성이나 되돌리기(Undo/Redo) 같은 시스템 공통의 무거운 기능을 개별 기능 클래스의 구현에 의존시키지 않고, 데이터 흐름의 구조 자체에 포함시킨 점도 극히 합리적이다. 기능을 추가하는 것은 새로운 클래스 간의 결합 관계를 협상하는 것이 아니라, 단순히 새로운 ‘데이터 처리 시트’를 병렬로 배치하는 것으로 끝낸다. 시스템의 전체 구조가 런타임상의 메모리 공간에서가 아니라, 코드상의 정적인 데이터로서 한눈에 파악할 수 있는 상태를 만들어 개발 효율을 비약적으로 향상시켰다.
C로 직접 만든 TCP 로드 밸런서로 이해하는 이벤트 드리븐 아키텍처
- TCP 레벨(Layer 4) 로드 밸런서를 C로 직접 구현하며 그 동작 원리를 깊이 이해하려는 실천적 해설이다. 단순한 개념 설명을 넘어, 「왜 thread-per-request 모델이 한계에 부딪히는가」와 「이벤트 드리븐 설계가 왜 효 과적인가」를 메모리·CPU 관점에서 구체적으로 보여준다.
- 로드 밸런서의 기본 역할은 클라이언트 연결 수락 → 백엔드 서버 선택 → 연결 → 양방향 데이터 전달로 단순하지만, 본질은 대량의 동시 연결을 어떻게 효율적으로 처리하느냐 에 있다. 스레드를 요청마다 생성하는 방식은 일견 이해하기 쉽지만, 메모리 소비나 컨텍스트 스위치의 비용으로 인해 곧 한계에 도달한다. 특히 백엔드 처리 중 스레드가 idle 상태로 대기하는 비효율이 크다. 그래서 등장하는 것이 epoll이나 kqueue 같은 이벤트 알림 기구를 사용한 설계이다.
- 이 설계에서는 「처리하는」 것이 아니라 「기다리는」 것을 다루는 방식이 근본적으로 바뀐다. 전통적으로는 각 요청에 전용 실행 주체(스레드)를 할당했지만, 이벤트 드리븐에서는 「지금 바로 처리해야 할 연결만 골라내는」 발상으로 바뀐다. 결과적으로 단일 또는 소수의 스레드로 수만 개의 연결을 다룰 수 있게 되어 리소스 효율이 극적으로 개선된다.
- CPU의 사용법도 함께 바뀐다. 스레드가 많을 경우 CPU는 문맥 전환에 시간을 빼앗기지만, 이벤트 드리븐에서는 그 오버헤드가 거의 사라진다. 즉, 같은 하드웨어에서도 「무엇에 시간을 쓰고 있는가」가 바뀜으로써 실효 성능이 크게 달라진다. 이 설계 사상이 NGINX나 HAProxy 같은 고성능 시스템의 핵심 설계 사상이다.
- CPU에게 최악의 데이터 액세 스 패턴을 탐구하는 실험을 통해, 메모리 계층(캐시, TLB, 페이지 테이블)과 DRAM의 작동 방식을 상세히 설명한 기사이다. 순차 액세스가 가장 빠른 반면, 랜덤 액세스는 이미 10배 이상 느려진다. 저자는 캐시 라인 낭비, 페이지 경계 활용(프리페치 무력화), 캐시 set conflict, stride를 통한 TLB/PTE 부하 증가, 그리고 DRAM bank/row conflict까지 하나씩 역이용하여 랜덤보다 약 33% 더 느린 액세스 패턴을 만들어낸다.
- CPU의 성능을 결정짓는 것은 클럭 주파수나 명령 실행 속도만이 아니다. 최근 CPU는 ‘다음에 무엇을 읽을지’를 예측하여 캐시로 미리 데이터를 옮겨 빠르게 처리한다. 따라서 프로그램의 실행 속도는 알고리즘뿐만 아니라 데이터를 어떤 순서로 읽는지에 크게 좌우된다.
- 그리고 그 최적화를 하나씩 파괴해 나가는 구성으로 되어 있다. 먼저 캐시 라인을 낭비하고, 다음으로 페이지 경계를 넘어 프리페치를 무력화하며, 이어서 캐시 세트 충돌이나 TLB·페이지 테이블의 부하를 늘리고, 마지막으로 DRAM 내부의 뱅크 충돌까지 노란다. 단순한 벤치마크가 아니라, ‘CPU가 왜 빠른가’를 역방향으로 이해하는 교재가 된다.
- 최종 단계에서는 성능 저하의 원인이 CPU가 아니라 메모리 컨트롤러나 DRAM의 내부 구조로 옮겨간다. 소프트웨어 코드가 결국 하드웨어의 물리적 구조에까지 영향을 받는다는 사실을 이 실험이 보여준다.
2.7KB 메모장 TinyRetroPad, bloat 시대에 던지는 메시지
- 전 Microsoft 엔지니어이자 Task Manager의 저자로 알려진 데이브 플러머(Dave Plummer)는, 최근 몇 년간 Windows 기본 메모장이 AI 기능과 각종 부가 기능으로 인해 점점 비대해지는 현상에 의문을 제기하며, 불과 약 2.5~2.7KB 크기의 초소형 메모장 “TinyRetroPad”를 공개했다. 이는 Windows XP 시대의 메모장을 연상시키는 간결한 조작성을 유지하면서도, 파일 열기·저장·폰트 변경·인쇄 등의 기본 기능을 모두 갖추고 있다.
- TinyRetroPad는 필요한 기능을 애플리케이션 내부에 모두 직접 구현하지 않고, Windows에 기본 탑재된 RichEdit 컴포넌트 등을 적극적으로 활용한다. 프로그램 자체는 극도로 작지만, OS가 제공하는 메커니즘을 현명하게 재사용함으로써 충분한 실용성을 확보했다. 이는 “새로 만드는” 것이 아니라 “이미 있는 것을 잘 활용하는” 설계 철학을 보여준다.
- 과거 Microsoft에서는 Notepad는 플레인 텍스트 전용, WordPad는 리치 텍스트 전용으로 역할을 명확히 구분하고, 불필요한 기능을 넣지 않는 것이 미덕으로 여겨졌다. 그러나 현재는 단순한 도구에도 AI 어시스턴트, 클라우드 연동, 텔레메트리 등 수많은 기능이 기본으로 추가되는 것이 당연시되고 있다. 사용자 경험 향상이라는 명목으로 기능이 계속 늘어나면서, 애플리케이션은 점점 크고 복잡해졌고, 본래의 “바로 시작해서 바로 쓸 수 있는 도구”라는 본질이 희미해졌다.
- TinyRetroPad는 이러한 흐름에 대한 일종의 반발이라고 생각한다. 극단적으로 작은 구현을 통해 “정말 필요한 것은 무엇인가”, “OS가 제공하는 공통 기능을 더 믿고 활용할 수는 없는가”라는 소프트웨어 설계의 원점을 다시금 되묻고 있다.
- 이 이야기는 단순한 “옛날 Notepad가 좋았어”라는 노스탤지어가 아니다. AI 시대일수록 모든 소프트웨어에 기능을 끊임없이 추가하려는 경쟁이 치열해지지만, 진정한 가치는 “무엇을 추가할까”를 결정하는 데서뿐만 아니라 “무엇을 추가하지 않을까”를 현명하게 판단하는 설계력에서도 나온다.
- 이 프로젝트는 단순히 “작은 바이너리”를 만드는 데 목적이 있는 것이 아니라, OS 전체를 하나의 플랫폼으로 보고 공통 자산을 최대한 재사용한다는 고전적인 설계 사상을 실증한다. 컴포넌트 재사용, 책임 분리, 단순성 유지라는 원칙이 AI 시대의 소프트웨어 개발에서도 여전히 강력한 가치를 지니고 있음을, 이 작은 텍스트 에디터가 조용히 보여주고 있다.
AI가 코드를 쓰는 시대, 우리는 무엇을 가르칠 것인가
- AI에 의한 코드 생성이 일상화되고 있는 시대에, 저자는 12년 만에 대학 알고리즘 강의를 다시 맡게 되었다. 이전에는 “어떤 교과서를 쓸까”가 주요 고민이었지만, 이번에는 “무엇을 가르쳐야 하는가”가 핵심 주제가 되었다. 학생들의 학습 방식과 소프트웨어 개발 현장이 크게 변했기 때문이다.
- 저자는 AI가 코드를 생성하는 시대가 되었기 때문에, 학생들에게 코드를 읽고 이해하며, 그 안에 담긴 알고리즘을 파악하고, 정확성과 성능을 분석·평가하는 능력이 더욱 중요해졌다고 강조한다. 교재 선택에서도 시중 교과서나 AI 기능을 강조하는 플랫폼(zyBooks 등)보다는, 자신의 강의 노트를 중심으로 엄선한 웹 자료를 보완하는 방향을 검토하고 있다. 알고리즘의 기본 체계 자체는 여전히 가치가 있는지 독자에게 묻는다.
- AI의 등장에도 불구하고 저자는 “새로운 알고리즘을 대거 추가해야 한다”는 극단적인 결론을 내리지 않는다. 오히려 코드 작성의 가치가 상대적으로 낮아질수록 추상적 사고와 계산 복잡도·타당성 평가 능력이 더 중요해진다는 관점을 제시한다.
- 교재 선택 기준 역시 가격이나 AI 기능 유무가 아니라, 학생의 이해를 얼마나 깊게 이끌어내는가에 초점을 맞추고 있다. AI 도입 자체를 목표로 삼지 않고, 학습 경험을 어떻게 설계할 것인지에 관심을 두는 태도가 인상적이다.
- 마지막으로 저자가 독자들에게 적극적으로 의견을 구하는 모습에서 알 수 있듯이, AI 시대의 컴퓨터과학 교육 커리큘럼은 아직 “완성형”이 아니다. 교육자들이 직접 시행착오를 거치며 만들어가는 과정이라는 점이 잘 드러난다.
- 좋은 API는 처음에 “아름답게 보이는” 것이 아니라, 시간이 지나도 망가지지 않고 계속 사용되는 API이다. API의 진짜 품질은 설계 직후나 첫 버전 단계에서는 제대로 판단할 수 없다. 처음에는 요구사항이 단순하고, 사용자도 제한적이며, 주변 시스템도 변하지 않았기 때문에 거의 모든 API가 괜찮아 보인다. 그러나 다른 팀이 사용하기 시작하고, 요구사항이 바뀌며, 구현이 교체되 고, 원래 설계자가 전혀 예상하지 못한 방식으로 활용되면서 진짜 우수한 API인지가 드러난다. 저자는 “시간이 지나도 여전히 의미가 있는 API”가 진정한 좋은 API의 기준이라고 강조한다.
- 이런 관점에서는 경계(Boundary)를 얼마나 신중하게 결정하느냐가 API 수명을 좌우한다. 편리함을 이유로 내부 상태나 불필요한 필드를 공개하면, 그것이 곧 사용자들의 전제가 되어 나중에 변경하기 극도로 어려워진다. 현재 UI나 일시적인 요구사항에 맞춰 API를 설계하는 경우도 마찬가지다. 프로덕트가 변하는 순간 API도 함께 구식이 된다. API는 화면의 모양이 아니라, 더 오래 지속되는 도메인 개념을 표현해야 하며, 버저닝(versioning)도 근본적인 설계 문제를 해결해주지 못한다고 지적한다.
- 이 사고방식의 핵심은 “API는 코드가 아니라 계약(Contract)이다”라는 인식이다. 개발자는 구현을 자유롭게 바꿀 수 있다고 생각하지만, 한 번 공개된 동작이나 데이터는 사용자가 의존하게 되면서 사실상의 사회적·기술적 계약이 된다. 따라서 “추가하는 것은 쉽지만, 삭제하는 것은 매우 어렵다”는 원칙을 가장 중요하게 여겨야 한다. 처음부터 최소한만 공개하고, 정말 필요할 때만 추가하는 보수적인 접근이 장기적으로 안정적인 API를 만든다. API는 화려함이나 단기적인 편리함보다 변경 내성(Change Resilience)을 최우선으로 설계해야 한다는 것이다.
- 프론트엔드에 최적화된 응답이나 지나치게 똑똑한 API도 경계해야 한다. 처음에는 개발 효율이 높아 보이지만, 실제로는 암묵적 가정과 복잡성을 API 안에 숨겨두는 행위일 뿐이다. 새로운 유스케이스가 등장하면 유연성을 잃고 유지보수가 힘들어진다. 장수하는 API는 화려함보다 조금 지루하고 솔직한(boring and honest) 모습, 즉 경계와 상태를 명확하게 드러내는 모습을 가져야 한다고 저자는 결론짓는다.
AI가 만드는 부와 권력을 누구에게 돌려줄 것인가 — 버니 샌더스의 제안
- 버니 샌더스는 WIRED 인터뷰에서 AI를 “인류 역사상 가장 중대하고 변혁적인 기술”로 규정하면서도, 그 개발·배치 방향을 소수의 거대 IT 기업과 억만장자(머스크, 베이조스, 저커버그 등)가 독점적으로 결정하는 것을 가장 큰 문제로 지적한다. AI가 인간 지식과 노동을 기반으로 한 기술임에도 불구하고, 그 이익이 극소수에게 집중되는 구조를 비판하며, 데이터센터 건설 모라토리엄(일시 중단)과 미국 AI 주권 부 펀드(American AI Sovereign Wealth Fund)를 주요 대안으로 제시하며, AI로 인한 이익을 주주뿐 아니라 사회 전체에 분배해야 한다고 주장한다.
- 주권 부 펀드는 단순한 재분배를 넘어, AI 기업(매출 2억 달러 이상)의 지분 절반을 공공이 소유하고 이사회에 공공 대표를 절반 참여시켜, 이익 분배뿐 아니라 기술 개발·배치 결정 자체에 시민의 목소리를 반영하려는 것이다. AI로 인한 대규모 실업(트럭·운송 노동자 등), 어린이 정신건강 악화, 프라이버시 침해, 정교해지는 딥페이크 등 위험이 이미 드러나고 있음에도, 의회에서는 의미 있는 논의나 입법이 전혀 이루어지지 않고 있다고 강하게 비판한다.
- 그 배경으로 거대 IT 기업의 막대한 정 치 자금 기부, 슈퍼 PAC, Citizens United 판결 등 부패한 선거 자금 시스템으로 인해 많은 정치인들이 AI 규제에 손대지 못하는 구조가 있다고 분석한다. 샌더스는 문제의 본질을 ‘AI 기술 자체’가 아니라 AI가 증폭시키는 권력 집중과 올리가키(소수 지배)에 둔다. 데이터센터 반대 운동도 환경·전기 요금 문제뿐 아니라, 지역 주민보다 기업 의지가 우선시되는 ‘민주주의 결여’에 대한 반발로 해석한다.
- 샌더스는 AI 개발을 ‘중국과의 경쟁’이라는 국가주의 프레임으로 접근하는 데도 거리를 두고 있으며, 인류 전체의 이익과 국제 협력을 강조한다. 기술 경쟁을 핑계로 규제를 미루는 대신, 사회적·인간적 가치를 최우선으로 다뤄야 한다는 입장이다.
- 전반적으로 이 인터뷰는 AI 논쟁의 초점이 ‘기술의 편리함 vs 위험’에서 ‘AI가 창출하는 막대한 부와 권력을 누가 통제하고, 누구를 위해 설계되는가’라는 자본주의·민주주의의 근본 설계 문제로 이동하고 있음을 보여준다. 샌더스는 수십 년간 일관되게 주장해온 ‘집중된 부의 민주주의 위협’이 AI 시대에 정점에 달했다고 보고, 지금이 변화를 위한 결정적 순간이라고 강조한다.
우수한 엔지니어란, 코드를 쓰는 사람이 아니라 팀의 ‘보이지 않는 마찰’을 줄이는 사람이다
- 이 글은 채용 면접에서 시스템 설계나 알고리즘 능력으로 높은 점수를 받지 못했던 엔지니어 ‘Mitch’가, 실제 입사 후 조직에 큰 가치를 창출하는 과정을 그린다. 그는 화려한 코딩 실력이나 아키텍처 설계 능력이 뛰어나지 않지만, 오래된 문서를 정리하고, 모호한 책임 영역을 명확히 하며, 인수인계 과정의 잠재적 문제를 미리 발견해 해결한다. 팀은 점차 그가 있음으로써 일이 훨씬 수월해지고 있다는 사실을 깨닫는다.
- 저자는 이런 인재를 ‘Gap Reader(갭 리더)’라고 명명한다. 이들의 핵심 가치는 방대한 지식량이 아니라, ‘어디에 구멍(갭)이 있는지’를 감지하는 능력이다. 조직 간 인식 차이, 아무도 소유하지 않는 책임 공백, 미래 장애 요인이 될 수 있는 의존 관계나 손실된 맥락을 찾아내 메워나간다. 그러나 이러한 성과는 ‘아무 일도 일어나지 않았다’는 형태로 나타나기 때문에, 면접이나 성과 평가에서 쉽게 간과되기 쉽다는 점을 지적한다.
- 이 글은 엔지니어링의 가치를 ‘코드를 작성하는 능력’에서 한 단계 더 나아가 ‘조직 전체의 마찰과 조정 비용을 줄이는 능력’으로 확장한다. 소프트웨어 개발에서 많은 작업은 실제 코딩 시간보다 사람과 사람, 팀과 팀을 연결하고, 안전하게 변경할 수 있는 상태를 만드는 데 쓰인다. Mitch가 하는 일은 바로 이런 기술적 레버리지(technical leverage)를 창출하는 진짜 엔지니어링이다.
- 이 글은 평가 시스템의 구조적 문제도 제기한다. 장애를 일으킨 뒤 영웅적으로 해결한 사람은 인정받기 쉽지만, 장애 자체를 미연에 방지한 사람은 눈에 띄지 않는다는 역설을 꼬집는다. ‘성과’는 눈에 보이는 결과물뿐 아니라, 문제가 발생하지 않은 안정성에도 존재한다는 관점이다.
- 마지막으로, Gap Reader의 잠재적 위험도 언급한다. 이 능력이 뛰어난 사람에게 조직이 지나치게 의존하게 되면, “그 사람에게 물어보면 된다”는 상태가 되어 개인 자체가 병목(Bottleneck)이 될 수 있다. 본래는 이런 지식과 조정을 시스템과 프로세스로 전환해야 하는데, 사람에게 의존하게 되면 장기적으로 위험해진다는 것이다.
- 「좋은 엔지니어는 모범 사례를 아는 사람이지만, 시니어는 그것을 깨야 할 순간을 아는 사람이다.」 이 한 문장이 10년 넘게 경험을 쌓은 엔지니어가 도달한 결론을 가장 잘 표현한다. 기술 스택이나 프로그래밍 언어의 우열에 크게 의미를 두지 않는다. 대신 소프트웨어 개발의 기본 원칙, 사람과의 소통, 문서 작성, 매니저와의 신뢰 관계, 적절한 이직 타이밍 같은 보편적인 요소들이 긴 커리어에서 훨씬 더 중요하다고 필자는 말한다. “최고의 코드는 존재하지 않는 코드”, “SQL은 투자 대비 효과가 가장 높은 언어” 같은 직설적인 의견도 유행보다 본질을 중시하는 태도를 보여준다.
- 커리어가 쌓일수록 가치관도 많이 바뀐다. 젊을 때는 최신 기술과 코딩 자체에 열중했지만, 경험을 쌓으면서 사람을 키우는 일, 팀을 지탱하는 일, 가족과 건강, 삶의 균형이 훨씬 더 소중하다는 것을 깨닫게 된다. “코드를 쓰는 것은 일의 일부일 뿐, 삶 그 자체는 아니다”라는 관점이 글 전체를 관통한다.
- 이 사고방식이 가장 잘 드러나는 것은 모범 사례를 아는 것과 상황에 따라 일부러 벗어나는 것을 구분하는 능력이다. 경험은 단순히 지식을 늘려주는 것이 아니라, 현실의 제약이나 조직 상황을 고려해 최적의 판단을 내릴 수 있게 해준다고 필자는 반복해서 강조한다. 기술뿐만 아니라 인간관계, 비즈니스, 조직 운영까지 폭넓게 생각할 수 있게 됐을 때 진짜 시니어 엔지니어라고 할 수 있다.
- 일에 대한 태도도 변한다. 기술은 취미에서 직업으로 바뀌고, 일은 삶의 중심에서 한 부분으로 자리 잡는다. 대신 자신이 키운 사람들, 지탱한 팀, 쌓아온 신뢰 관계가 오래 남는 진짜 성과라는 가치관으로 자연스럽게 옮겨간다.
- 코드는 실행되어 실제로 동작하므로 신뢰할 수 있지만, 명세서(Spec)나 문서는 금세 오래되어 신뢰하기 어렵다.
- 예전에는 인간이 직접 생각하면서 수동으로 코드를 작성했기 때문에, 코드에는 인간의 판단과 맥락이 많이 녹아 있었고, 그것이 신뢰의 주요 근거였다.
- Claude Code 같은 AI 에이전트를 사용하면, 구현 과정에서 원래 아이디어를 실시간으로 조정할 수 있어 개발 속도가 매우 빨라진다.
- 구현하면서 피드백을 즉시 얻을 수 있다는 점은 큰 장점이지만, 코드도 명세도 아닌 ‘경험이 풍부한 인간’이 진리의 원천(Source of Truth)이 되어 버린다는 문제가 생긴다.
- 개발자가 에이전트의 부족한 컨텍스트를 보완해주는 방식은 시스템 규모가 작고 한 사람이 전체를 머릿속에 담을 수 있을 때는 잘 작동한다.
- 그러나 시스템이 커지고 팀원이 바뀌면 인간의 기억은 신뢰할 수 없게 되고, 기술되지 않은 부분에 대해 에이전트가 그럴듯한(plausible) 추측으로 구현해 버린다.
- 일반 소프트웨어 개발에서 명세(spec)는 작업이 끝나면 거의 보지 않는 일시적인 산출물이지만, 항공우주·의료 등 규제 산업에서 사용하는 ‘요구사항(requirement)’ 개념이 도움이 될 수 있다.
- 요구사항은 시스템이 무엇을 해야 하는지뿐만 아니라, 의도대로 구현되었음을 증명하는 증거가 어디에 있는지도 함께 기록하며, 작업 완료 후에도 지속적으로 살아남는다.
- AI로 구현이 빨라졌기 때문에 오히려 의도(intent)를 잃어버릴 위험이 커졌다. 테스트가 통과하고 CI가 녹색이어도 원래 의도와 미묘하게 어긋난 경우가 발생한다.
- 처음부터 거대한 명세서를 완벽하게 작성하는 것이 정답은 아니다. 중요한 것은 의도와 구현 사이에 생기는 drift(어긋남)을 어떻게 관리할 것인가이다.
- 코드가 바뀌면 관련 요구사항과 테스트를 의심하고, 요구사항이 바뀌면 코드를 리뷰하는 등 추적 가능성(traceability)과 증거 관리가 필수적이다.
- CI 테스트 통과는 “현재 테스트를 만족한다”는 증거일 뿐, 원래 의도와 여전히 일치하는가에 대한 증거는 아니다.
- 에이전트로 코드를 저렴하고 빠르게 만들 수 있게 되었기 때문에, 오히려 더 쉽게 잃어버리게 된 ‘의도’를 요구사항 형태로 더 진지하게 관리해야 한다.
- 경험이 풍부한 시니어 엔지니어일수록 AI에 의한 생산성 향상을 가장 낮게 평가하며, 그 출력을 가장 신뢰하지 않는다.
- 이는 단순한 불만이 아니라, 대시보드에 드러나지 않는 코드베이스의 위기를 감지하는 중요한 신호이다.
- 조사에 따르면, 변경된 코드 중 복사-붙여넣기(copy/paste) 비율이 2021년 8.3%에서 2024년 12.3%로 증가했다.
- 반면 리팩토링(refactoring) 비율은 약 25%에서 10% 미만으로 급감했다.
- AI로 인해 중복 코드를 쉽게 대량 생산할 수 있게 되어, 코드베이스가 점점 넓어지고(wider) 정리되지 않고 있다.
- 중복 코드를 하나로 통합하는 지루한 작업은 AI가 스스로 하지 않고, 주니어도 잘 알아차리지 못하기 때문에 시니어만이 이 위기를 먼저 감지하고 있다.
- AI 도입률이 25% 증가하면 배포 안정성(delivery stability)은 7.2% 하락하고, 처리량(throughput)도 1.5% 하락한다.
- AI를 사용하면 코드 생산량이 늘어나 변경 규모(batch size)가 커지고, 리뷰가 어려워져 결과적으로 복구 비용이 증가한다.
- 결국 개발 속도는 오히려 느려지고, 시스템 안정성도 저하된다.
- AI 출력의 정확성에 대한 개발자 신뢰도는 40%에서 29%로 하락했으며, 호감도(favorability)도 72%에서 60%로 떨어졌다.
- 개발자의 46%가 AI 정확성을 적극적으로 불신하고 있으며, 가장 큰 불만은 “거의 맞지만 완벽하지 않은(almost right, but not quite)” 제안이다.
- 개발자의 96%가 AI 생성 코드의 정확성을 완전히 신뢰하지 않지만, 커밋 전에 반드시 검증하는 사람은 48%에 불과하다.
- 이 무거운 검증 부담은 주로 시니어 엔지니어에게 집중되고 있다.
- 이사회에서 보는 커밋 수, PR 수 등의 velocity 지표는 성장하는 것처럼 보이지만, 대시보드는 불편한 진실을 숨기고 있다.
- 코드 재작성(churn), 축적되는 중복, 하락하는 안정성, 신뢰도 저하 등은 표시되지 않는다.
- 눈앞의 수치만 쫓다 보면 나중에 발생할 보안 문제와 높은 유지보수 비용을 은폐하게 된다.
- AI 생산성 향상을 이유로 신규 채용을 동결하거나 시니어를 줄이는 기업이 있지만, 이는 조직에 심각한 장기 문제를 초래한다.
- AI 활용이 늘수록 코드 검증과 감독 업무가 증가하므로, 시니어의 감사·감독 역할은 오히려 더 중요해진다.
- 주니어가 AI 출력 복붙에만 의존하면 미래 시니어로 성장할 기회를 잃게 된다.
- 시니어가 기계가 만든 코드의 후처리(cleanup)만 맡게 되면 의욕을 잃고 퇴사할 가능성이 높아지며, 중요한 시스템 지식이 함께 사라진다.
- AI 생산성 효과는 시니어와 주니어 사이에 큰 차이가 있으므로, 이를 전제로 인력 계획을 세워야 한다.
- 코드 리뷰, 아키텍처 설계, 감독 업무를 시니어의 주요 업무로 공식화하고, 적절히 평가·보상해야 한다.
- 대시보드에 처리량뿐만 아니라 코드 재작성율(churn), 중복률, 리팩토링률, 변경 실패율 등의 품질 지표를 함께 표시한다.
- AI 영향을 개인이 아닌 팀 단위로 측정하고, 개발자 sentiment(감정) 조사와 연계해 신뢰를 유지한다.
- 미래 시니어를 육성하기 위해 주니어 채용과 시니어 리뷰 체계를 의도적으로 유지한다.
- 시니어 엔지니어가 보내는 신호는 조직의 위험을 알리는 탄광의 카나리아와 같다.
- 기계가 코드를 얼마나 빨리 쓰는지가 아니라, 기계가 틀렸을 때 그것을 정확히 지적할 수 있는 인재를 어떻게 유지하고 육성할 것인지가 핵심이다.
왜 모든 소프트웨어 엔지니어가 “돈의 심리학”을 읽어야 하는가
- 스킬업과 건강 관리에 열중하느라, 돈의 메커니즘을 배우는 습관을 완전히 놓치고 있었다.
- 돈을 버는 것과 돈을 유지하는 것은 완전히 다른 스킬이다.
- 돈에 대한 올바른 사고방식을 배우기 위해, 《The Psychology of Money》에서 얻은 교훈을 소프트웨어 엔지니어 관점에서 정리한다.
- 자산을 쌓고 유지하려면 꾸준히 저축하면서 복리의 힘을 활용해야 한다.
- 부(wealth)는 눈에 보이지 않는 부분에 존재한다. 따라서 허세를 부리며 생활 수준을 과도하게 높이는 소비(lifestyle inflation)는 피해야 한다.
- 높은 월급을 받아도 큰 아파트나 새 차, 비싼 습관에 계속 돈을 쓰면 진짜 부를 쌓기 어렵다.
- 복리의 힘은 인생을 극적으로 바꿀 수 있으므로 절대 과소평가해서는 안 된다.
- 엔지니어가 매일 새로운 기술을 배우며 스킬을 compounding하는 것처럼, 돈 역시 같은 방식으로 꾸준히 쌓아갈 수 있다.
- 돈을 모으면 자신의 시간을 자유롭게 통제할 수 있게 된다.
- 진짜 목표는, 시간이라는 가장 소중한 자산을 자신이 진정으로 가치 있게 여기는 일에 쓸 수 있는 자유를 얻는 것이다.
- 기술 업계에서의 일뿐만 아니라, 업계 밖의 인생 계획도 함께 세워야 한다.
- 누군가 젊어서 유명 기업에 들어가거나, 자신보다 먼저 승진하는 모습을 보면 초라하게 느껴질 때가 있다.
- 하지만 현실에는 운, 타이밍, 리스크 등 본인의 힘으로 통제할 수 없는 요소가 많이 작용한다.
- 우리는 각자 다른 Git 브랜치에서 코드를 작성하고 있는 것과 같다. 타인의 진척을 비교하며 시간을 낭비하지 말아야 한다.
- 다른 사람의 경제 상황을 부러워하거나 신경 쓰는 대신, 자신의 노력에 집중하면 불만 대신 성장할 수 있다.
- 아무리 뛰어난 지식과 기술을 배워도, 일관성 있게 행동하지 않으면 모든 노력이 물거품이 된다.
- 의욕이 없는 날에도 최소한 할 수 있는 일을 해내서, 오래 시장에 남아 있는 것이 성공의 핵심이다.
- 이 책은 어디에 투자하라는 구체적인 조언이 아니라, 돈에 대해 어떻게 생각해야 하는지 사고의 틀을 알려준다.
- 이 교훈은 커리어의 어느 단계에 있는 엔지니어에게도 동일하게 적용할 수 있다.
- 매일 쌓아가는 작은 노력들이 수년 후 복리처럼 불어나, 결국 스스로 자랑스러워할 수 있는 인생을 만들어줄 것이라고 믿는다.
옛날 소프트웨어가 빨랐던 이유: 선택의 여지가 없었기 때문이다
- Spark 클러스터를 시작하고 조정하는 간단한 Java 프로그램(launcher/coordinator)이 있다.
- 이런 시작용 프로그램에는 원래 1개의 CPU와 2GB 메모리 정도면 충분하다.
- 그러나 “본番(프로덕션) 환경”이라는 이유만으로, 리소스를 사치스럽게 쓰는 것을 당연하게 받아들인다.
- 일시적인 장애가 발생할 때마다 대처책으로 메모리나 CPU 할당량을 늘려버린다.
- 안전 마진을 크게 확보함으로써 재발을 막고, 시스템이 안정되었다고 안심한 채 다음 작업으로 넘어간다.
- 시간이 지나면서 원래 원인은 잊히고, 일시적인 응급 조치가 변경 불가능한 필수 요구사항으로 굳어진다.
- 하드웨어가 진화하고 최적화가 진행되었음에도, 소프트웨어는 그보다 더 빠른 속도로 무거워지고 있다.
- 기술 진보로 얻은 여유를 더 무거운 런타임, 복잡한 라이브러리, 과도한 모니터링·텔레메트리에 소비한다.
- 개발 효율이 높아졌는데도 단순한 시스템을 만드는 대신, 더 복잡하고 움직임이 많은 시스템을 구축하게 된다.
- 컨테이너 메모리 상한에 여유를 주면, Java 런타임은 여유가 있다고 판단해 가비지 컬렉션을 게을리하게 된다.
- 소프트웨어는 작업량이 늘어서가 아니라, 주어진 리소스 만큼 팽창한다.
- 현대 시스템에 필요한 보안·관찰가능성(observability) 등의 복잡함은 진짜이지만, 그것을 핑계로 불필요한 설정까지 옹호해서는 안 된다.
- 사용하지 않는 불필요한 라이브러리, 로그, 기본 이미지 등의 누적이 전체를 크게 비대하게 만든다.
- 옛날 소프트웨어가 빨랐던 이유는 개발자의 윤리관이 뛰어나서가 아니라, 하드웨어의 엄격한 제약 때문이었다.
- 리소스가 수 기가바이트로 제한되던 시대에는 서비스를 제대로 동작시키기 위해 우선순위를 정하고 튜닝할 수밖에 없었다.
- 현대 클라우드 인프라는 관대해서 불필요한 리소스 할당이 정상 상태로 간과되기 쉽다.
- 메모리 사용률이 겨우 10%여도 모니터링 화면에는 건강한 녹색으로 표시되어, 최적화 실패가 운영 안전성으로 오인된다.
- 시스템이 한계에 도달했을 때의 알림은 충실하지만, 리소스가 텅 비어 있는 상태(structural emptiness)를 경고하는 메커니즘은 거의 없다.
- 과거에는 하드웨어 추가에 물리적 절차와 승인이 필요해 유익한 마찰(friction)이 있었다.
- 지금은 설정 파일만 바꾸면 쉽게 리소스를 늘릴 수 있어 의사결정이 가벼워졌고, 스스로 설명하고 지적할 기회가 사라졌다.
- 엔지니어 인건비가 컴퓨터 자원보다 훨씬 비싸기 때문에, 하드웨어 증강은 경제적으로 합리적인 경우가 많다.
- 그러나 하드웨어에 지나치게 의존하면 모든 장애를 provisioning 문제로 일단락짓게 되고, “돈을 지불해 야간 트러블을 막는 것”을 우수한 설계로 착각할 위험이 있다.
- 의사결정자와 비용 부담자가 다르기 때문에 시스템 전체의 비대화가 살아남는다.
- 의존성을 추가한 개발자는 즉각적인 개발 속도를 얻지만, 미래 유지보수 담당자가 업그레이드 고통을 짊어진다.
- 느린 시스템은 일상 작업 효율을 계속 떨어뜨리지만, 결정적 장애가 아니므로 긴급 과제로 삼지 않는다.
- 해결책: 프로그램 시작 시간, 컨테이너 크기, 메모리 사용량에 대해 명확한 예산(budgets)을 설정해야 한다.
- 예산을 초과하는 변경 시, 무엇이 바뀌었고 어떤 가치를 가져다주는지 명확히 설명하게 한다.
- 모든 코드를 극한까지 최적화할 필요는 없지만, 선택지의 트레이드오프를 의식하는 것이 중요하다.
- 단순한 프로그램에 수십 GB가 필요하다면, 시작 시 무엇이 로드되고 있는지 객관적으로 보여줄 필요가 있다.
- 근거를 보일 수 없는 리소스 할당은 더 이상 엔지니어링이 아니라 단순한 미신(superstition)이다.
- 타인이 어떻게 하는지를 기준으로 삼지 말고, 기계가 실제로 무엇을 하는지 파악하고, 작은 리소스 제한을 과도하게 두려워하는 것을 그만둬야 한다.
오픈 소스
- 이 사이트는 많은 개발 팀이 실제 필요를 앞지른 premature optimization으로 Redis, Elasticsearch, Kafka 등 수많은 외부 서비스를 도입해 시스템을 불필요하게 복잡하게 만드는 관행을 날카롭게 비판한다. 표면적으로는 진지한 기술 제안처럼 보이지만, “Webscale™(유행하는 기술을 무작정 늘어놓은 복잡한 구성)” 스택이라는 풍자적 표현을 통해 트렌드를 맹목적으로 추종하는 엔지니어 문화와 “혁신 토큰(inovation tokens)” 낭비하지 말라는 등 풍자와 실용적인 조언을 하고 있다.
- 결국 “하나의 데이터베이스로 충분하다”는 메시지는, 운영 복잡성과 예상치 못한 문제에 시달리는 현업 개발자들에게 강력한 공감을 불러일으키며, 지루하지만 검증된 인프라(Boring Infrastructure)로의 회귀와 Postgres의 한계를 먼저 도전해보는 실용성을 강조한다.
- 이 주장이 설득력을 얻는 배경에는 하드웨어의 극적인 발전이 있다. 과거 고가의 전용 장비와 자원 부족해서 성능을 짜내기 위해 데이터를 분산·최적화할 수밖에 없는 물리적 제약이 존재해 부족한 자원과의 싸움이었지만, 지금은 단일 서버로도 수백 코어 CPU, 테라바이트 메모리, 초고속 NVMe 스토리지를 활용할 수 있게 되었다. 한때 대규모 데이터 센터나 전문 DBA(데이터베이스 관리자) 팀이 필요했던 수준의 부하를, 이제 저렴한 한 대의 머신이 여유롭게 처리해 버린다. 대부분의 애플리케이션에서 “성능 부족 공포”는 이미 시대착오적인 것이 되었다.
아래는 Postgres로 할 수 있는 것들에 대응되는 툴들(오픈소스)을 소개한다.
| You need… | You reach for… | But Postgres has… |
| Caching | Redis, Memcached | UNLOGGED tables, materialized views → |
| Job queues | Redis + Sidekiq, RabbitMQ | SKIP LOCKED, pgmq, pgflow → |
| Full-text search | Elasticsearch, Algolia | tsvector, pg_trgm, ParadeDB → |
| Document store | MongoDB, CouchDB | JSONB, FerretDB → |
| Vector search / AI | Pinecone, Weaviate | pgvector, pgvectorscale → |
| Time-series data | InfluxDB, TimescaleDB | TimescaleDB, pg_partman → |
| Analytics / OLAP | Snowflake, BigQuery | pg_analytics, DuckDB integration → |
| Graph database | Neo4j, Neptune | Apache AGE, recursive CTEs → |
| Geospatial | Specialized GIS systems | PostGIS → |
Herdr이 AI Agent 시대에는 잘 맞는 툴인 것 같다. IDE에서 CLI로 넘어가면서 자연스럽게 아래 워크플로가 가능해진다. 자세한 사용법은 Herdr 설정에서 확인할 수 있다.
- 평소에는 Ghostty에서 터미널 중심으로 작업하고,
- 대규모 코드 리딩이 필요하면 Zed에서 하고,
- 이동 중에는 Orca IDE에서 같은 Agent를 이어받아 확인하며,
- 다시 집에 와서는 Ghostty에서 이어서 작업한다.

