1장 아키텍처 기본 기법
프로그래밍의 정석 도서 3.11 아키텍처 기본 기법 정리
아키텍처 기본 기법이란 소프트웨어 아키텍쳐를 적절하게 구축하는 데 필요한 기초 원리다. 제대로 소프트웨어 아키텍처를 구축하려면 기초가 되는 몇 가지 원리에 기반을 두고 수행해야 한다. 소프트웨어 개발의 역사 속에서 수많은 프로그래머가 축적해 온 실천적이며 방대한 경험에 기반하고 있다. 어떤 문제에 대해 특정한 해결책이 다른 방법보다 뛰어나다는 사실을 프로그래머들이 인식하고 그 해결책을 여러 차례 재사용해 왔는 데, 그것이 바로 기본 기법이다.
추상이란 개념적으로 명확한 선 긋기를 수행하는 것이다. 선 긋기에 따라 어떤 모듈을 그 이외의 모듈로부터 명확하게 구별한다. 추상은
사상
과 일반화
라는 2가지 관점에서 정리된다.사상
- 복잡한 대상의 몇 가지 성질을 버리고 특정한 성질에 주목하는 것이다.
- 불필요한 것을 버리고 본질을 파악하는 것이다.
일반화
- 구체적인 대상으로부터 공통 성질을 추출해서 더욱 범용적인 개념으로 정식화하는 것이다.
- 다른 여러 개의 대상에 집중할 때 공통된 성질을 찾아내고 공통점을 조합시켜 범용적인 개념을 구상한다.
관련 있는 데이터와 로직을 그룹핑해서 하나의 모듈을 정의한다. 관계성이 강한 데이터와 로직을 모듈이라는 껍질로 감싸는 것을 캡슐화라고 부른다.
그룹핑을 통해 관련 있는 요소끼리만 특정 추상 개념을 담당하도록 모듈로 모은다. 이렇게 하면 다음과 같은 장점을 얻을 수 있다.
- 관련 없는 요소가 섞이지 않기 때문에 코드가 읽기 쉬워진다.
- 변경 시의 영향이 모듈 안으로 한정된다.
- 영향도가 명확해지므로 코드의 변경이 쉬워진다.
- 각각 독립된 부품이므로 재사용성이 높아진다.
- 작은 단위로 분할되므로 복잡한 문제에 대처할 수 있다.
모듈의 구현을 해당 모듈을 사용하는 클라이언트로부터 은닉한다.
모듈이 클라이언트가 알 필요 없는 내부의 상세 부분을 은닉하면 인터페이스가 작아지고 정보의 교환이 단순해지며 코드 전체의 복잡성을 낮출 수 있다.
정보 은닉을 실현하려면 캡슐화를 사용한다. 캡슐화와 정보 은닉은 원래 다른 개념이다.
- 캡슐화
- 관계가 있는 요소를 모아 모듈화하는 것이다.
- 관계가 깊은 데이터와 함수를 한군데로 모은다.
- 정보 은닉
- 모듈의 내부 상태나 내부 함수를 은닉하는 것이다.
- 내부에 대한 외부로부터의 직접적인 접근을 차단한다.
모듈을 의미 있는 단위로 모든 다음 그룹화한다. 이는 소프트웨어 전체를 의미 있는 단위로 분할하는 것이다. 이렇게 분할된 단위를 패키지라고 부른다.
어느 정도 대규모 소프트웨어가 되면 이번에는 대량으로 작성된 모듈이 오히려 복잡성을 낳는 결과를 초래한다. 이것이 바로 패키지다. 패키지화에는 다음과 같은 이점이 있다.
- 소프트웨어 전체가 패키지라는 작은 단위로 분할되므로 복잡도가 낮아진다.
- 패키지 안에 관련 없 는 모듈이 섞이지 않으므로 모듈을 관리하기 쉬워진다.
- 수정에 대한 영향도가 패키지 안에 머무를 가능성이 높으므로 코드를 변경하기 쉬워진다.
- 종속 관계가 정리되어 패키지 단위로 재사용하기 쉬워진다.
관심이란 소프트웨어의 기능이나 목적을 뜻한다. 관심을 분리한다는 것은 각각의 관심에 관련된 코드를 모아 독립된 모듈로 만들어 다른 코드로부터 분리한다는 뜻이다.
설계 기법에서 패턴의 대부분은 관심의 분리를 실현하려는 목표를 가지고 있다. 가장 대표 적인 패턴이 MVC 패턴이다. MVC 패턴에서는 비즈니스 로직, 사용자에 대한 표시, 입력 처리를 분리한다.
캡슐화에 의해 관련 있는 요소들이 특정 추상 개념을 담당하는 모듈로 모여진다. 모듈이 담당하는 추상에 대한 표현은 충분하고 완전하며 프리미티브여야 한다.
충족성이란 모듈이 표현하고자 하는 추상이 그것을 전하기에 충분한지를 뜻한다. 예를 들어 모듈이 컬렉션을 표현하고 있는 때 remove가 제공된다고 해도 add가 제공되지 않는다면 컬렉션이라는 점을 전하기에는 불충분한다.
완전성이란 모듈이 표현하고자 하는 추상이 모든 특징을 갖추고 있는지를 뜻한다. 뭔가 빠진 것이 없이 모든 것을 갖추고 있다면 어떤 클라이언트에서도 사용하기 쉬워진다. 예를 들어 모듈이 컬렉션을 표현하고 있을 때 요소의 개수를 구하는 size가 제공되지 않는 다면 완전하다고 할 수 없다.
프리미티브성이란 모듈이 표현하고자 하는 추상이 모두 순수한지 아닌지를 의미한다. 예를 들어 모듈이 켈렉션을 표현하고 있을 때 아이템 1개 추가하는 add가 제공된다면 아이템을 10개 추가하는 add10은 필요하지 않다. 추상의 순수성이라는 관점에서 보면 오히려 불필요한 기능이다.
모듈은 정책 혹은 구현을 다룬다. 다만 하나의 모듈에서 양쪽 모두를 다루어서는 안 된다.
정책 모듈
- 해당 소프트웨어의 전체에 종속되는 비즈니스 로직이나 그 밖의 모듈에 대한 파라미터를 선택하는 부분이다.
- 해당 소프트웨어에 특화되어 있다. 해당 소프트웨어에 변경이 생기면 정책 모듈은 변경을 강요당한다.
구현 모듈
- 해당 소프트웨어의 전제의 종속되지 않는 독립적 로직 부분이다.
- 특정 소프트웨어에 종속되지 않는 순수한 모듈이므로 다른 소프트웨어에서도 재사용할 수 있다.
모듈은 인터페이스 파트와 구현 파트 2개의 분리된 부분으로 구성한다.
인터페이스 파트란 모듈이 가진 기능을 정의하고 모듈의 사용 방법을 정하는 부분이다. 클라이언트에서 접근할 수 있는 함수의 원형으로 구성된다.
구현 파트란 모듈이 가진 기능을 실현하는 코드 부분이다. 모듈이 내부에서 사용하는 로직과 데이터가 표함된다. 구현 파트는 클라이언트에서 접근할 수 없다.
모듈의 인터페이스 사양만 제시되므로 단순하고 이해가 쉬워져 모듈을 쉽게 사용할 수 있다. 사용법과 기능의 실현 방법이 서로 독립성으로 확보할 수 있다.
모듈에 관한 설계 원리로
구현이 아닌 인터페이스에 맞춰 프로그래밍하라
라는 격언이 있다. 이에 따라 모듈끼리의 호출은 서로 인터페이스만 사용하도록 한다. 인터페이스의 구현은 인터페이스 뒤쪽으로 숨겨 이를 직접 호출하는 것을 허용하지 않도록 한다.모듈의 요소에 관한 선언과 정의는 1회로 제한한다. 정의가 1회라는 말은 예를 들어 변숫값을 초기화했다면 이후 값을 변경하지 않는다는 뜻이다. 이렇게 하면 변숫값의 변화를 추적하지 않아도 되므로 직관적인 코드가 된다.
참조 투과성
- 호출 결과가 파라미터에만 종속된다 : 파라미터로 같은 값을 넘겨주면 항상 같은 반환값을 돌려주는, 즉 반환값이 파라미터값에만 종속되는 특성이다.이런 특성을 가리켜 순수하다고 표현한다.
- 호출이 다른 기능의 동작에 영향을 주지 않는다 : 함수가 부작용을 갖지 않는 특성이다. 부작용이란 어떤 처리가 상태의 변경을 일으켜 이후의 처리 결과에 영향을 주는 것이다.
커다란 문제를 그 자체로 해결하려면 어려워지고 시간이 많이 걸린다. 최악의 경우 해결할 수 없을 때도 있다. 규모가 너무 큰 탓에 문제가 너무 복잡하기 때문이다. 제어하기 쉬운 규모까지 문제를 분할하고 거기서부터 착수하는 방식이 효율적이다.
Last modified 5mo ago