왜 나는 hexagonal 구조에 관심을 갖는가?

Su hwan Choi·2023년 5월 14일

Hexagonal 구조란?

Hexagonal 구조는 Alistair Cockburn이 제안한 소프트웨어 아키텍처 패턴으로, 애플리케이션의 핵심로직과 외부 시스템 간의 상호작용을 분리하는 것이 목적이다. 이로 인해, 유연한 아키텍처를 구축할 수 있고, 유연한 아키텍쳐는 테스트 용이성과 확장성 향상을 동반한다.

그래서 한번 해보기로 했다

마침 이사한 집에서 펜트리에 보관하는 여러 물건들의 수량을 관리해야 할 필요가 들었다. 쉬면서 포트폴리오로 제공할 프로젝트라는 의미에도 나쁘지 않은것 같다.
GitHub - soyotime0118/homeInventorySystem
hexagonal 관련된 내용을 적용하는 것을 우선 목표로 하고, 개발이슈를 기준으로한 git-flow등은 과감히 무시하고 개발하기로 하자. 중요하지 않다는 것이 아니라. 이 프로젝트 특성상 중요한 문제가 아니라 생각한다.


Hexagonal 구조의 장점

1. 높은 수준의 유연성

Hexagonal 구조는 핵심로직과 외부 세계와의 연결을 분리함으로써 높은 수준의 유연성을 제공한다. 사실 우리가 아키텍쳐를 연구하는 이유중 하나일 것이다. 유연성 증가는 새로운 기술이나 서드파티 라이브러리를 도입하거나 변경할 때 시스템의 전체적인 설계에 큰 영향을 주지 않고 쉽게 적용할 수 있다.

2. 테스트 용이성

유연성증가로 응용프로그램의 내부와 외부를 독립적으로 테스트할 수 있는 환경이 된다. 이 구조를 사용하면, 외부 서비스나 인프라와의 의존성 없이 핵심 로직에 대한 테스트를 수행할 수 있게되어 테스트코드를 의존성없이 만드는 것이 쉬워진다. 하지만 이를 테스트코드 작성이 쉬워진다고 착각하면 안된다.

3. 간결한 코드

코드가 짧고 읽기 좋아진다. 핵심 로직과 외부 시스템간의 상호 작용을 명확하게 구분하기 때문에, 해당 모듈만 잘 찾아가고, 구분이 잘되어 있다면 코드가 잘 정리되어 있으며 이해하기 쉽다. 역시나 이를 ‘무조건 짧은코드’ 라고 오해하면 안된다. 원래 긴 코드라면 요술을 부려서 짧게 할수는 없다. 무의미하게 20라인씩 기계적으로 나누는 건 의미가 없다. 하지만 짧다고 하지 않았나? 뭘 말하려는 걸까?
여기서 말하는 간결의 의미는 코드를 읽는 개발자의 피로도가 적다는 것이다. 이것은 생각보다 굉장히 중요한 문제다. 아무리 훌륭한 개발자도 코드를 읽지 않고서는 개발할 수 없다. 코드를 읽는다는것은 머리속 혹은 종이위에서 코드를 따라가 본다는 것이다.
만약 이 과정이 매우피곤하다면? 흔히말하는 유지보수가 나쁜 코드가 될 것이다.


Hexagonal 구조의 예시

집의 재고를 관리하는 시스템을 예로 들어, Hexagonal 구조 적용을 고려해보자.

1. 핵심로직(use case)

집안 물건의 사용을 담당하는 UseInventory 클래스를 정의한다. 이 클래스는 사용자의 재고사용 요청을 처리하고, 잔여 수량을 반환한다

public class UseInventory {
	@Override
	@Transactional
	public int usingInventory(InventoryId inventoryId, Integer quantity) {
    //id기준으로 Inventory 가져오기
    Inventory inventory = inventoryPersistentRepository.loadByInventoryId(inventoryId)
            .orElseThrow(() -> new NotFindStockException(inventoryId));

    //재고 사용처리
    inventory.use(quantity);

    inventoryPersistentRepository.modifyInventory(inventory);

    return inventory.getQuantity();
	}

}

2. 인터페이스 정의

재고수량 사용으로 인한 차감을 위해 다양한 외부 인터페이스를 사용할 수 있다. 이를 위해, 외부 인터페이스를 추상화한 ModifyInventoryStateOutput 인터페이스를 정의한다

public interface ModifyInventoryStateOutput {

    //재고수량변경
    void modifyInventory(Inventory inventory);

    Optional<Inventory> loadByInventoryId(InventoryId inventoryId);

}

3. 외부 서비스 구현

InventoryPersistentRepository 인터페이스를 구현하여, 실제 외부 서비스와의 통신을 처리하는 클래스를 만들고 이를 주입한다.

public class InventoryPersistentRepository implements ModifyInventoryStateOutput{
    
}

public class FakeInventoryRepository implements ModifyInventoryStateOutput {

}

결론

Hexagonal 구조는 유연성 증가로 인한 테스트 용이성, 간결한 코드등의 이점을 제공한다. 그러나 모든 상황에 Hexagonal 구조가 완벽한 해결책은 아니다.
이 구조를 적용할 때는 프로젝트의 특성, 요구 사항, 팀의 기술 레벨 등을 고려해야 한다. 올바른 상황에서 Hexagonal 구조를 사용하면 유연성 증가로 품질이 향상될 것이라 생각한다.
차츰차츰 관련된 내용을 블로그 글에 추가할 생각이다.

0개의 댓글