홈으로 돌아가기

Anders Hejlsberg의 강의: 소프트웨어 아키텍처, TypeScript, C#

C#와 TypeScript의 창시자인 Anders Hejlsberg로부터 소프트웨어 설계의 핵심 원칙을 배우세요: 빠른 피드백, 스케일링, 오픈소스, 개발에서의 AI.

Anders Hejlsberg: 소프트웨어 설계의 핵심 원칙과 개발자를 위한 강의
Advertisement 728x90

앤더스 헤일스버그의 통찰: 확장성과 지속성을 갖춘 소프트웨어 아키텍처 구축 원칙

C#과 TypeScript 같은 상징적인 프로그래밍 언어의 설계자이자 Turbo Pascal과 Delphi의 창시자인 앤더스 헤일스버그는 수십 년간 소프트웨어 개발 접근 방식을 형성해 왔습니다. 그의 경력은 단순히 성공적인 제품을 만드는 것을 넘어, 시스템이 시간의 시험과 확장을 견딜 수 있게 하는 원칙에 대한 끊임없는 성찰의 연속입니다. 그의 작업을 깊이 분석해 보면 장기적인 진화가 가능한 모든 복잡한 시스템을 설계하는 데 적용할 수 있는 보편적인 패턴을 발견할 수 있습니다. 수백만 명의 개발자를 위한 핵심 도구를 만들고 발전시키면서 다듬어진 이 교훈들은 피드백 속도부터 인공지능의 역할, 그리고 개방형 협업의 중요성에 이르기까지, 끊임없이 변화하는 기술 환경 속에서도 여전히 유효합니다.

1. 빠른 피드백 — 생산성의 기반

앤더스 헤일스버그의 초기 경험은 혹독한 제약 속에서 형성되었습니다. 64KB 메모리 컴퓨터 시대에는 스스로를 정당화하지 못하는 추상화는 설 자리가 없었습니다. 그는 그런 환경에서 개발자는 "모든 것을 머릿속에 담고" 있을 수 있었고, 핵심 요구사항은 코드를 작성한 후 즉시 실행하는 것이었다고 회상합니다.

"코드를 입력하면 바로 실행하고 싶었습니다." — 앤더스 헤일스버그.

Google AdInline article slot

Turbo Pascal의 영향은 Pascal 언어 자체보다는 피드백 루프를 획기적으로 단축했다는 점에 있었습니다. 편집, 컴파일, 실행, 디버그, 반복의 모든 과정이 디스크 접근이나 긴 대기 시간 없이 이루어졌습니다. 이러한 접근 방식은 개발자의 시간과 주의력을 절약하여 더욱 효율적으로 작업할 수 있게 했습니다.

이와 동일한 아이디어는 형태는 다르지만 수십 년 후 TypeScript에서 구현되었습니다. 언어 자체는 가치의 일부일 뿐입니다. TypeScript의 이점 중 상당 부분은 강력한 도구에 있습니다. 점진적 타입 검사, 빠른 부분 결과, 그리고 매우 큰 코드베이스에서도 즉시 반응하는 언어 서비스가 그것입니다.

여기서 실질적인 교훈은 매우 중요합니다. 개발자는 도구를 선택할 때 이 원칙을 직접 적용할 수 있습니다. 빠른 피드백은 근본적으로 행동을 변화시킵니다. 오류가 빠르게 드러나면 개발자는 실험에 더 적극적이고, 리팩토링에 더 자신감을 가지며, 문제가 발생한 시점에 더 가깝게 문제를 발견합니다. 반대로 피드백이 느리면 팀은 복잡한 규칙, 임시방편, 복잡한 프로세스로 보완해야 합니다. 언어, 프레임워크 또는 내부 도구를 선택할 때 피드백 속도는 매우 중요합니다. 코드를 작성하고 그 결과를 이해하는 데 걸리는 시간을 단축하는 도구는 신뢰를 얻습니다. 강력하더라도 지연을 추가하는 도구는 종종 외면받기 마련입니다.

Google AdInline article slot

2. 소프트웨어 확장성: 개인적 선호 포기하기

헤일스버그가 개인 작업에서 팀을 이끄는 역할로 전환했을 때, 특히 Delphi 시대에 가장 어려웠던 점은 기술적인 변화가 아니라 개인적인 선호를 포기해야 한다는 것이었습니다. 그는 팀 개발에서 "자신이 선호하는 방식으로 일이 진행되지 않는다는 것을 받아들여야 합니다. 그것을 고쳐도 행동은 변하지 않을 것입니다."라고 깨달았습니다.

이 접근 방식은 언어 개발을 훨씬 넘어 적용됩니다. 여러 팀에 걸쳐 확장해야 하는 모든 시스템은 개인적인 선호에서 공유된 표준으로 전환해야 합니다. 목표는 "내가 작성할 코드"가 아니라 "많은 사람이 이해하고 유지보수하며 발전시킬 수 있는 코드"가 됩니다.

C#은 이상적인 "백지 상태" 개념으로 등장한 것이 아니라, 상충되는 요구사항의 결과물로 탄생했습니다. Visual Basic 개발자들은 단순함을 원했고, C++ 개발자들은 강력함을 필요로 했으며, Windows는 실용주의를 요구했습니다. 그 결과는 이론적으로 완벽한 시스템이 아니라 사람들이 효과적으로 사용할 수 있는 언어였습니다. 프로그래밍 언어는 완벽하게 설계되었기 때문에 성공하는 것이 아니라, 팀이 실제로 작업하는 방식을 수용하고 효과적으로 협업할 수 있도록 지원하기 때문에 성공합니다.

Google AdInline article slot

3. TypeScript가 JavaScript를 대체하지 않고 확장한 이유

TypeScript는 JavaScript가 다른 어떤 언어도 달성하기 어려운 규모를 이루었기 때문에 등장했습니다. 브라우저가 진정한 크로스 플랫폼 런타임이 되면서, 팀들은 동적 타이핑이 효과적으로 지원하는 수준을 훨씬 뛰어넘는 애플리케이션을 개발하기 시작했습니다. 이를 해결하려는 초기 시도들은 종종 매우 급진적이었습니다. 일부 팀은 정적 분석 및 리팩토링 도구에 접근하기 위해 다른 언어를 JavaScript로 컴파일하기도 했습니다.

이러한 접근 방식은 헤일스버그에게 결코 만족스럽지 않았습니다. 개발자들에게 이미 깊이 투자한 생태계를 포기하라고 말하는 것은 비현실적이었습니다. 2012년에 완전히 새로운 언어를 만드는 것은 컴파일러뿐만 아니라 에디터, 디버거, 리팩토링 도구, 그리고 가장 중요하게는 커뮤니티의 채택에 수년간의 투자를 필요로 했을 것입니다.

대신, TypeScript는 다른 길을 택했습니다. JavaScript를 확장하여 그 단점을 계승하면서도 대규모 프로젝트 개발을 크게 단순화했습니다. 이것은 이념적인 결정이 아니라 순전히 실용적인 결정이었습니다. TypeScript는 개발자들이 기존 도구, 라이브러리, 정신 모델을 포기하도록 강요하는 대신, 이미 직면하고 있던 제약 조건 내에서 작동했기 때문에 성공했습니다.

궁극적으로, 핵심 교훈은 타협의 필요성입니다. 기존 워크플로우를 수용하는 개선 사항은 더 쉽게 확산되는 반면, 완전한 교체를 요구하는 개선 사항은 거의 추진력을 얻지 못합니다. 실제로, 상당한 진전은 종종 처음부터 시작하려 하기보다는 이미 의존하고 있는 기존 시스템을 발전시킴으로써 달성됩니다.

개방성과 변화에 대한 적응

4. 가시성은 오픈 소스 성공의 핵심

TypeScript는 하룻밤 사이에 센세이션을 일으킨 것이 아닙니다. 초기 릴리스는 공식적으로 오픈 소스였지만, 개발은 주로 비공개로 진행되었습니다. 이는 2014년 프로젝트가 GitHub로 이전되면서 바뀌었고, 개발 프로세스는 완전히 개방되었습니다. 기능 제안은 풀 리퀘스트를 통해 이루어졌고, 타협점은 공개적으로 논의되었으며, 작업 우선순위는 커뮤니티 피드백을 기반으로 결정되었습니다.

이러한 변화는 의사결정 과정을 투명하게 만들었습니다. 개발자들은 무엇이 릴리스되었는지뿐만 아니라, 특정 결정이 왜 내려졌고 다른 결정은 왜 아니었는지도 알 수 있었습니다. 팀에게도 이는 작업 우선순위를 정하는 접근 방식을 변화시켰습니다. 무엇이 가장 중요한지 추측하는 대신, 개발자들이 중요하게 생각하는 문제를 직접 관찰할 수 있었습니다.

효과적인 오픈 소스 프로젝트는 단순히 코드를 공개하는 것 이상을 합니다. 의사결정 과정을 가시화하여 기여자(contributor)들이 우선순위와 트레이드오프를 이해하도록 돕고, 궁극적으로 신뢰를 구축하며 더 활발한 커뮤니티 참여를 촉진합니다.

5. 구현 언어로서 JavaScript에서 벗어날 필요성

수년 동안 TypeScript 컴파일러는 자체 호스팅 방식이었습니다. 즉, TypeScript로 작성되어 JavaScript로 실행되었습니다. 이는 강력한 브라우저 내 도구를 제공하고 실험을 단순화했습니다. 그러나 시간이 지남에 따라 한계가 분명해졌습니다. JavaScript는 단일 스레드이며, 공유 메모리 동시성을 지원하지 않고, 객체 모델은 유연하지만 리소스 집약적입니다. TypeScript 프로젝트가 커지면서 컴파일러는 사용 가능한 컴퓨팅 리소스의 상당 부분을 활용하지 못했습니다.

팀은 더 이상의 최적화만으로는 부족한 지점에 도달했습니다. 그들은 다른 실행 모델이 필요했습니다. 논란의 여지가 있는 결정은 컴파일러를 Go로 포팅하는 것이었습니다. 이것은 처음부터 다시 작성하는 것이 아니었습니다. 목표는 '의미론적 충실도(semantic fidelity)'였습니다. 새로운 컴파일러는 특이점과 엣지 케이스를 포함하여 이전 컴파일러와 정확히 동일하게 동작해야 했습니다. Rust는 인기가 많았지만, 소유권 제약과 순환 데이터 구조의 광범위한 사용으로 인해 상당한 재설계가 필요했을 것입니다. Go의 가비지 컬렉션과 TypeScript와의 구조적 유사성은 성능과 병렬성을 향상시키면서도 기존 동작을 보존할 수 있게 했습니다.

그 결과, 네이티브 실행과 병렬 처리 모두에서 성능이 크게 향상되었습니다. 더 중요한 것은 커뮤니티가 컴파일러의 동작을 다시 배울 필요가 없었다는 점입니다. 때로는 가장 책임감 있는 선택이 가장 야심 찬 선택이 아니라, 동작을 보존하고 혼란을 최소화하며, 아무리 점진적인 최적화를 해도 극복할 수 없는 강력한 제약을 제거하는 선택일 수 있습니다.

개발의 미래와 협업의 역할

6. AI 시대에는 생성보다 제약이 더 중요합니다

앤더스 헤일스버그는 AI를 위해 주로 설계된 프로그래밍 언어라는 아이디어에 회의적입니다. 그는 대규모 언어 모델이 이미 널리 접한 언어에서 가장 잘 작동하며, 이는 자연스럽게 JavaScript, Python, TypeScript와 같은 거대한 생태계를 선호한다고 지적합니다.

그러나 AI는 도구 측면에서 판도를 바꿉니다. 전통적인 IDE 모델은 개발자가 코드를 작성하고 도구를 사용하여 프로세스를 지원한다고 가정했습니다. 점차 이 관계는 역전되고 있습니다. AI 시스템이 코드를 생성하고, 개발자는 이를 검토하고 수정합니다. 타입 검사기 및 리팩토링 엔진과 같은 결정론적 도구는 미묘한 오류를 방지하는 '가드레일' 역할을 합니다. 이러한 도구의 가치는 정밀성과 제약에 있습니다. AI 시스템이 의미 있는 질문을 하고 신뢰할 수 있는 답변을 받을 수 있도록 정확한 의미론적 정보를 제공해야 합니다.

위험은 AI 시스템이 나쁜 코드를 생성하는 것이 아니라, 프로젝트 코드베이스의 모든 미묘한 차이를 고려하지 않은 그럴듯한 코드를 생성할 수 있다는 점입니다. 개발자에게 이는 초점을 바꿉니다. 궁극적으로 AI 지원 워크플로우에서 가장 가치 있는 도구는 이를 적절하게 제약하는 도구입니다. 강력한 타입 시스템, 견고한 리팩토링 도구, 정확한 의미론적 모델은 필수적인 조력자가 됩니다. 이러한 도구는 AI 시스템의 출력을 맹목적으로 신뢰하기보다는 효과적으로 검사, 검증 및 수정할 수 있는 구조를 제공합니다.

7. 개방형 협업의 결정적인 중요성

자금 조달 및 유지보수의 어려움에도 불구하고, 헤일스버그는 개방형 협업에 대해 낙관적입니다. 한 가지 핵심 이유는 '기관 기억(institutional memory)'입니다. 수년간의 논의, 내려진 결정, 도달한 타협점은 여전히 검색하고 볼 수 있습니다.

이러한 역사는 비공개 이메일 체인이나 내부 시스템에서 사라지지 않습니다. 시스템이 어떻게, 왜 진화했는지 이해하고자 하는 모든 사람이 접근할 수 있습니다. 그는 "우리 프로젝트에는 12년간의 역사가 기록되어 있습니다. 누군가 논의가 있었다는 것을 기억한다면, 우리는 보통 그것을 찾을 수 있습니다. 맥락은 이메일이나 비공개 시스템으로 사라지지 않습니다."라고 설명합니다. 이러한 접근성은 시스템이 진화하는 방식을 변화시킵니다. 설계 논의, 거부된 아이디어, 타협점은 개별 결정이 내려진 후에도 오랫동안 남아 있습니다. 나중에 프로젝트에 참여하는 개발자에게 이 공유된 맥락은 종종 코드 자체만큼이나 가치가 있습니다.

핵심 요약

  • 빠른 피드백은 생산성과 개발 품질의 핵심 요소이며, 실험과 신속한 문제 식별을 가능하게 합니다.
  • 확장성을 위해서는 개인적인 선호를 버리고, 실제 팀 요구사항을 충족하는 공유되고 이해하기 쉬운 규칙과 실용적인 솔루션을 따라야 합니다.
  • 진화적 개발 (JavaScript를 위한 TypeScript처럼 기존 시스템을 확장하는 것)은 현재 워크플로우와 생태계를 존중하므로, 혁명적인 교체보다 종종 더 효과적입니다.
  • 오픈 소스 프로젝트의 프로세스 개방성은 신뢰를 구축하고, 의사결정의 투명성을 보장하며, 귀중한 기관 기억을 보존합니다.
  • 개발에 AI를 통합할 때는 생성된 코드의 "가드레일" 역할을 하는 정밀성과 제약(예: 강력한 타입 시스템)을 제공하는 도구에 초점을 맞춰야 합니다.

결론: 수십 년간 반복된 모델

수십 년간의 프로그래밍 언어 개발을 통해 동일한 주제들이 꾸준히 나타납니다.

  • 빠른 피드백은 아키텍처의 우아함보다 더 중요합니다.
  • 시스템은 많은 사람이 작성한 불완전한 코드를 고려해야 합니다.
  • 행동 호환성은 아키텍처의 순수성이나 이론적 이상보다 종종 더 중요합니다.
  • 가시적인 타협과 프로세스 투명성은 커뮤니티의 신뢰를 강화합니다.

이것들은 사소한 점이 아닙니다. 이는 도구가 사용자가 늘어남에 따라 적응하고 현실 세계의 시험을 견딜 수 있는지 여부를 결정하는 근본적인 결정입니다. 더욱이, 이들은 혁신의 기반이 되어, 이미 작동하는 것을 망가뜨리지 않고 새로운 아이디어를 도입할 수 있도록 보장합니다. 오래 지속되기를 바라는 도구를 만드는 사람들에게 이러한 기본 원칙은 어떤 혁신적인 기능만큼이나 중요합니다. 그리고 이것이 아마도 앤더스 헤일스버그의 가장 중요한 교훈일 것입니다.

— Editorial Team

Advertisement 728x90

다음 읽기