레이어드 아키텍처는 소프트웨어를 관심사에 따라 여러 레이어로 분할하여 구성하는 아키텍처 패턴이다.
레이어드 아키텍쳐는 다음과 같은 구성요소로 이루어져 있다.

Presentation Layer : 사용자 혹은 클라이언트 시스템과 직접적으로 연결되는 부분이다.
Business Layer : 비즈니스 로직을 구현하는 부분이다.
Persistence Layer : 데이터의 영구 저장과 관리를 담당하는 부분이다.
레이어드 아키텍쳐는 도메인에 대한 작업을 모두 비즈니스 레이어에서 처리하기 때문에 비즈니스 레이어가 비대해진다.
<도메인에 관한 작업을 비즈니스 로직에서 모두 처리>
@Service
@RequiredArgsConstructor
public class Service{
private Repository repository;
public Long join(String username){
// 도메인 생성이나 수정작업을 모두 비즈니스 레이어에서 수행
Member member = new Member(username);
repository.save(member);
return member.getId();
}
}
그리고 레이어 간의 의존성이 높아져 결합도가 높아지는 문제도 발생할 수 있다.
<Business Layer에서 JPA에 의존>
@Service
@RequiredArgsConstructor
public class Service{
private Repository repository;
}
@Repository
@RequiredArgsConstructor
public class Repository{
private EntityManager em;
public void save(Member member){
em.persist(member);
}
}
<Business Layer에서 Rest 방식으로 들어온 인스턴스 직접 사용>
@RestController
@RequiredArgsConstructor
public class Controller{
private Service service;
@PostMapping("/post")
public ResponseEntity<Void> post(PostDto postDto){
service.save(postDto);
return new ResponseEntity(HttpStatus.CREATED);
}
}
@Service
@RequiredArgsConstructor
public class Service{
private Repository repository;
// Presentation Layer의 Dto를 사용, 또는 엔티티를 그대로 사용
public Long save(PostDto postDto){
}
}
도메인에 대한 작업만 수행하는 도메인 계층을 만들어서 비즈니스 레이어의 규모를 줄일 수 있다.
@Service
@RequiredArgsConstructor
public class Service{
private Repository repository;
public Long join(String username){
Member member = Member.from(username);
repository.save(member);
return member.getId();
}
}
public class Member{
private Long id;
private String username;
// 도메인 클래스에서 도메인에 관한 작업 수행
public static Member from(String username){
Member member = new Member();
member.username = username;
return member;
}
}
포트는 어댑터와 도메인이 통신하기 위한 인터페이스이다. 어댑터는 외부세계와 실제로 상호작용하는 클래스들이다.
// use case
@Service
@RequiredArgsConstructor
public class Service{
private Repository repository;
}
// persistence adapter와의 통신을 위한 port
public interface Repository{
public void save(Member member);
}
// persistence adapter
@Repository
@RequiredArgsConstructor
public class RepositoryImpl implements Repository{
private EntityManager em;
@Override
public void save(Member member){
em.persist(member);
}
}
// web adapter
@RestController
@RequiredArgsConstructor
public class Controller{
private Service service;
@PostMapping("/post")
public ResponseEntity<Void> post(PostDto postDto){
WebDto webDto = WebDto.from(postDto);
service.save(webDto);
return new ResponseEntity(HttpStatus.CREATED);
}
}
// web adapter와의 통신을 위한 port
public interface Service{
public Long save(WebDto webDto);
}
// use case
@Service
@RequiredArgsConstructor
public class ServiceImpl implements Service{
private Repository repository;
@Override
public Long save(WebDto webDto){
}
}
이 때 레이어드 아키텍쳐의 Presentation Layer나 Persistence Layer에 해당했던 부분은 모두 외부세계로 볼 수 있다. 헥사고날 아키텍쳐에서는 이 부분들을 Infrastructure Layer라고 한다.
