본문 바로가기

Books in Life/2009

소트웍스 앤솔러지(ThoughtWorks Anthology) - 소프트웨어 기술과 혁신에 관한 에세이


이번 10회 자바 컨퍼런스에서 안영회님에게 질문을 하고 받은 책입니다.

강연 도중 여러번 이 책에 관하여 언급을 하셔서 사서라도 봐야겠다고 생각하고 있었는데, 질문을 드려 무료로 받게 되었습니다. ;-)

깔끔한 표지부터 참 좋더라구요~
특히 엔터프라이즈 애플리케이션 아키텍처 패턴(Patterns of Enterprise Application Architecture)이란 유명한 책의 저자인 마틴 파울러(Martin Fowler)가 최고 책임 과학자(Chief Scientist)로 재직중인 소트웍스(ThoughtWorks)의 문화와 사상을 이해할 수 있는 계기가 되었습니다.

14개의 장은 각기 서로 다른 이야기를 일관되게 풀어내고 있습니다. Agile이란 공통된 화두속에서 소프트웨어의 각 측면에서 어떻게 효과적으로 Agile적인 방안을 적용할것인가에 대한 깊은 고민이 묻어나오는 책입니다.

사실 저는 Agile에 많은 기대를 가지고 있지 않은 사람중에 하나였습니다.
왜냐하면 방법론은 하나의 방침이며, 방침은 사람들이 적극적으로 수용하고 행동으로 옮겨야 제대로 실행될 수 있다고 생각하였기 때문입니다.

이런 측면에서 볼때 우리나라의 문화상 Agile은 여러모로 힘들다고 생각하여 왔습니다.
Java 컨퍼런스에서 안영회님의 강연과 이 책을 통하여 Agile을 새롭게 볼 수 있게 되었습니다. 가장 중요한것은 기업의 문화인듯 싶습니다.

한사람이 Agile적인 사고를 가지고 실천한다고 하더라도 여러 방면에서 받쳐주고 따라주지 않는다면 결코 쉽게 Agile적인 소프트웨어 개발이 이루어 지지 않을것 같습니다.

그런 면에서 소트웍스(ThoughtWorks)는 이러한 Agile적인 체계가 매우 잘 정립된 회사라고 생각합니다. 이 속에서 개발하시는 모든 분들이 부럽습니다. 개인적으로 마틴 파울러(Martin Fowler)의 Big Fan이라 더 그런것 같습니다.

이 책을 읽으면서 제 나름대로 중요하게 생각되는 부분은 다음과 같습니다.



2장 비즈니스 소프트웨어의 "마지막 한 단계" 해결하기 에서

소프트웨어 개발의 '마지막 한 단계'는 풀리지 않았다.'마지막 한 단계'란 소프트웨어 프로세스의 일부로서, 기능적 요구사항은 모두 만족하지만 아직 실전에 투입되어 비즈니스 가치를 만들어내지 않고 있는 단계를 일컫는다.

소프트웨어 개발자는 '마지막 한 단계'를 쉽게 생각하는 경향이 있는데, 일정 압박을 받는 상황에서 특히 그러하다. 하지만 '마지막 한 단계'는 비즈니스 소프트웨어 출시에 있어서 가장 중요한 단계이다.

기업은 소프트웨어가 창출한 비즈니스 가치를 보고 투자한다. 하지만 새 소프트웨어는 간혹 엄청난 재정적 재난의 상징으로 비춰지기도 하는데, 다음 중 한가지 상황이라도 발생하는 경우에 특히 그렇다.

  • 새 소프트웨어가 기업이 필요로 하는 만큼의 사용자 규모나 트랜잭션을 수용하지 못한다.
  • 새 소프트웨어가 기존 데이터베이스를 망친다.
  • 새 소프트웨어가 예측 불가능하게 오작동하거나, 기존 시스템까지 불안정하게 만든다.
  • 새 소프트웨어가 기업의 민감한 정보를 신뢰할 수 없는 업체 혹은 개인에게 노출시킨다.
  • 새 소프트웨어가 악의적인 사용자가 시도하는 허가되지 않은 행위를 허용한다.

오늘날의 Agile 소프트웨어 개발 프로젝트는 대략 다음과 같은 형태로 진행된다.
  1. 비즈니스 스폰서가 욕구(needs)를 파악한다.
  2. 비즈니스 스폰서가 프로젝트 예산을 승인한다.
  3. 개발부서가 사용자 스토리를 나열한다.
  4. 개발부서가 사용자 스토리를 구현한다.
  5. 비즈니스 스폰서가 구현된 사용자 스토리를 검수한다.
  6. 개발부서가 완성된 코드를 넘긴다.

Agile 소프트웨어 운동이 가장 크게 기여한 바는 소프트웨어 개발이 근본적으로 사회적 행위라는 인식을 알린것이다. 사람들 사이의 대화를 개선하면 소프트웨어도 개선될 것이다. 애자일 개발 방법론을 도입하는 과정에서 드는 노력중 많은 부분은 기존 조직의 사회적 구조를 분해하고 이를 더욱 효과적인 패턴과 실천법으로 교체하는 일에 쓰인다.

이점이 Agile의 확산을 힘들게 하는 요소라고 생각합니다.

지속적인 통합(Continuous Integration)과 테스트 주도 설계(Test-Driven Design)는 고품질의 소프트웨어를 빠르게 개발하고자 할 때 매우 유용한 도구이다.

Agile 방법론의 가치는 프로젝트에 소요되는 전체 시간을 줄여주고, 비즈니스 요구사항이 떠오른 시점에서부터 이것이 구현되어 업무에 적용되는 시점에서부터 이것이 구현되어 업무에 적용되는 시점 사이의 비용을 줄여주는 데에 있다.



3장 악당 소굴과 20개의 루비 DSL 에서

몇년전에 데이브 토마스가 자신의 블로그에 코드 카타(code katas)라는 표현에 대하여 쓴 적이 있다.

카타란 여러가지 서로 다른 방법으로 풀어볼 수 있는 작은 프로그래밍 문제들인데, 이를 풀어보면서 서로 다른 해법들이 어떻게 동작하는지 또 각 해법들 사이에 장단점은 무엇인지 살펴볼 수 있다.



4장 프로그래밍 언어의 울창한 숲 에서

명령형 언어는 종종 절차형(Procedural) 언어라고 불리기도 하는데 그 이유는 언어의 기본적인 구조화 매커니즘이 프로시저(Procedure)이기 때문이다. 하지만 명령형 언어와 절차형 언어라는 특성은 다른 것이기 때문에 앞으로도 이 둘을 명확히 구분해서 쓰는 것이 좋을 것 같다.

리스프(Lisp)는 동적 언어이기도 하다. 동적이란 특성은 어떠한 결정이나 계산이 수행되는 시점에 대한 것이다. 동적 언어에서 컴파일러가 하던 일 중 많은 부분을 실행 중에 처리한다. 따라서 "코딩, 컴파일, 테스팅 좌절, 다시 코딩" 이라는 정적 언어에서의 개발 주기가 동적언어에서는 "코딩, 테스팅, 좌절, 다시 코딩"으로 바뀐다.
소스코드는 컴파일이 없이 즉시 실행된다. CLR이나 JVM같은 가상 기계의 인가가 높아짐에 따라 이러한 구분이 좀 불분명해졌지만 동적 언어라는 범주 자체는 중요하다.


Java는 객체지향 프로그래밍 언어로 분류되는데 그 이유는 이 언어의 주요 구조화 단위가 객체이기 때문이다. 개념적으로 객체란 상태변수와 메소드의 묶음이다. 객체는 특정 클래스에 속하는데, 클래스는 자신에게 속한 객체가 가져야 할 상태와 메소드를 명시하고 있다. 같은 클래스에 속한 객체들은 서로 관련되어 있기는 하지만 서로 독립적인 단위이다. 어떠한 언어가 객체지향으로 갖춰야 할 필요충분 조건이 무엇인지에 대해서는 몇가지 경쟁 중인 정의들이 있지만, 거의 모든 정의가 상속(Inheritance)과 캡슐화(Encapsulation)를 포함하고 있다.

상속은 클래스들은 서로 연결시켜주는(따라서 객체들도) 하나의 방법이다. 캡슐화는 정보 은닉(Information hiding)을 구현하기 위한 방법이다. 다형성(Polymorphism)은 동일한 함수 호출이 객체 타입에 따라 서로 다른 동작을 하도록 만들어주는 기능이다.

강한 타입(Strongly Typed)은 오용되는 경우가 많다. 실행 중 타입 오류가 발생할 가능성이 있는 소스코드는 컴파일 되지 않도록 한다는 것이 강한 타입에 대한 일반적인 정의이다. 물론 이 설명은 타입 오류가 무엇인지에 대한 정의가 필요하다.



5장 다언어 프로그래밍 에서

Java 설계자들은 Java를 만들 때 훌륭한 결정을 하였다. 그것은 플랫폼으로부터 언어를 분리한 것이다. 그 결정이 개발자들에게 다언어 프로그래밍이라는 "지옥 탈출"카드를 준 셈이다.

이런 저런 솔루션을 하나의 언어에 쑤셔 넣으려던 시절은 끝나가고 있다. Java나 CLR과 같은 훌륭한 관리 런타임이 있기에, 더 나은 도구로 이들 플랫폼을 활용해야 한다.

다언어 프로그래밍은 중요한 작업을 맡던 기존 코드를 버리지 않고도 솔루션별로 맞춤 대응을 할 수 있게 해준다. 언어 개발은 이 두 플랫폼에서 넘처나고 있다.

개발자로서 작업에 더욱 알맞는 도구를 통하여 더 좋은 코드를 작성할 수 있도록 이와 같은 성장을 활용하는 방법을 배울 필요가 잇다.



6장 객체지향 생활 체조 에서

좋은 설계의 바탕에 있는 핵심 개념은 쉽게 알 수 있다. 예를 들어 보통 중요하다고 알고 있는 7가지 코드 품질 항목, 즉, 응집력, 느슨한 결합, 무중복, 캡슐화, 테스트가능성, 가독성, 그리고 촛점이 있다. 하지만 그런 개념을 실제로 펼치기란 어렵다. 캡슐화가 데이터, 구현, 타입, 설계, 또는 생성의 은닉을 가리킨다고 이해하는 것과 캡슐화를 잘 구현하는 코드를 설계하는 것은 전혀 별개의 문제이다.



7장 반복 관리자란 무엇인가? 에서

반복 개발 세계에서라면 누군가 팀을 지원하고, 고객과 잦은 대화를 촉진하고, 팀이 중요한 일에 집중할 수 있도록 유지해야 한다. 반복관리자는 팀 내에서 매끄러운 스토리 배분을 책임지고, 팀원에게 스토리를 할당하고, 기술 요건이 바뀌면 인원 교체도 권유한다.

프로젝트 내에서 적시(Just-in-Time)의사결정 개념은 새로운 것이 아니다.
도요타의 지식기반 공학으로 구현한 린 개발 시스템(Lean Development System)은 집합기반 동시공학(Set-Based Concurrent Engineering)이라 부르는 기법을 수년간 성공적으로 채용해왔다.

집합 기반 동시공학은 "반드시 결정해야 할 때까지 신중을 기하고 선택의 여지를 유지하려고 애써, 가능한 많은 정보를 얻고나서 결정하는 것이 서둘러 결정해 다른 선택의 여지를 조기에 없애는 것보다 빠르게 최적안에 도달하게 한다"라고 설명한다.

반복관리자는 전문적이고 책임감있는 환경을 지향해야 한다. 이러한 환경은 다음과 같은 고유한 행위나 특징을 보인다.
  • 자신을 존중하고 아울러 다른 팀원과 고객을 서로 존중한다.
  • 성공을 축하한다.
  • 실패를 배우는 기회로 취급한다.

반복관리자는 팀이 성공과 실패를 함께하는 하나의 응집력있는 집단이 되도록 힘쓴다.



9장 소비자 주도 계약: 서비스 진화 패턴 에서

서비스 지향 아키텍쳐(Service Oriented Architecture)는 조직으 민첩성을 높이고 변화에 드는 전반적인 비용을 절감한다. 고부가가치의 비즈니스 기능을 컴포넌트화함으로써, 재사용 가능한 서비스는 기능의 연결가 조율을 더욱 손쉽게 하여 핵심 비즈니스 프로세스를 만족시킨다. 서비스간의 의존성을 낮춤으로써 변화의 비용은 더욱 줄어들어 서비스는 변화나 불시의 사건에 대응할 수 있도록 빠르게 재구성되고 조율될 수 있다.

비즈니스는 SOA를 통하여 서비스 상호 독립적으로 진화할 수 있게 해야만 이러한 이점들을 십분 활용할 수 있다. 이런 독립성을 확보하는 방법으로 흔히 받아들여지는 것이 양식(Type)이 아닌 계약(Contract)을 공유하는 서비스 구축이다.

소비자 계약을 개입시켜 소비자와 메시지 교환시 개입시킨 소비자 계약을 준수하는 서비스는 "소비자 주도 계약(Consumer-Driven Contract)"이라고 하는 제공자 계약의 파생된 형태를 구현한다.

서비스 커뮤니티의 구성원간에 변경 비용을 분산할 수 있는 방법은 2가지이다.
  • 스키마를 수정하고 각 소비자가 검색결과를 정확히 검증하기 위하여 각자 사본을 갱신하도록 요청하는 것이다.
  • 두번째 오퍼레이션과 스키마를 새 소비자에게 노출하면 원래 오퍼레이션과 스키마는 기존 소비자들을 위하여 유지하는 것이다.

소비자 측 검증을 향상할 수 있는 한 방안은 수신 메시지의 문서 트리 축을 따라 패턴 표현식을 검증하는 것으로서, 스키마트론과 같은 구조적 트리 패턴 검증 언어를 사용하는 것이다.


소비자 계약은 개방성과 불안정성, 다중성과 비권위성, 제한적 안정성과 불변성의 특정이 있다.



10장 도메인 어노테이션 에서

소프트웨어가 다루어야 할 가장 복잡한 부분은 소프트웨어가 다루는 문제 도메인(Problem Domain)이라는 사실을 이해하게 되었다.

도메인 주도 설계(Domain Driven Design)의 영역이 도메인 객체지향적 모델(Object Oriented Model)을 다루고, 도메인 관점에서 표현되며, 소프트웨어 시스템의 심장부에 위치한다는 사실을 의미한다.데이터는 RDBMS에 저장되지만, 이 경우에도 데이터를 바라보는 관점은 도메인 객체가 된다.



11장 Ant 빌드 파일 리팩터링하기 에서

리팩터링은 시스템을 조금씩 변화시켜 가독성, 명확성이나 코드베이스의 유지보수성을 개선하는 기법이다. 리팩터링은 기능은 바꾸지 않는다. 리팩터링은 코드베이스 내부를 일하기 쉽게 바꿀때 사용한다.

지속적인 통합(Consinuous Integration)은 소프트웨어 프로젝트에서 격는 통합의 고통을 줄이는 기법이다.

Ant 기반의 프로젝트에서는 똑같은 문자열을 가진 Ant XML 코드가 몇번씩 되풀이 되곤한다. 이는 메이븐(Maven) 프로젝트를 시작하게 된 이유중에 하나이다.

개별 빌드를 한데 모아보면 공통적인 화제가 있음에도 불구하고, 커뮤니티들은 각자 빌드 시스템을 만들었고 빌드 로직을 여러 프로젝트에 걸쳐 재사용하지 않았다.

Better Builds with Maven



여러가지 아주 중요한 이야기들을 이책을 통하여 들을 수 있었습니다.

그 동안 Agile에 대하여 정확하게 모르고 있었던 부분들을 하나 하나씩 깨우쳐 가는 소중한 시간이었습니다.
역시 이번 10회 Java 컨퍼런스에서도 얻은 것들이 참 많아 좋았습니다.

좋은 책을 주시고 강연 및 답변도 해주신 안영회님에게 감사드립니다.