소프트웨어 아키텍처 배우기

1 hour ago 1
  • 소프트웨어 설계는 강의보다 실제 프로젝트에서 책임을 맡고 문제가 자기 일이 될 때 더 깊게 배워짐
  • Conway’s Law는 소프트웨어가 조직의 사회적 구조를 반복한다는 관점이며, 과학 코드와 산업 코드의 차이도 인센티브에서 생길 수 있음
  • rust-analyzer는 빠른 빌드, stable 지원, C 의존성 제거, 몇 초짜리 테스트로 고효율 기여자가 집중하기 쉽게 만듦
  • rust-analyzer는 독립 기능을 catch_unwind로 보호하고 PR 기준을 낮췄지만, 핵심 spine에는 훨씬 엄격한 품질 기준을 적용함
  • 실험적 구조는 장기 현실이 될 수 있으며, rust-analyzer도 LSP 아키텍처 프로토타입에서 또 하나의 컴파일러 유지로 이어짐

소프트웨어 설계는 실전에서 가장 잘 배움

  • 소프트웨어 설계는 공식 강의보다 실제 프로젝트에서 책임을 맡고 문제를 직접 해결할 때 더 잘 배워짐
  • 대학 설계 수업과 코스 프로젝트에서 “아키텍트” 역할을 맡았을 때보다, 두 번째 실전 프로젝트였던 IntelliJ Rust에서 설계 문제가 자기 일이 되면서 학습이 본격화됨
  • IntelliJ Rust에서는 몇 가지 실수가 있었지만 치명적이지 않았고, 그 과정에서 많은 것을 배울 수 있었음
  • 소프트웨어 엔지니어링은 호기심 있는 사람이 원리부터 생각하고 여러 글을 읽으며 익힐 수 있을 만큼 단순한 면도 있음

인센티브 구조와 Conway’s Law

  • Conway’s Law 는 소프트웨어가 그것을 만드는 조직의 사회적 구조를 반복한다는 관점임
  • 산업용 소프트웨어와 과학 코드의 차이는 소프트웨어 구축 지식 자체보다, 사람들에게 소프트웨어를 만들게 하는 인센티브 구조에서 비롯될 수 있음
  • “3개월 안에 논문을 내야 하는 PhD” 같은 상황은 과학 코드의 형태를 좌우하는 중요한 요인이 될 수 있음
  • 인센티브 구조에는 크게 두 가지 방식으로 대응 가능함
  • 프로젝트의 인센티브를 설계하거나 움직이기

    • 프로젝트의 인센티브 구조를 설계하거나 조정할 기회는 드물지만, 그런 기회가 생기면 영향이 커짐
    • TIGER_STYLE의 핵심은 규칙 목록 자체가 아니라, 그 규칙들이 좋은 선택이 되도록 만드는 사회적 맥락에 있음
  • 바꿀 수 없다면 제약에 적응하기

    • 인센티브 구조는 원하는 대로 주어지는 경우가 거의 없으며, 바꿀 수 없다면 그 구조에 맞춰 적응해야 함
    • 산업 소프트웨어 프로젝트에서도 “제대로 할 시간”은 거의 없고, 주어진 제약 안에서 가능한 최선을 해야 함

rust-analyzer에서 구조와 참여자를 맞춘 방식

  • rust-analyzer는 깊이와 폭을 모두 가진 프로젝트임
  • 깊은 측면에서는 컴파일러라는 성격 덕분에 뛰어나고 헌신적인 기여자를 끌어들일 수 있음
  • 넓은 측면에서는 고전적인 IDE가 목적별 특수 기능을 많이 갖고 있어, Rust를 배우는 사람이나 꾸준히 참여하기 어려운 주말 기여자가 자신의 불편을 해결하려고 한두 시간을 쓰기에 적합함
  • rust-analyzer가 rustc 빌드를 요구하지 않고, stable에서 빌드되며, C 의존성이 없고, 전체 테스트 스위트가 몇 초 안에 끝나도록 고집한 이유는 고효율 기여자를 끌어들이기 위해서였음
  • 빌드 시스템을 다듬어 사람들이 다른 것을 신경 쓰지 않고 borrow checker 작업에 집중할 수 있게 하려 했음
  • 주말 기여자를 끌어들이기 위해 rust-analyzer 내부는 여러 독립 기능으로 나뉘었고, 각 기능은 런타임에서 catch_unwind로 보호됨
  • 기능 PR의 기준은 “해피 패스가 동작하고 테스트가 있음”으로 낮췄고, 해당 코드가 크래시하더라도 받아들일 수 있다고 봄
  • 다만 두 조건이 필요했음
    • 품질 문제가 개별 기능 안에 격리되고 다른 부분으로 번지지 않아야 함
    • 런타임 크래시는 사용자에게 보이지 않아야 하며, 이를 위해 rust-analyzer 기능은 불변 스냅샷으로 동작하고 데이터를 오염시키지 못해야 함
  • 반대로 기능을 떠받치는 핵심 spine에는 훨씬 엄격한 품질 기준을 적용함

실험적 구조가 장기 현실이 되는 위험

  • 인센티브 구조를 고치기보다 적응할 때는 미래가 불확실하고, 대개 가장 불편한 방식으로 현실화될 수 있음을 조심해야 함
  • rust-analyzer의 원래 동기는 IntelliJ Rust 안에 병렬 컴파일러를 하나 더 작성하는 일을 피하고, LSP를 위한 더 나은 아키텍처를 프로토타입으로 검증해 그 배움을 rustc로 되돌리는 것이었음
  • 그래서 핵심부까지 포함해 코드가 매우 실험적이었음
  • 결과적으로 또 하나의 컴파일러를 유지하게 됨
  • 비슷하게 uutils 프로젝트도 Rust를 배우는 사람들의 주요 목적지로 시작해 Ubuntu의 coreutils 구현체가 됨

참고할 만한 자료와 책

  • 정답이 담긴 단일 책은 없으며, 실전이 필수 요소로 보임
  • Boundaries by Gary Bernhardt
    • 구체적인 조언이 탄탄하고, 더 상위 수준의 탐구를 촉발한 자료임
  • How to Test
    • 테스트의 중요성은 바로 이해했지만, 널리 인용되는 많은 테스트 조언이 실질적이지 않다는 점을 인정하고 실제로 작동하는 방식을 개념화하기까지 오래 걸렸음
  • ∅MQ guidePieter Hintjens의 글
    • Conway’s Law식 사고를 접하게 해준 자료임
    • rust-analyzer의 기능 개발 아키텍처는 optimistic merging을 적용한 형태임
  • Reflections on a decade of coding by Jamii
    • 매우 메타적인 내용을 다루며, 링크 모음의 첫 번째 항목으로 둘 만큼 훌륭함
  • Ted Kaminski 블로그
    • 존재하지 않는 책을 위한 노트라는 형식으로, 소프트웨어 개발에 대한 일관된 이론에 가장 가까움
  • Software Engineering at Google과 Ousterhout의 The Philosophy of Software Design
Read Entire Article