티스토리 뷰

어떤 서비스나, 제품의 소프트웨어를 개발할때 설계가 굉장히 중요하고 설계을 어떻게 잡느냐에 따라 생산성과 비용이 판이하게 달라집니다. 그러한 아키텍쳐 관점 중의 하나가 바로 클린아키텍쳐인데요. Go 언어에서는 어떻게 적용하고 구성하는지 알아보도록 하겠습니다.

Clean Architecture

Go 언어에서 Clean Architecture는 Robert C. Martin의 'Clean Architecture' 책에서 제시한 소프트웨어 아키텍쳐의 일종입니다. 이 아키텍쳐는 의존성 역전 원칙(Dependency Inversion Principle)을 중심으로 구성되어 있고, 비즈니스 로직과 프레임워크 또는 라이브러리와 같은 기술적 세부 사항을 분리하는 것을 강조합니다.

 

Clean Architecture는 다양한 레이어로 구성되어 있으며, 각 레이어는 서로 독립적이고 분리된 책임을 가집니다. 이를 통해 유지보수성과 테스트 용이성을 향상시키고, 비즈니스 로직과 기술적인 세부사항 간의 결합도를 줄이는데 도움이 됩니다.

구성요소

  • Entities : 비즈니스 논리를 포함하는 구조체 또는 인터페이스
  • Use Cases : 비즈니스 로직을 구현하는 메서드 또는 함수
  • Repository : 데이터 저장소에 대한 인터페이스 
  • Presenters : 출력용 데이터를 생성하는 인터페이스
  • Controllers : HTTP 요청을 처리하는 메서드 또는 함수

구성요소를 방금 설명했지만 읽으면서도 내가 구현한 모듈이나이나 인터페이스가 어떻게 재배치해야할지 감이 잘 오지 않을 수 있습니다. 실제 위와 같은 구성요소를 본인이 구성한 구현체에서 바꿔보는 실습도 진행할 예정이라 우선 이론적으로 이런것이 필요하다는 것을 알고 넘어가면 좋겠습니다.

이러한 구성 요소는 서로 분리되어 있으며, 의존성 역전 원칙을 따르는 방식으로 상호작용합니다. 이렇게 구성하면 장점은,

 

  • 유연하고
  • 확장가능하며,
  • 테스트하기 쉽고
  • 유지보소 하기 쉽다.

의존성 역전원칙

앞에 나온 개념중 의존성 역전원칙이라는 내용이 있는데요. 대충 감은 오시겠지만 조금더 명확하게 하기위해서 집고 넘어가도록하겠습니다. 이 원칙은 객체 지향 프로그래밍에서 중요한 원칙 중 하나이며, 이 원칙은 소프트웨어 아키텍쳐의 품질을 향상시키는데 도움이 됩니다. 

 

의존성 역전원칙은 상위 수준의 모듈이 하위 수준의 모듈에 의존해서는 안되며, 두 모듈 모두 추상화에 의존해야 한다는 원칙입니다. 즉, 인터페이스나 추상 클래스와 같은 추상화된 클래스를 사용하여 두 모듈 간의 의존성을 낮추는 것입니다.

 

이러한 원칙을 따르면 하위 수준 모듈의 변경으로 인해 상위 수준 모듈이 영향을 받지 않게 됩니다. 이는 유연하고 확장 가능한 아키텍쳐를 구현하는데 도움이 됩니다. 또한, 이 원칙은 테스트 용이성을 향상시키는 데도 중요한 역할을 합니다. 추상화를 통해 하위 수준 모듈을 대체하여 테스트할 수 있기 때문입니다. 의존성 역전원칙은 소프트웨어 아키텍쳐에서 중요한 원칙 중 하나이며, 객체 지향 설계의 다른 원칙들과 함께 사용하여 유지보수 가능하고 테스트 용이한 코드를 만들 수 있다.

 

적용준비

이러한 아키텍쳐의 변경은 기존에 잘 돌아가는 소프트웨어를 굳이 왜 바꿔야하는지 의문이 들게 생각할 수 있지만 지금보다, 나중을 더 생각하는 관점에서 바라보는 것이 중요합니다. 한번 개발한 소프트웨어가 영원히 불멸할것 같지만 꽤나 다양하게 바뀝니다. 단순히 문제가 있어서 바뀔수 도 있고, 속도를 빠르게 하기위해 바뀔수 도 있으며, 비즈니스 요구사항을 만족시키기 위해 바꿔야하는 경우도 있습니다.

 

당장 여러분이 개발한 소프트웨어를 클린아키텍쳐로 변경할 필요가 없어보여도 이번 기회가 변경해봄으로써 차후에 어떤 장점들을 실제로 얻게되는지 해보는 것도 개발 커리어에서 중요하다고 생각 되는데요. 이제 클린아키텍쳐를 Go 로 간단한 웹서버를 만들어보도록 하겠습니다.

 

도메인 유스케이스

  • 새로운 book을 저장한다.
  • book의 타입(개발서적, 마켓팅, 기타)에 따라 북 리스트를 가져온다.
  • 제목을 보고 book 한개를 가져온다.

도메인에 대한 정의는 간단하게 이렇게 하고 프로젝트 Allocation을 구성해보도록 하겠습니다.

https://github.com/golang-standards/project-layout/blob/master/README_ko.md

 

GitHub - golang-standards/project-layout: Standard Go Project Layout

Standard Go Project Layout. Contribute to golang-standards/project-layout development by creating an account on GitHub.

github.com

Go를 통해 주로 사용하는 Allocation 패턴은 위 깃허브를 통해 참고해주시면 좋고 아래와 같이 구성하겠습니다. 사실 코드를 실제 구현하기 전에 어떤 파일을 어디 폴더에 배치할 거냐도 굉장히 중요한 설계요소이니 먼저 구현하지 말고 생각먼저해주세요!

 

  • /cmd : 프로젝트의 주요 어플리케이션을 포함, 서버를 실행하거나 데이터베이스 마이그레이션 등의 역할
  • /internal : 프로젝트 외부에 공개하지 않는 코드를 포함하여 대부분의 코드가 이 안에 위치
  • /internal/app : Clean Architecture 에서 Presentation 레이어에 있는 코드를 포함
  • /internal/pkg : Clean Architecture 에서 Domain, Database 레이어에 있는 코드를 포함 
  • /pkg : 외부에 공개하는 인터페이스 관련 코드를 포함

이렇게 작성했지만, 제일 위에 요소가 Entity, use case 이런 것들을 어디다가 작성하는 것일까요? Repositorys어디도 Presenter는 어디지? 하는 생각이 들 수 있습니다. 아무래도 Go에서 추구하는 디렉토리 정의 포맷이랑 클린아키텍쳐랑 조금 맞지 않은 면이 있어서 인데요. usecase, entity, repository는 /internal/pkg에 있다고 보시면 되고, controller와 presentation 코드는 /internal/app 에 있다고 생각하시면 됩니다.

 

이제 폴더를 잡고 구현해봐야할텐데요, 한번 실제 구현하고 동작시켜보고 나서 인사이트를 뽑는 작업들을 해볼 예정인지라, 같이 하나씩 따라해보면 좋을 것 같습니다. 그럼 다음 시간에 뵐께요!

 

댓글