
여기서 가장 큰 문제점은 UI, 비즈니스 로직이 데이터 계층에 결합되는 것입니다. 물론 직접적으로 의존하진 않지만 전이되는 의존성입니다. UI는 비즈니스 로직이 없으면 제대로 작동할 수 없고, 비즈니스 로직은 데이터 액세스 계층이 없다면 제대로 작동할 수 없습니다. 여기서 인프라스트럭처는 시스템마다 상이하기 때문에 잠시 무시하겠습니다.
솔직히 제가 지금 제안드리는 아키텍쳐는 완전히 새로운 것은 아닙니다. 오른쪽 이미지는 어니언 아키텍쳐입니다. 어니언 아키텍쳐의 기본(기반) 규칙은 모든 코드들은 가운데 코어 레이어에 의존할 수 있지만 그 밖에 있는 코어에는 의존할 수 없다는 것입니다(의존성의 방향이 안쪽으로만 흐른다).
repository inrefaces)를 찾을 수 있을겁니다. 객체를 저장하는 동작은 애플리케이션 코어에 있지 않으며 일반적으로 데이터베이스에 개입되어 있습니다. 단지 인터페이스가 애플리케이션 코어 안에 있을 뿐입니다. 가장 바깥쪽에서는 UI, 인프라나 테스트를 볼 수 있습니다. 그 밖에 레포지토리 인터페이스를 구현하는 클래스들을 찾을 수 있습니다. 이 클래스는 특정 데이터 액세스 방법과 결합되어 있으며, 이것이 애플리케이션 코어의 밖에 존재하는 이유입니다. 이 클래스는 레포지토리 인터페이스를 구현하기 때문에 결합됩니다.
어니언 아키텍쳐는 전적으로 Dependency Injection 이론에 기반합니다. 애플리케이션 코어는 코어 인터페이스의 구현체를 필요로 하고, 구현 클래스가 애플리케이션의 가장자리에 있는 경우 애플리케이션이 유용한 작업을 수행할 수 있도록 런타임에 해당 코드를 주입하는 메커니즘이 필요합니다.
데이터베이스는 중앙이 아닌 외부에 있어야 합니다. 데이터베이스를 외부화하는 것은 애플리케이션을 데이터베이스 애플리케이션으로 생각하는 사람들에게 큰 변화를 유발할 수 있습니다. 어니언 아키텍쳐를 사용하면 위와 같은 데이터베이스 애플리케이션은 없습니다. 아마 데이터베이스를 저장 서비스로 사용하는 애플리케이션은 있을겁니다. 대신 애플리케이션 코어에 적절한 인터페이스를 구현하는 외부 인프라 코드를 통해서만 가능합니다. 데이터베이스, 파일 시스템과 같은 것들로부터 결합도를 떼어내면 애플리케이션의 라이프사이클을 유지시키는데 많은 도움이 됩니다.
Alistair Cockburn이 작성한 헥사고날 아키텍쳐 중 헥사고날 아키텍쳐와 어니언 아키텍쳐는 같은 전제를 공유합니다. 인프라를 외부화하고 인프라가 밀접하게 결합되지 않도록 어댑터 코드를 작성해야 한다는 것이죠.
파트 1에서는 어니언 아키텍쳐라고 불리는 아키텍쳐 패턴을 소개했습니다. OOP 디자인 컨셉은 새로운 것이 아니지만 여러 개의 기술과 컨벤션을 하나의 패턴 안에 끌어와서 이름을 붙혔습니다. 파트 2에서는 예시를 살펴봅니다.
UI 클래스 중 하나인 SpeakerController는 닷넷 MVC 프레임워크와 결합되어 있고 IConferenceRepository, IUserSession 와 결합되어 있습니다. 컨트롤러는 애플리케이션 코어 안에 정의된 인터페이스들에만 의존해야 합니다. 모든 의존성은 중앙쪽으로 향해야한다는 것을 기억하세요.
실제 UserSession 구현체와 ConferenectRepository 구현체는 애플리케이션 코어 밖에 위치해 있고 이들은 인터페이스에 의존해있으므로 구현이 가능합니다. 이 두 클래스들은 각각 자신의 위치보다 중심에 더 가까운 인터페이스들을 구현합니다. 런타임에서는 IoC 컨테이너가 레지스트리를 살펴보고 SpeakerController의 생성자에 필요한 의존성들을 충족시키게 해줍니다.
public SpeakerController(IConferenceRepository conferenceRepository,
IUserSession userSession, IClock clock)
: base(userSession)
{
_conferenceRepository = conferenceRepository;
_clock = clock;
_userSession = userSession;
}

IConferenceRepository,IUserSession 는 애플리케이션 코어 안에 정의된 인터페이스
런타임에서 IoC 컨테이너는 인터페이스를 구현한 클래스를 확인해서 SpeakerController에 전달합니다. 그 시점부터 SpeakerController는 스스로의 일을 할 수 있습니다.
어니언 아키텍쳐의 기본 규칙에 따르면 SpeakerController는 UserSession 클래스와 같은 레이어에 위치하기 때문에 직접적으로 사용해도 상관이 없습니다. 그러나 ConferenectRepository 클래스는 아닙니다(구현체가 아닌 코어 안에 있는 인터페이스를 의존해야 합니다).
Part 2에서는 애플리케이션를 위한 아키텍쳐를 정의하는 접근법에 대해서 설명했습니다. 이번에는 모호함과 키 포인트를 강조하기 위해 다이어그램을 조금 수정했습니다. 3장의 목표는 어니언 아키텍쳐와 전통적인 레이어드 아키텍쳐를 비교하고 대조시키는 것입니다. 레이어드 아키텍쳐와 어떻게 생겼는지를 비교하기 위해 어니언 아키텍쳐를 (레이어드 아키텍쳐처럼) 평평하게 피고 레이어드 아키텍쳐를 어니언 형태로 강제로 만들어 보겠습니다. 모양이 둘 중 하나일 수 있지만 실제 애플리케이션의 구조는 널리 알려진 것과는 많이 다릅니다.
다시 한번 강조하지만 어떤 기술들의 돌파구를 주장하는 것이 아닙니다. Martin Fowler, Ward Cunningham, Kent Beck, Michael Feathers 등과 같은 업계 리더들로부터 배웠던 것은 다른 아키텍쳐의 접근법에 대해서 소통한 결과로 어니언 아키텍쳐를 제시하는 것입니다. 이것들은 사실 근본적으로 다르지 않습니다.
살펴봅시다. 레이어드 아키텍쳐는 아래 묘사된 다이어그램과 비슷해보일 수 있습니다. 각 레이어들은 자신의 아래에 있는 레이어들과 커뮤니케이션합니다. UI는 비즈니스 로직과 소통하지만 데이터 액세스 계층과 직접적으로 소통하진 않습니다. 레이어링 접근 방식은 특정 카테고리의 코드를 UI에서 제외해야할 필요성을 나타냅니다. 가장 큰 단점은 비즈니스 로직이 결국 인프라스트럭처 관심사와 결합된다는 것입니다. 데이터 액세스, I/O, 웹서비스 모두 인프라스트럭쳐입니다. 인프라스트럭처는 **의 애플리케이션에 경쟁우위를 주진 않지만 필수적인 코드(any code that is a commodity and does not give your application a competitive advantage)**입니다. 이런 코드들은 애플리케이션의 수년동안의 유지 관리를 거치면서 자주 변경될 가능성이 높습니다. 인프라 스트럭처와 비즈니스 로직이 독립적인 상태가 되면 인프라가 변경될 때 비즈니스 로직이 바뀌지 않아도 됩니다.



