HOME / CATALOG / IT LEADERS
IT Leaders

만들면서 배우는 헥사고날 아키텍처 설계와 구현 (ebook)

자바와 쿼커스를 활용한 빠르고 생산성 높은 애플리케이션 구축
지은이 다비 비에이라
옮긴이 김영기
도서 정보
출간일
2023년 7월 10일
쪽수
412쪽
판형
188*240*17mm
ISBN
9791158394486
시리즈
IT Leaders 시리즈_037
정가
22,400원
난이도
도서 소개
저자 소개
역자 소개
목차
예제 코드
정오표

도서 소개

리팩터링, 확장, 유지보수하기 쉬운 시스템 개발을 위한 헥사고날 애플리케이션 구축 실용 가이드!

헥사고날 아키텍처는 기술 코드와 비즈니스 코드의 분리, 변경에 더 잘 견디는 소프트웨어, 그리고 많은 양의 리팩터링 없이도 새로운 기술의 발전 및 통합을 허용해 개발자의 생산성을 향상시킨다. 헥사고날 원칙을 고수함으로써, 코드를 이해하고 유지보수에 필요한 노력을 줄이는 방법으로 소프트웨어를 구조화할 수 있다.

이 책은 엔티티, 유스케이스, 포트와 어댑터 같은 헥사고날 아키텍처의 기반 요소에 대한 심도 깊은 분석으로 시작해, 도메인 헥사곤에서 비즈니스 코드를 결합하는 방법, 애플리케이션 헥사곤에서 포트와 유스케이스를 사용해 기능을 만드는 방법, 프레임워크 헥사곤에서 어댑터를 사용해 소프트웨어를 다양한 기술과 호환이 되게 만드는 방법 등을 배운다. 또한 모든 헥사고날 아키텍처의 기반 요소를 적용하는 실제 시나리오를 기반으로 시스템을 직접 개발해 본다.

아울러 헥사고날 시스템을 만들어 보면서 자바 모듈을 사용해 의존성 역전을 강화하고 아키텍처 내의 각 헥사곤에서 격리를 보장하는 방법과 쿼커스를 사용해 헥사고날 애플리케이션을 클라우드 네이티브 시스템으로 바꾸는 방법도 알려준다.

이 책이 끝날 무렵이면, 복잡하고 오랫동안 지속되는 애플리케이션의 개발에 질서와 온전함을 가져올 수 있을 것이다.

★ 이 책에서 다루는 내용 ★

  • 명세 디자인 패턴을 활용한 비즈니스 규칙 알고리즘의 결합
  • 강력한 도메인 모델 생성을 위한 도메인 주도 설계 기법과 헥사고날 원칙의 결합
  • 시스템이 REST, gRPC, 웹소켓 같은 다양한 프로토콜을 지원하기 위한 어댑터의 사용 방법
  • 헥사고날 원칙에 기반한 모듈과 패키지 구조 생성
  • 의존성 역전의 적용과 소프트웨어 컴포넌트 사이의 격리를 보장하기 위한 자바 모듈의 활용
  • 입력 및 출력 포트의 수명주기 관리를 위한 쿼커스 DI 구현

 

도서 상세 이미지

저자 소개

다비 비에이라 (Davi Vieira)

다비 비에이라는 소프트웨어 설계, 개발, 아키텍처 분야에서 대규모 기업이 직면한 문제에 깊은 관심을 갖고 있는 소프트웨어 장인이다. 다비는 객체지향 언어를 사용해 복잡하고 오래 계속되는 사업에 필수적인 시스템(mission critical system)의 구축 및 유지 관련 분야에서 10년 이상의 경력을 갖고 있다. 그는 자신보다 선배들이 남긴 훌륭한 교훈과 소프트웨어 개발 전통을 귀중하게 여긴다. 이러한 소프트웨어 전통에서 영감을 얻어 자신의 아이디어를 개발하고 발전시키고 있다.

역자 소개

김영기 (resious@gmail.com)

삼성전자 네트워크 사업부 SE 그룹에서 소프트웨어 개발과 관련한 다양한 업무를 수행하고 있다. 주요 이력으로 지능망(IN)과 모바일 자바 애플리케이션 개발, 정적 분석과 소프트웨어 구조 분석, 소프트웨어 개발 도구 및 인프라 관리 등이 있다. 현재는 형상 관리와 개발 전략을 담당하고 있으며, 소프트웨어 개발과 관련된 조직 및 개발 문화, 애자일과 데브옵스, 인프라 자동화에 관심이 많다.

목차

  • [1부] 아키텍처 핵심 기초
  • ▣ 01장: 왜 헥사고날 아키텍처인가?
  • 기술 요구사항
  • 소프트웨어 아키텍처 검토
  • __보이지 않는 것들
  • __악순환
  • __아키텍처는 모두를 위한 것이 아니다
  • __모놀리식 시스템과 분산 시스템
  • __의사결정
  • 헥사고날 아키텍처 이해
  • __도메인 헥사곤
  • __애플리케이션 헥사곤
  • __프레임워크 헥사곤
  • __헥사고날 접근 방식의 장점
  • 요약
  • 연습 문제
  • 더 읽을거리
  •  
  • ▣ 02장: 도메인 헥사곤으로 비즈니스 규칙 감싸기
  • 기술 요구사항
  • 엔티티를 활용한 문제 영역 모델링
  • __도메인 엔티티의 순수성
  • __관련 엔티티
  • __UUID를 이용한 식별자 정의
  • 값 객체를 통한 서술력 향상
  • 애그리게잇을 통한 일관성 보장
  • 도메인 서비스 활용
  • 정책 패턴과 명세 패턴을 활용한 비즈니스 규칙 처리
  • POJO를 통한 비즈니스 규칙 정의
  • 요약
  • 연습 문제
  • 더 읽을거리
  •  
  • ▣ 03장: 포트와 유스케이스를 통한 동작 처리
  • 기술 요구사항
  • 유스케이스를 통한 소프트웨어 동작 표현
  • __유스케이스 작성 방법
  • 입력 포트를 갖는 유스케이스 구현
  • 출력 포트를 이용한 외부 데이터 처리
  • __어디에 출력 포트를 사용하는가?
  • 애플리케이션 헥사곤을 통한 동작 자동화
  • 요약
  • 연습 문제
  • 더 읽을거리
  •  
  • ▣ 04장: 외부와 상호작용하는 어댑터 만들기
  • 기술 요구사항
  • 어댑터 이해
  • 드라이빙 오퍼레이션 허용을 위한 입력 어댑터 사용
  • __입력 어댑터 생성
  • 다양한 데이터 소스와 통신하기 위한 출력 어댑터 사용
  • __출력 어댑터 생성
  • 요약
  • 연습 문제
  • 더 읽을 거리
  •  
  • ▣ 05장: 드라이빙 오퍼레이션과 드리븐 오퍼레이션의 본질 탐색
  • 기술 요구사항
  • 드라이빙 오퍼레이션을 통한 헥사고날 애플리케이션에 대한 요청 호출
  • __웹 애플리케이션을 헥사고날 시스템에 통합
  • __테스트 에이전트 실행
  • __애플리케이션 간의 헥사고날 시스템 호출
  • 드리븐 오퍼레이션을 통한 외부 리소스 처리
  • __데이터 지속성
  • __메시징과 이벤트
  • __모의 서버
  • 요약
  • 연습 문제
  •  
  • [02부] 헥사곤을 활용한 견고한 기반 구축
  • ▣ 06장: 도메인 헥사곤 만들기
  • 기술 요구사항
  • 도메인 헥사곤 생성
  • 문제 영역 이해
  • 값 객체 정의
  • 엔티티와 명세 정의
  • __Equipment와 Router 추상 엔티티
  • __코어 라우터 엔티티와 명세
  • __에지 라우터와 명세
  • __스위치 엔티티와 명세
  • 도메인 서비스 정의
  • __라우터 서비스
  • __스위치 서비스
  • __네트워크 서비스
  • 도메인 헥사곤 테스트
  • 요약
  • 연습 문제
  •  
  • ▣ 07장: 애플리케이션 헥사곤 만들기
  • 기술 요구사항
  • 애플리케이션 헥사곤 생성
  • 유스케이스 정의
  • __라우터 관리 유스케이스에 대한 디스크립션 작성
  • __라우터 관리를 위한 유스케이스 인터페이스 정의
  • __스위치 관리 유스케이스를 위한 디스크립션 생성
  • __스위치 관리를 위한 유스케이스 인터페이스 정의
  • __네트워크 관리자 유스케이스에 대한 디스크립션 생성
  • __네트워크 관리를 위한 유스케이스 인터페이스 정의
  • 입력 포트를 갖는 유스케이스 구현
  • __애플리케이션 헥사곤 테스트
  • 요약
  • 연습 문제
  •  
  • ▣ 08장: 프레임워크 헥사곤 만들기
  • 기술 요구사항
  • 프레임워크 헥사곤 부트스트래핑
  • 출력 어댑터 구현
  • __라우터 관리 출력 어댑터
  • __스위치 관리 출력 어댑터
  • 입력 어댑터 구현
  • __라우터 관리 입력 어댑터
  • __스위치 관리 입력 어댑터
  • __네트워크 관리 입력 어댑터
  • 프레임워크 헥사곤 테스트하기
  • 요약
  • 연습 문제
  •  
  • ▣ 09장: 자바 모듈을 이용한 의존성 역전 적용
  • 기술 요구사항
  • JPMS 소개
  • 헥사고날 시스템에서 의존성 역전
  • __유스케이스와 입력 포트를 통한 서비스 제공
  • 출력 포트와 출력 어댑터를 통한 서비스 제공
  • 입력 어댑터가 추상화에 의존하게 만들기
  • 자바 플랫폼의 ServiceLoader 클래스를 사용해 JPMS 공급자 구현체 검색하기
  • __RouterManagementGenericAdapter 초기화하기
  • __SwitchManagementGenericAdapter 초기화
  • __NetworkManagementGenericAdapter 초기화
  • 요약
  • 연습 문제
  • 더 읽을 거리
  •  
  • [03부] 아키텍처 핵심 기초
  • ▣ 10장: 모듈화된 헥사고날 애플리케이션에 쿼커스 추가
  • 기술 요구사항
  • JVM 다시 살펴보기
  • __JIT 컴파일러를 통한 런타임 성능 향상
  • __AOT 컴파일을 통한 시작 시간 개선
  • 쿼커스 소개
  • __JAX-RS를 통한 REST 엔드포인트 생성
  • __쿼커스 DI를 통한 의존성 주입
  • __객체의 유효성 검증
  • __데이터 소스 구성 및 하이버네이트 ORM 사용
  • 모듈화된 헥사고날 애플리케이션에 쿼커스 추가
  • 요약
  • 연습 문제
  •  
  • ▣ 11장: CDI 빈즈를 활용한 포트와 유스케이스 관리
  • 기술 요구사항
  • 쿼커스 DI 배우기
  • __빈으로 작업하기
  • 포트, 유스케이스, 어댑터를 CDI 빈으로 변환
  • __라우터 관리 객체에 대한 CDI 구현
  • __스위치 관리 객체에 대한 CDI 구현
  • __네트워크 클래스와 인터페이스를 위한 CDI 구현
  • 쿼커스와 큐컴버를 통한 유스케이스 테스팅
  • 요약
  • 연습 문제
  •  
  • ▣ 12장: RESTEasy 리액티브를 활용한 입력 어댑터 구현
  • 기술 요구사항
  • 서버 요청을 처리하는 방법
  • __명령형 접근 방식
  • __반응형 접근 방식
  • RESTEasy 리액티브를 통한 입력 어댑터 구현
  • __라우터 관리를 위한 리액티브 입력 어댑터 구현
  • __스위치 관리를 위한 리액티브 입력 어댑터 구현
  • __네트워크 관리를 위한 리액티브 입력 어댑터 구현
  • OpenAPI와 스웨거 UI 추가
  • 리액티브 입력 어댑터 테스트
  • 요약
  • 연습 문제
  •  
  • ▣ 13장: 출력 어댑터와 하이버네이트 리액티브를 이용한 데이터 유지
  • 기술 요구사항
  • 하이버네이트 리액티브와 파나쉬 소개
  • __하이버네이트 리액티브 기능
  • __파나쉬 기능
  • __액티브 레코드 패턴 적용
  • __리포지토리 패턴 적용
  • 출력 어댑터에 대한 반응형 동작 활성화
  • __반응형 데이터 소스 구성
  • __엔티티 구성
  • __반응형 리포지토리 클래스 구현
  • __반응형 출력 어댑터 구현
  • __MySQL 출력 어댑터에 대한 반응형 라우터 관리
  • __MySQL 출력 어댑터에 대한 반응형 스위치 관리
  • 반응형 출력 어댑터 테스트
  • 요약
  • 연습문제
  •  
  • ▣ 14장: 클라우드 배포를 위한 Dockerfile과 쿠버네티스 객체 설정
  • 기술 요구사항
  • 도커 이미지 준비
  • __우버 .jar 아티팩트를 통한 도커 이미지 생성
  • __네이티브 실행 파일을 통한 도커 이미지 생성
  • 쿠버네티스 객체 생성
  • __쿠버네티스의 주요 객체
  • __헥사고날 시스템을 위한 쿠버네티스 객체 구성
  • 미니큐브에 배포
  • 요약
  • 연습 문제
  •  
  • ▣ 15장: 헥사고날 애플리케이션을 위한 모범 설계 실천법
  • 기술 요구사항
  • DDD를 이용한 도메인 헥사곤 생성
  • __비즈니스의 이해
  • __지식 증대를 위한 협업 촉진
  • __도메인 헥사곤 구축을 위한 DDD 기법 적용
  • __헥사고날 시스템에서의 바운디드 컨텍스트와 서브도메인 구현
  • 포트와 유스케이스의 필요성
  • 다양한 어댑터의 범주 처리
  • 결론 - 헥사고날 여정
  • 요약
  • 연습 문제
  •  
  • ▣ 모범 답안
  •  

예제 코드

정오표

  • 21쪽, 예제 코드의 밑에서 4번째 줄

    outer.filterRouterByType(RouterType.valueOf(type)));

    ==>

    Router.filterRouterByType(RouterType.valueOf(type)));
  • 41쪽, 첫 번째 예제 코드의 밑에서 9번째 줄

    var networks = new ArrayList<>(Arrays.asList(network));

    ==>

    var networks = new ArrayList<>();
  • 44쪽, 페이지 하단 예제 코드의 12번째 줄

    Network = router.createNetwork(address,name,cidr);

    ==>

    Network network = router.createNetwork(address, name, cidr);
  • 96쪽, 본문 3번째 줄

    모든 ORAM 속성에 대해

    ==>

    모든 ORM 속성에 대해

  • 124쪽, 예제 코드의 밑에서 4번째 줄

    const reader = new Vtree.reader.Object();

    ==>

    const reader = new VTree.reader.Object();
  • 129쪽, 본문 5번째 줄

    이제 드라이븐 오퍼레이션의 수단으로

    ==>

    이제 드라이빙 오퍼레이션의 수단으로

  • 134쪽, 5번 항목 예제 코드의 4번째 줄

    }}

    ==>

    }
  • 158쪽, 페이지 상단 예제 코드의 2번째 줄

    private Protocol;

    ==>

    private Protocol protocol;
  • 178쪽, 4번 항목의 예제 코드를 다음 코드로 교체

    var location = createLocation("US");
    var coreRouter = createCoreRouter(location, "30.0.0.1");
    var newCoreRouter = createCoreRouter(location, "40.0.0.1");
    
    coreRouter.addRouter(newCoreRouter);
    assertEquals(1,coreRouter.getRouters().size());
  • 223쪽, 첫 번째 예제 코드(createRouter 메서드)의 4번째 줄

    public Router createRouter(Vendor vendor, Model, IP, Location, RouterType routerType){

    ==>

    public Router createRouter(Vendor vendor, Model model, IP ip, Location location, RouterType routerType){
  • 223쪽, 두 번째 예제 코드(addRouterToCoreRouter 메서드)의 5~6번째 줄

    Router = routerManagementUseCase. retrieveRouter(routerId);
    CoreRouter = (CoreRouter) routerManagementUseCase.retrieveRouter(coreRouterId);

    ==>

    Router router = routerManagementUseCase.retrieveRouter(routerId);
    CoreRouter coreRouter = (CoreRouter) routerManagementUseCase.retrieveRouter(coreRouterId);
  • 223쪽, 세 번째 예제 코드(removeRouterFromCoreRouter 메서드)의 5~6번째 줄

    Router = routerManagementUseCase.retrieveRouter(routerId);
    CoreRouter = (CoreRouter) routerManagementUseCase.retrieveRouter(coreRouterId);

    ==>

    Router router = routerManagementUseCase.retrieveRouter(routerId);
    CoreRouter coreRouter = (CoreRouter) routerManagementUseCase.retrieveRouter(coreRouterId);
  • 225쪽, 세 번째 예제 코드(createAndAddSwitchToEdgeRouter 메서드)의 4~5번째 줄

    public EdgeRouter createAndAddSwitchToEdgeRouter(Vendor, Model, IP, Location, SwitchType, Id routerId) {

    ==>

    public EdgeRouter createAndAddSwitchToEdgeRouter(Vendor vendor, Model model, IP ip, Location location, SwitchType switchType, Id routerId) {
  • 226쪽, 페이지 상단 예제 코드(createAndAddSwitchToEdgeRouter 메서드)의 밑에서 5번째 줄

    Router = switchManagementUseCase
      .addSwitchToEdgeRouter(newSwitch, (EdgeRouter) edgeRouter);

    ==>

    Router router = switchManagementUseCase
      .addSwitchToEdgeRouter(newSwitch, (EdgeRouter) edgeRouter);
  • 226쪽, 페이지 하단 예제 코드(removeSwitchFromEdgeRouter 메서드)의 5번째 줄

    EdgeRouter = (EdgeRouter) routerManagementUseCase.retrieveRouter(edgeRouterId);

    ==>

    EdgeRouter edgeRouter = (EdgeRouter) routerManagementUseCase.retrieveRouter(edgeRouterId);
  • 226쪽, 페이지 하단 예제 코드(removeSwitchFromEdgeRouter 메서드)의 7~8번째 줄

    Router = switchManagementUseCase
      .removeSwitchFromEdgeRouter(networkSwitch, edgeRouter);

    ==>

    Router router = switchManagementUseCase
      .removeSwitchFromEdgeRouter(networkSwitch, edgeRouter);
  • 246쪽, 페이지 상단 예제 코드의 첫 번째 줄

    RouterManagementUseCase = loaderUseCaseRouter.findFirst().get();

    ==>

    RouterManagementUseCase routerManagementUseCase = loaderUseCaseRouter.findFirst().get();
  • 246쪽, 2번째 예제 코드의 3번째 줄

    RouterManagementOutputPort = loaderOutputRouter.findFirst().get();

    ==>

    RouterManagementOutputPort routerManagementOutputPort = loaderOutputRouter.findFirst().get();
  • 247쪽, 첫 번째 예제 코드의 3번째 줄

    SwitchManagementUseCase = loaderUseCaseSwitch.findFirst().get();

    ==>

    SwitchManagementUseCase switchManagementUseCase = loaderUseCaseSwitch.findFirst().get();
  • 247쪽, 두 번째 예제 코드의 3번째 줄

    SwitchManagementOutputPort = loaderOutputSwitch.findFirst().get();

    ==>

    SwitchManagementOutputPort switchManagementOutputPort = loaderOutputSwitch.findFirst().get();
  • 248쪽, 첫 번째 예제 코드의 3번째 줄

    NetworkManagementUseCase = loaderUseCaseNetwork.findFirst().get();

    ==>

    NetworkManagementUseCase networkManagementUseCase = loaderUseCaseNetwork.findFirst().get();
  • 267쪽, 본문 2번째 줄

    모든 엔티티를 조회하기 위해 /request-validation 엔드포인트를 만들어 보자.

    ==>

    모든 엔티티를 조회하기 위해 /get-all-entities 엔드포인트를 만들어 보자.

WHERE TO BUY · 정가 22,400원
WHERE TO BUY · 정가 22,400원