GN⁺ 10달전 | parent | ★ favorite | on: 그럭 브레인 개발자(2022)(grugbrain.dev)
Hacker News 의견
  • 나는 좋은 디버거의 가치를 돌로도 환산할 수 없을 만큼 높게 여김, 실제로 더 대단함을 느낌. 작은 스타트업이든 유명 빅테크 팀이든, 팀에서 나만 디버거를 쓰는 경우가 많았음. 실제 많은 사람들이 여전히 print 문으로 디버깅하는 현실을 봄. 내 워크플로를 동료들에게 알려주려 해도 반응이 없음. 시스템을 이해하기에 가장 좋은 출발점은 바로 디버거라는 데 동의함. 테스트 중 흥미로운 코드 라인에서 중단하고 스택을 보는 게 머릿속으로 코드를 따라가는 것보다 훨씬 쉬움. 디버거 쓰는 법을 익혀두면 진짜 소소한 초능력 얻는 것임. 가능하다면 꼭 한번 적용해보길 추천함
    • 나는 진짜 디버거를 쓰고 싶지만, 대기업에서만 일해온 입장에선 현실적으로 불가능했던 상황임. 마이크로서비스 메쉬 아키텍처에선 로컬에서 뭘 돌릴 수가 없고, 테스트 환경에서도 스텝 디버거를 붙일 수 없도록 세팅되는 경우가 대부분임. 그래서 print 디버깅이 유일하게 가능한 선택지임. 심지어 로그 시스템에까지 문제가 생기거나 프로그램이 로그를 출력하기 전에 그냥 크래시된다면 print조차 쓸 수 없는 상황임
    • 이 주제에 대해 수년 전 좋은 토론이 있었음. Brian Kernighan과 Rob Pike의 명언이 있는데, 둘 다 어린 개발자는 아님. "우리는 stack trace나 변수 값 몇 개를 확인하는 정도 외의 목적으로는 디버거를 쓰지 않음. 복잡한 자료구조와 제어 흐름 때문에 디테일에 갇히게 쉬움. 직접 프로그램을 머릿속으로 더 고민하고, 중간중간 print로 출력과 self-checking 코드 넣는 것이 더 생산적임. print 넣는 것이 디버거로 스텝 단위로 들어가는 것보다 훨씬 빠름. 또, print 코드는 프로그램에 남아 있고, 디버깅 세션은 사라짐." 나도 이 의견에 동의함. 대부분의 개발 과정에서 print-가설-실행 루프가 훨씬 빠른 문제 해결 제공함. 코드를 머릿속으로 "실행해보는" 게 아니고, 코드 흐름에 대해 이미 작동 모델이 있어서 print가 잘못된 출력을 보여주면 대개의 경우 빠르게 실상을 직감함. 관련 링크: The unreasonable effectiveness of print debugging
    • 리눅스 계열에서 printf 디버깅이 늘 보편적이었던 이유가, GUI 기반 디버거를 신뢰할 수 없는 환경 때문임. 리눅스의 GUI는 종종 불안정해서 믿을 수가 없음. 내게도 디버거를 제대로 쓰기 시작한 시점이, (1) 윈도우에서 GUI가 잘 되지만 CLI가 종종 깨질 때였고, (2) print 디버깅 코드가 실수로 버전에 반영돼서 문제 일으킨 경험을 여러 번 한 뒤였음. 그다음엔 CLI 디버거로 여러 모험을 했었고, Junit+디버거(이클립스 등 IDE 기반)로 실험적 코드를 바로 써보며 테스트로 남기는 식의 프로세스가 Python REPL만큼 편리함을 느낌. 단, 디버거를 환경에 맞게 세팅하는 초기 투자가 필요하긴 함
    • 내 코드에서는 디버거 쓰기가 쉽고 진짜 좋아함. 그런데 디버거가 내가 작성한 코드보다, 라이브러리나 프레임워크 내부로 깊게 들어가면 나도 바로 길을 잃고 싫어짐. 이런 프레임워크/라이브러리는 수십만 시간을 들여 만들어진 것이기 때문에 내 수준에서는 이해의 범위를 바로 넘어감
  • 교수님(Carson) 혹시 이 글 보신다면, 진심으로 감사 인사 전하고 싶음. 대학 때 HTMX를 왜 배우는 지, 왜 그렇게 열정적이셨는지 이해 못하다가, 몇 년 뒤에 제대로 깨달음. HTML over the wire가 진짜 전부임. Staff Ruby on Rails Engineer로 일하며 Hotwire에서도 교수님의 작업을 여러 번 봤고, 가끔 GitHub나 Hacker News에서 활동하시는 걸 보면 정말 놀라움. 늘 프로그래밍 커뮤니티의 빛 같은 존재임. 깊은 존경과 감사를 전함
    • 여기서 울컥하는 건 나뿐만이 아님, 감동임
    • HTMX가 그냥 밈 아니었나? Poe’s Law 때문에 진지한 건지 헷갈림
  • 이 글에는 진짜 명언이 많지만, 나는 마이크로서비스 얘기가 제일 좋았음: "grug는 큰 뇌가 시스템을 제대로 분해하기 힘든데, 굳이 네트워크 호출까지 추가하는 이유를 모름"
    • 어떤 사람들은 시스템을 파트로 쪼개는 방법을 API로 만드는 것밖에 모름. API로 노출되지 않으면 그저 이해 불가하고 재사용도 안되는 불투명 코드라고 생각함
    • 여러 이유로 마이크로서비스가 실용적인 경우가 있어서 쓰이는 점이 아쉽기도 함
    • 나는 사소한 웹앱 하나에 다섯 개의 폼만 있어도, 두 명짜리 소규모 dev팀이 이를 “마이크로서비스” 구조(데이터베이스 공유, API 관리, 큐를 통한 배치 작업, 이메일 알림, 자체 Observability 플랫폼 추가 등)로 복잡하게 만드는 걸 계속 봄. 그리고 결국은 평범한 폼도 SPA로 만들어서 ‘더 쉽기 때문’이라고 함. 이제는 “아키텍처”와 “패턴”이 쓸모없는 개발자들의 일거리 창출용임을 이해함. 만약 그런 게 없다면 “샌드위치 한 조각이라도 줄 테니 자바스크립트 쓸게요”라는 푯말 들고 거리에 있을 사람들임
    • 내 음모론 하나 말하자면, 마이크로서비스 패턴을 클라우드 벤더들이 밀어서 이런 결과가 나왔다고 생각함. - K8S 같은 오케스트레이터 없이는 실행도 못하게 만들고, 이걸로 관리형 클라우드 팔기 쉬워짐 - 더 많은 네트워크 트래픽/CPU 사용으로 과금 더 나옴 - 대규모 상태 공유가 힘들어서 관리형 데이터베이스/이벤트 큐 필요하게 만듦 - 로컬 실행 어려워져서 개발 환경까지 클라우드 비용으로 이어짐 - 클라우드 고유 방식에 종속돼 벗어나기 힘들어짐. 예전에 클라우드가 IT 비용을 절약해준다고 광고했는데 완전 웃김. 이미 2000년대부터 그게 허상임을 알았고, 결국 전부 더 비싸지는 결과뿐임
  • "복잡함 vs 티라노사우르스 대 면대면, grug는 복잡함보다 티라노사우르스 택함: 적어도 티라노사우르스는 눈에 보이니까"라는 문장을 일주일에 한 번은 떠올릴 만큼 인상 깊음
    • 인용문: "넘어지면서도 Leyster는 삽을 놓지 않고 있었다. 당황 속에서 그 사실을 잊은 것. 그래서 필사적으로 삽을 들고 새끼 티라노의 다리에 휘둘렀다...". 티라노사우르스와의 극한 생존 싸움을 생생하게 묘사한 장면임. 결국 동료 Tamara가 용맹하게 창으로 티라노 얼굴 한가운데를 찔러서 위기를 극복한 순간. 전투와 긴장감, 그리고 침묵의 장면이 인상적임
    • grug는 분명 ‘보이지 않는’ 티라노사우르스와 싸워본 적 없음. 나는 지금도 보이지 않는 티라노사우르스와 1:1 대결 중임, 진짜 고생임
  • 이 아티클에서 감탄할 점은, 작성자가 ‘더 복잡한 것’을 할 수 있지만 경험적으로 그 길을 선택하지 않는다는 점임. 물론 추상화나 복잡함이 필요한 때/장소가 있지만, grug 철학은 그런 것 자체에 본질적 가치가 없다는 것을 말함. 이 부분이 정말 일리 있다는 생각임. AI도 일관되고 데이터에 기반한 코드에서 더 효과적임을 느낌
    • 복잡함과 추상화를 사용할 때는, 그로 인해 코드가 전보다 이해하기 쉬워질 때임. ‘이해를 위해 특별 강좌가 추가로 필요하지 않을 때’라는 전제를 꼭 기억함. (상황에 따라 다름)
    • "모든 것은 가능한 한 단순하게 만들어야 한다, 그러나 너무 단순하게는 말고"
  • 이 글이 2022년 글이라니 믿기 힘듦. 이미 10년 전에 읽고 ‘고전’으로 알고 있었던 느낌임
  • 이 에세이가 소프트웨어를 만드는 데 있어 내가 제일 좋아하는 글임. 스타일도 매력적이고(누군가는 거부감 느낄 수도 있겠지만), 본질은 늘 유효함
  • "슬프지만 사실임: '예스' 배우고, 실패하면 다른 grug 탓하는 법 배우기, 최고의 커리어 전략"이라는 코드조각이 현실임. 나도 처음에는 회사에서 단순히 기술팀의 소통 문제가 원인이라고 착각했지만, (grug처럼) 실제로 그렇다는 걸 시간 지나며 배움
  • 지금까지 본 visitor pattern 설명 중 이 아티클 내용이 최고임
    • 나는 전형적인 OO 코드베이스에서 일하지 않아서 visitor pattern이 뭔지 제대로 몰랐는데, "Crafting Interpreters"라는 인터프리터/VM 만드는 책을 추천하고 싶음. 그 책에서는 visitor pattern을 실제로 어떤 식으로 쓰는지 나옴. 직접 읽어보며 복잡성의 이유를 이해하려 애썼지만, 결국 tagged union으로 대체했었음. 아마 내가 OO에 약한 건지도 모르지만, grug 아티클의 요지도 이와 같음. 굳이 복잡함과 간접성을 자처할 필요가 없을 때는 더 직관적인 방법이 있다는 점
    • 나는 네이밍에 민감한 편인데, visitor pattern이라는 이름은 너무 모호해서 불만임. 실제로 Visitor라는 이름으로 만든 적 없음. 예를 들어 문법 트리(AST) 실습이라면 Visitor 대신 AstWalker, AstItem::dispatch(AstWalker), AstWalker::process(AstItem)처럼 구체적 네이밍이 훨씬 의미 있음. visitor란 “방문한다”는 게 너무 추상적이고 무의미함. 상황에 따라 다른 게 맞고, 그냥 주석으로 ‘visitor pattern’이라고 명시하면 인식에 문제없음. 과거 두 개의 오브젝트 트리를 맞춰서 데이터를 비교/임포트할 일이 있었을 때, AbstractImporter라는 이름을 썼던 경험이 있음. 더 구체적인 이름, 과정, 역할이 명확했음. 전형적 visitor pattern과는 다름
    • 실제로 찾아보니 “Bad”라는 평이 있었음. ㅋㅋ
  • 관련 글 공유함. 다른 사람의 의견이나 추가 글 있음?<br/><i>The Grug Brained Developer (2022)</i> - https://news.ycombinator.com/item?id=38076886 - 2023년 10월 (192개 댓글)<br/><i>The Grug Brained Developer</i> - https://news.ycombinator.com/item?id=31840331 - 2022년 6월 (374개 댓글)