1P by GN⁺ 3일전 | ★ favorite | 댓글 1개
  • 소프트웨어 설계에서 항상 “가능한 가장 단순한 일”을 선택하는 것이 효과적인 조언임
  • 뛰어난 시스템 설계는 거창해 보이지 않으며, 실제로 최소한의 구성요소만을 사용해 문제를 해결함
  • 단순한 해결책을 추구할 때, 새로운 요구 사항이 발생할 때에만 점진적으로 확장해나가는 YAGNI(You Aren't Gonna Need It) 원칙을 핵심 설계 철학으로 삼을 수 있음
  • “단순함”의 정의에 대해 논란이 있지만, 컴포넌트 수가 적고 내부 연결이 느슨하며 안정적인 시스템이 가장 단순함에 가까움
  • 과도한 확장성 집착은 코드베이스를 유연하지 못하게 만들기 때문에, 실제 요구사항에 충실한 단순한 설계가 장기적으로 더 유리함

가능한 가장 단순한 일의 추구

소프트웨어 시스템을 설계할 때는 “가능한 가장 단순한 일”을 하는 것이 중요함. 이 접근법은 버그 수정, 기존 시스템 유지보수, 신규 아키텍처 설계 등 거의 모든 상황에 적용 가능함. 많은 엔지니어가 “이상적인” 시스템, 즉 잘 조직되고, 거의 무한히 확장 가능하며, 깔끔하게 분산된 구조를 꿈꾸지만, 실제로는 현 시스템을 깊게 이해한 후 가장 쉬운 해결책을 선택하는 것이 더 효과적임.

단순함의 저평가

  • 시스템 설계에는 앱 서버, 프록시, 데이터베이스, 캐시, 큐 등 다양한 도구 사용 능력이 필요함
  • 주니어 엔지니어일수록 여러 기술을 사용해 복잡한 구조를 만들고 싶어하지만, 진정한 숙련도는 오히려 불필요한 것을 줄이는 데에 있음
  • 뛰어난 소프트웨어 설계는 밋밋해 보이며, 오히려 문제를 생각보다 쉽게 풀 수 있다는 인상을 줌
  • 예를 들어, Unicorn과 Rails REST API는 Unix 기본 기능을 활용해 최소한의 구조로 핵심 보장(격리, 확장, 복구 등)을 실현하여 설계적으로 훌륭함

단순하게 구현하는 사고 방식

  • 예를 들어 Golang 애플리케이션에 rate limiting 기능을 추가할 때, Redis 같은 외부 스토리지를 쓸 수도 있지만, 꼭 필요한 경우가 아니라면 메모리 내 카운트 등 더 단순한 방법을 먼저 시도할 수 있음
  • 단순한 방법으로 충분하다면 무거운 인프라 추가를 미룰 수 있음
  • 실제로 새로운 요구가 등장할 때에만 시스템을 확장하는 점진적 개발 전개가 가능함
  • 이는 YAGNI 원칙을 설계의 최우선으로 두는 접근임

단순함의 함정과 현실적 한계

1. Big Ball of Mud 현상

  • 모든 요구를 즉각 해결하다 보면 복잡하고 유지보수 어려운 “진흙 뭉치(big ball of mud)” 코드베이스로 전락할 위험 있음
  • 그러나 즉흥적 수정(hack)은 단순함이 아니라 오히려 이해와 유지에 더 많은 복잡성을 초래함
  • 정말로 단순한 해결책을 찾으려면 많은 방법을 비교하고 실제로 체계적인 엔지니어링을 수행해야 함

2. 단순함의 정의

  • “단순함”이 무엇인지에 대한 동의가 쉽지 않음
  • 대체로 단순한 시스템은 이동 부품(동작 요소) 이 적고, 컴포넌트 간 연결이 느슨하며, 인터페이스가 뚜렷
  • 실 예시: Unix 프로세스와 Unicorn은 메모리를 공유하지 않아 단순성이 높으며, Puma나 Redis와 비교 시 내부 연결성이 더 낮음
  • 선택이 애매할 때는, 더 적은 유지 관리가 필요한 쪽이 단순하다고 봄

3. 확장성 집착에 대한 비판

  • “단순한 방법”은 대규모 트래픽에 적합하지 않을 수 있음
  • 하지만 미래의 급격한 규모 확장에 맞춰 미리 복잡하게 설계하는 것은 대개 쓸모없는 노력임
  • 대다수 코드는 실제로 2–5배 정도만 늘어날 트래픽만 대비하면 되며, 그 이상은 실제로 문제 발생 시 대응하는 것이 합리적임
  • 과도한 확장성 중심 설계는 코드 유연성을 해침, 필요 이상의 구조 분할은 특정 기능 구현을 오히려 어렵게 만들며, 복잡한 트랜잭션 관리까지 요구할 수 있음

결론

  • 시간이 지날수록 시스템의 미래 요구를 예측하는 역량에 비관적이게 변함
  • 실전에서는 현재의 시스템 상태를 정확히 파악하는 것만으로도 충분히 어렵고, 이것이 좋은 설계를 가로막는 주된 문제임
  • 소프트웨어 개발에는 크게 두 방식이 있음
    • 미래 요구를 예측하여 설계하는 방식
    • 현재 요구에 충실해 가능한 가장 단순한 일을 반복하는 방식
  • 후자가 실제로 더 효과적이며, YAGNI와 단순함 중심 사고가 장기적으로 좋은 설계를 만듦

부록: Hacker News 논의 및 용어 출처

  • 아키텍처 단순함이 규모가 커질수록 의미 없어진다는 의견에 대해, 저자는 오히려 대규모일수록 단순한 구조가 더욱 중요하다고 주장함(기능 상호작용의 복잡도에 대비)
  • “Do the simplest thing that could possibly work”라는 표현은 Ward Cunningham과 Kent Beck가 만들었음
Hacker News 의견
  • 나는 이런 접근법이 단순한 도메인에서는 잘 통할 수 있다고 생각함. 하지만 대형 테크 기업에서 오래 일한 후에도 요구되는 복잡성에 늘 놀라움을 느낌. 가장 단순한 비즈니스 문제도 1년 넘게 걸려 해결하거나, 수많은 엣지 케이스와 스케일 문제로 자주 깨짐. 단순성을 외치는 사람은 대규모 경험이 없던 것임. 10년 된 코드베이스를 참고해도, 고려해야 할 것이 너무 많아 리라이트도 종종 실패함. Chesterton's Fence 비유처럼, 무언가의 존재 이유를 모르면 함부로 없애지 않는 지혜가 필요함

    • 소프트웨어 엔지니어들이 서로 소통을 잘 못해서 발생하는 고전적인 오해라고 생각함. 기사 제목처럼 '가능한 가장 단순한 것'을 하라는 것임. 복잡한 문제에 복잡성은 피할 수 없지만, 불필요하게 더 복잡하게 만드는 실수를 조심하라는 의미임. 복잡성을 완전히 피하라는 게 아니라, 지나치게 복잡하게 만드는 습관을 경계해야 한다는 것임

    • 지적한 대로 복잡성이 도메인 자체 때문이 아닐 수도 있음. 소프트웨어 설계가 좋지 않아 생긴 문제일 수 있음. 의존성과 사이드이펙트로 가득하다면, 관심사 분리와 결합도 관리가 안 되었기 때문임. 리팩터링이 거의 불가능해지고, 조직 문화가 개선되지 않으면 리팩터 도중에 새로운 문제만 덕지덕지 더해짐. 그래도 관심사 분리와 단순한 조합만으로도 복잡한 문제 해결 가능함. 어렵긴 하지만, 시니어 개발자들이 이런 관점을 확고히 가져야 성공 가능성이 높아짐

    • 글쓴이가 GitHub의 스태프 엔지니어임을 언급하면서, 이 사람도 충분히 대규모 시스템 경험이 있다고 생각함

    • 레거시 시스템은 엣지에 존재함. 실제 시스템에서도, 다차원 공간에서 차원이 늘어날수록 점들이 경계 면(엣지)에 모이듯이, 실제 사용자들도 시스템의 한계점 근처에서 대부분 작업함. 이 모든 엣지를 최적으로 수용하는 것이 결국 기존의 오래된 시스템임

    • 이전 직장에서는 복잡성의 상당 부분이 실패하거나, 중간에 그만두거나, 미완성인 리팩터링이나 개선 시도에서 나왔었음. 이런 걸 초기에 방지했다면 더 단순한 시스템을 물려받았을까 자주 궁금했음. 리팩터와 개선을 아예 하지 말라는 게 아니라, 확실히 100% 유스케이스를 커버하도록 계획하고, 예산과 마일스톤 확보 뒤 점진적으로 개선되도록 보장해야 한다고 생각함

  • "가능한 가장 단순한 것"이란 표현의 기원을 꼭 밝혔으면 좋았을 것임. 이 문구는 위키의 발명가 Ward Cunningham과 Kent Beck이 함께 작업하며 80년대 후반에 자주 썼던 원칙임. 둘이 코딩하면서 서로 계속 이 원칙을 일깨워주었고, 이후 발표나 글쓰기에서 중요한 주제가 됨. 닫힌 문 예시처럼, 단순해 보이지만 상황에 따라 그 "단순함"이 다르다는 지점을 이 기사에서도 언급함. 단순한 해결책을 찾는 게 항상 단순하지 않다는 것임. 이 방식은 기술 부채를 남길 수 있다는 자각도 있었지만, 일단 코드를 동작시키는 게 우선순위였음. 개인적으로는 이번 글에서도 기술 부채 측면이 좀 더 나왔으면 좋겠다고 생각함

    • Kent Beck은 이후 익스트림 프로그래밍(Extreme Programming)을 공식화함. 이 방법론은 요구사항이 바뀔 때마다 단순한 시스템이 자연스럽게 진화할 수 있도록 돕는 실천법의 모음임

    • 나는 이 표현을 동료한테 듣고 삶의 좌우명처럼 사용하는 걸 알았지만, 워드 커닝햄이 원조인 줄은 몰랐음. 표현이 너무 널리 쓰이니 원작자를 아무도 모르는 정도가 최고의 영예인 듯함

    • Wiki를 언급한 게 흥미로웠음. 예전 직장에서는 Lotus Notes로 프로젝트를 관리했는데, 기본적으로 문서가 언제 변경됐는지 하이라이트 해줘서 유용했음. 그다음 프로젝트에서는 Wiki만 썼는데, 바뀐 문서를 한눈에 못 알아봐서 사실상 쓸모가 없어졌음. 단순하긴 했지만 너무 단순해서 오히려 실용성이 떨어졌음

  • "동작한다"의 정의를 두고 커리어 내내 가장 논쟁이 많았음. "동작한다고 해서 망가지지 않은 건 아니다"라는 말은 직접 무언가를 고쳐본 사람들에게는 직관적으로 와닿음. 수리공들은 깨진 연장으로 대충 고치다 결국 바꾸려고 마음먹는 반면, 개발자들은 '고쳐야 한다'는 필요성을 잘 느끼지 못하는 것 같음

    • 내 커리어에서 가장 힘들었던 시기는 프로토타입을 좋아하는 팀이 있던 회사였음. 그 팀은 빠르게 개념증명만 만들고, 임원이랑 데모만 하고 바로 배포했음. 그러면 임원들은 '이렇게 빠르게 완성된 거면 곧바로 배포 가능하다'고 착각함. 이후 담당 팀이 코드를 열어보면 엔드투엔드 보안, 검증, 오류 처리 등 반드시 필요한 것들이 다 빠져 있었음. 결국 처음부터 다시 만들어야 했고, 임원들은 배포팀이 무언가 쓸데없이 복잡하게 만드는 거라고 오해했음

    • "프로그램이 동작하는 것만으로는 충분하지 않음. 올바른 이유 때문에 동작해야 함"이라는 인상적인 인용을 어딘가에서 봤음. 본질적으로 같은 메시지임

    • 이런 대화는 직업적으로 중요한 부분임. 어떤 시스템이 원하는 출력을 낼 수 있다는 의미에서 "동작한다"고 할 수는 있지만, 신뢰성이나 비용 면에서 여전히 실패한다고 볼 수도 있음

    • 내가 맡은 일의 '동작한다' 정의는, 고용주가 자원(내 시간)을 어디에 투입할지에 따라 달라짐. 품질 향상에 시간을 써도 되는 상황이면 최선을 다함. 반대로 단순히 목표치 달성이나 체크 리스트만 바란다면 거기에 맞춰 일함. 뭐든 측정하는 대로 결과가 나온다고 생각해서 조언은 할 수 있어도 결정권은 내게 없음

  • 이런 조언의 아이러니는, 실제로 잘 적용할 수 있는 사람은 이미 경험이 풍부한 전문가라는 점임. 예를 들어 '가장 단순한 것'이 뭔지 어떻게 알 수 있을지, 그게 진짜 될지 어떻게 판단하는지. 나는 최근에 직접 만든 XLSX 임포터에서 XML 네임스페이스 처리 실수를 겪었고, 실제로 Excel이 항상 기본 네임스페이스만 쓴다는 가정 때문에 문제 생겼음. 너 나중에 가서 네임스페이스 딴 파일을 받았더니 바로 깨짐. 그냥 접두사만 지우고 처리하면 단순하겠지만, 내 미래를 위해 4시간 들여 파서 전체를 네임스페이스 친화적으로 다시 짰음. '가장 단순한 것'을 한다는 게 실제로 그렇게 쉽지 않고, 경험이 많을수록 좀 더 잘 판단할 수는 있음. 근데 그 정도 경험이 되면 이런 조언 자체가 필요 없다고도 생각함

    • 이런 조언이 적용되기 어려운 이유에 대해 글 본문에서도 언급했다고 생각함. '가장 단순한 해결책을 찾으려면 여러 접근법을 고려해야 하고, 결국 엔지니어링적 사고가 필요함'이라는 점이 핵심임

    • 우리는 회사에서 "잘못된 방향으로 코드 추가하지 말자"는 원칙을 둠. 부분 구현이어도, 나중에 발전시키기 좋은 방향으로만 코딩하도록 함. KISS이지만, 절대 편법을 허락하지 않음

    • 나는 '전환이 가장 쉬운 것'을 기준으로 단순함을 판단함. 복잡한 추상화나 인프라에 의존하지 않는 단일 서비스가 결국 전환이 쉬움. 읽는 사람이 바로 이해할 수 있고, 인수 인계와 디버깅도 수월함. 다만 추상화가 필요할 때는 반드시 넣고, 인프라가 꼭 필요할 때는 추가함. 중요한 것은, 코드를 넘겨줄 때 설명이 가장 쉬운 구조인가 항상 고민함. 나는 예전에는 최대한 전체를 추상화/서비스별 분리/설정기반 등으로 짜고 코드 거의 없게 만드는 걸 추구했지만, 실제로 전환이나 인수 인계가 완전히 실패했음. 이제는 꼭 필요할 때만 구조를 복잡하게 하고, 기본은 직관적인 단순함을 유지함. 이게 결국 신규 인원 온보딩이나 버그 수정, 실제 전환에 모두 이로움을 줌

    • AI vibecoding도 비슷함. 경험과 노하우가 늘수록 적합한 태스크 선정과 에이전트 관리가 쉬워짐

    • "가장 단순한 것"이란 편법이나 급한 땜질이 아니라는 점을 많은 사람들이 놓치는 것 같음. 단순한 방법일수록 사실 더 많은 고민과 시스템 이해가 필요하고, 글 서두에서 말한 것도 그 지점임. 많은 사람들이 제목만 보고 본인의 불만을 쏟아낸 듯함

  • 일반적으로 이런 식의 원칙이나 강한 주장을 듣는 순간 경계심이 생김. 소프트웨어 개발에 대해 뭔가 보편적인 정답이 있는 것처럼 말하면 사실 잘 모르는 경우가 많음. 진짜 경험 많은 개발자의 결론은 소프트웨어는 어렵고 신중함이 필요하다는 것임. 절대 만능 답은 없음. 열린 사고와 배려가 필요함

    • 단순함(즉, 복잡성의 역방향)은 소프트웨어 설계 대안을 비교할 때 거의 최우선 기준임. 그 이유는 결국 사람이 기획, 동의, 구현, 유지보수해야 하기 때문임. 하지만 단순함을 판단하는 건 너무 어렵고, 업계 평균 엔지니어는 이런 판단을 신뢰할 수 없음. 게다가 "단순함"이란 주장 자체가 무의미한 유행어 비슷하게 퍼져서, 제대로 된 주장에 "이게 더 단순하다"며 반박으로만 쓰이는 모습도 많음. 팀장이 이런 이슈를 잘 잡아내야 하는데, 점점 팀장 역량이 신뢰 못 할 정도로 낮아지고 있어서 더 힘들어짐

    • 기사에서도 인상 깊은 구절이 있었음. 진정한 달인은 '더하는 것'이 아니라 '덜하는 것'을 알고, 초보자는 동작이 많고 화려하지만, 달인은 적게 움직이고 결정적인 한 방만 쓰는 장면처럼 말임

    • 글을 읽으면서 초반에 약간 짜증도 났었지만, '편법'은 또다른 복잡성만 추가하기 때문에 시행착오의 본질을 잘 짚었다고 생각함. 문제는 이런 원칙이 경영진 명령처럼 과잉 적용될 때, 복잡한 문제에 너무 단순히 대응하려다 지식 전수도 힘들고 나중에 더 복잡한 수습만 남게 되는 경우임. 반대로, 필요 이상으로 복잡해지는 이유는, 계속되는 임기응변/편법에 물려 있다가, 한 번에 잡으려다 이번엔 너무 과하다는 것임. 결국 개발자는 회의에 적극적으로 개입해서 애초에 현명한 결정을 유도해야 함

    • 나는 이게 경고등일 정도까지는 아니라고 생각함. 불필요한 복잡성은 매일매일 늘어나기 때문에, 단순함을 지키자고 주장할 필요가 꼭 있음. 디자이너, 제품 관리자, 심지어 고객, 아키텍트까지도 본능적으로 복잡성을 추가하려고 하거든

    • 네 주장도 공감하지만, 결국 "모든 것은 트레이드오프" 아님 "공짜 점심은 없다"는 식으로 귀결된다는 점에도 주목하겠음. 어떤 일반론도 현장 경험의 집대성이므로 완전히 없앨 수 없는 부분임. 문제는, 실용적인 컨셉이 어느 순간 과잉 소문/종교처럼 변질돼서 폴더명 논쟁만이 남는 경우임

  • 스타트업(Seed~Series C)에서 0-1 시스템을 여럿 만들면서 체화한 원칙이 있음. "단순함이 곧 견고함"임. 초기 설계나, 기존 시스템 개선도 너무 과도하게 설계하게 되기 쉬움. 고객 요구는 계속 진화하고, 미래 요구를 예측한다고 해도 결국 빗나갈 수밖에 없음. 단순함은 단순히 오류를 줄이는 것뿐 아니라, 쉽게 구조를 바꿀 수 있는 기반이 된다고 생각함. 가능한 X, Y, Z를 준비하되, 미래 확장성과 여지를 주기 위해 "가장 단순한 것"을 만드는 방향을 추구함. 복잡성은 필연적으로 제약을 늘리고, 시간이 지나면서 쌓이면 쌓일수록 스택이 더 약해짐

  • "이상적인 시스템"을 설계하려는 시도를 어느 정도 해봐야, 결국 '가장 단순한 것'에 도달할 수 있다고 생각함. 읽기 쉽고, 변화 주기 쉬운 시스템을 만드는 데도 많은 노하우가 필요함. 진정으로 "단순한" 개선 역시 경험과 깊은 이해에서 나온다고 봄

  • Gall's law와 맥락이 같음. 이 이론에 따르면, 제대로 동작하는 복잡한 시스템은 항상 단순한 시스템에서 시작해서 점진적으로 복잡성이 추가된 경우임. 처음부터 복잡하게 만든 시스템은 잘 안 됨. 그래서 가장 단순한 시스템을 먼저 만들고, 요구사항에 맞춰 점점 복잡성을 더해야 함

    • 그럼 언제 멈춰야 함? 복잡성의 '최종 보스' 혹은 임계치는 있는지 궁금함
  • 글의 취지에는 동의하지만, 클라우드 인프라의 등장으로 '단순함'의 정의가 변화했다고 생각함. 과거에는 "단순하지만 확장성 없는 것" vs "복잡하지만 확장성 있는 것"의 구도였지만, 지금은 그렇지 않음. 인메모리 rate-limiting 솔루션은 싱글 서버에서는 단순하겠지만, 서버가 두 대만 돼도 바로 분산상태 문제가 되어버림. 반면 DynamoDB나 ElastiCache와 같은 managed service는 싱글 노드건 1000대건 단일 진실원이 되어 복잡성을 크게 줄여줌. '단순한 시스템이 견고하다'는 관점에서 보면 managed 서비스를 쓰는 게 더 근본적으로 단순하다고 할 수 있음. 데이터 손실, 분산 상태 관리 등 반복적 문제를 사라지게 해주기 때문임. 이제 '가장 단순한 것'의 정의는 직접 관리 없는 managed service를 잘 활용하는 것으로 변한 듯함. 요즘은 외부 의존성 회피보다는, 격리된 검증 시스템을 효과적으로 레버리지해서 복잡성 최소화하는 게 오히려 시간과 비용을 절약한다고 봄

    • 이건 클라우드에만 해당하는 현상은 아니라고 봄. 단일 서버에서조차 flat file, sqlite, postgres 등 다양한 스토리지 선택을 두고 같은 논의를 할 수 있음. 오늘날에는 비교적 적은 복잡성만 더하면 매우 큰 기능을 쓸 수 있게 해주는 소프트웨어가 엄청나게 많다는 게 현실임. 물론 모든 선택에는 트레이드오프가 있으니, 판단력은 필수임. 처음부터 무조건 managed 서비스(Amazon 등)를 고르는 게 꼭 답은 아님. 실제로 규모에 맞지 않는 DynamoDB 채택에 대한 후회 사례도 여러 번 들었음
  • "가능한 한 단순하게, 그러나 그 이하로 단순하게 만들지 말라"는 명언에 공감함. 항상 이 원칙을 따르려고 하지만, 최신 기술을 잘 몰라서 필요 없는 복잡성을 놓치고 있는 건지, 아니면 불필요한 복잡성에 다들 빠지고 있는 것인지 늘 고민임. 실전 프로젝트에서 직접 써보지 않으면 진짜 쓸만한지 배우기도 어렵고, 반대로 자기 학습만을 위해 실전에 최신 도구를 억지로 넣는 건 팀에도 폐를 끼친다는 걸 봤음

    • 비슷한 악몽을 겪고 있음. 항상 최신 소프트웨어에 관심 많은 윗사람 때문에, 의미 있을지 모를 툴을 실전에 검토해야 함. 실적과 무관하게 주마다 그런 탐색을 계속 하라고 하니 부담임

    • 실제론 가장 간단한 방법으로 동작하게 해보고(필요하면 수작업이라도), 필요한 순간이 올 때만 전체 기능을 추가하는게 맞다고 생각함. 처음에 모든 걸 자동화/툴화해서 공연히 시간 낭비했다 해도, 나중에 왜 필요한지 명확하게 알게 됐다는 경험이 더 중요함

    • 이 감정이 매우 익숙함. 나도 이런글에 항상 공감하고 단순함을 실천하려 노력하지만, 그게 정말 현명함과 실용성인지, 아니면 단순히 경험/실력이 부족한 건지 늘 헷갈림

    • 이것 때문에 '이력서 중심 개발'로 빠질 수 있어 정말 조심하려고 노력함