<aside> ✅
사용자가 본인 계좌에서 다른 계좌로 송금하는 유스케이스
</aside>
코드를 구조화하는 첫 번째 접근법은 계층을 이용하는 것

계층으로 구성하면 기능적인 측면들이 섞이기 쉽다.
웹, 도메인, 영속성 계층 각각에 대해 전용 패키지를 두었다. 간단한 구조의 계층은 적합한 구조가 아닐 수 있어서 의존성 역전 원칙을 이용해 의존성이 domain 패키지에 있는 도메인 코드만을 향하도록 만들었다.
이 패키지는 최적의 구조가 아니다

기능을 기준으로 코드를 구성하면 기반 아키텍처가 명확하게 보이지 않는다.
가장 본질적인 변경은 계좌와 관련된 모든 코드를 최상위의 account 패키지에 넣었으며, 계층 패키지들도 없앴다.
각 기능을 묶은 새로운 그룹은 account와 같은 레벨의 새로운 패키지로 들어가고, 패키지 외부에서 접근되면 안 되는 클래스들에 대해 package-private 접근 수준을 이용해 패키지 간의 경계를 강화할 수 있다.
패키지 경계를 package-private 접근 수준과 결합하면 각 기능 사이의 불필요한 의존성을 방지할 수 있다.
추가로 AccountService의 책임을 좁히기 위해 SendMoneyService로 클래스명을 바꿨다.
이제 ‘송금하기’ 유스케이스를 구현하는 코드는 클래스명만으로도 찾을 수 있게 됐다.
그러나 기능에 의한 패키징 방식은 계층에 의한 패키징 방식보다 아키텍처의 가시성을 훨씬 더 떨어뜨린다. 어댑터를 나타내는 패키지명이 없고, 인커밍 포트, 아웃고잉 포트를 확인할 수 없다.
심지어 도메인 코드와 영속성 코드 간의 의존성을 역전시켜 SendMoneyService가 AccountRepository 인터페이스만 알고 있고 구현체는 알 수 없도록 했음에도 불구하고, package-private 접근 수준을 이용해 도메인 코드가 실수로 영속성 코드에 의존하는 것을 막을 수 없다.