Golang에서 wire을 통해 DI를 쉽게 해보자

코딩하는범이·2022년 4월 24일
0
post-thumbnail

문제 상황

Golang에서 개발하면서 Spring에서 처럼 편하게 의존성을 주입받고 싶을 때가 있다. 그러나 Golang에서는 일일이 하나씩 생성해서 주입 시켜줘야 하는데 예제로 보여줄 수 있는 코드는 아래와 같다

func initController() {
	db := database.GetDB()
	userRepository := repository.NewUserRepository(db)
	userService := service.NewUserService(userRepository)
	userController = controller.NewUserController(userService)
}

위에서 보여지는 코드는 User Controller 생성에 필요한 Service를 주입받고 있는 경우인데 Service의 경우 Repository를 다시 필요로 하고 Repository는 DB를 필요로 하기에 다단계로 주입 받고 있는 형태이다.
프로젝트 크기가 커지게 되면 주입 받아야 할 경우들이 매우 많아지고 코드도 늘어나기 마련이다.

해결 방법

이러한 문제를 해결하기 위해 나는 google에서 만든 wire 라는 library를 사용해 보려고 한다. 해당 library는 편하게 DI를 할 수 있도록 도와준다.

https://github.com/google/wire

위의 라이브러리 사용법은 간략하게 정리하면 아래 순서와 같다

  1. wire.go 파일에 DI 해야하는 부분을 정의
  2. 제공해주는 명령어를 통해 wire-gen.go 생성
  3. wire-gen.go 에서 자동 생성된 코드를 이용

예제

위에서 보여줬던 InitController 부분을 wire 라이브러리를 통해서 변경해 보겠다.

해당 프로젝트 경로에서 아래 명령어 실행해 wire 라이브러리를 사용

go get github.com/google/wire

command에서 wire 명령어를 사용하기 위해 아래의 명령어 실행해 설치

go install github.com/google/wire/cmd/wire@latest

wire.go 작성

// +build wireinject

package module

import (
	"github.com/google/wire"
	"gorm.io/gorm"
	"login/controller"
	"login/core/repository"
	"login/service"
)

func InitUserController(db *gorm.DB) controller.UserController {
	wire.Build(repository.NewUserRepository, service.NewUserService, controller.NewUserController)
	return controller.InUserController{}
}

문서에 따르면 위에서 작성한 // +build wireinject 는 꼭 작성해 줘야 한다. Build tool에서 무시하는 조건으로 보인다.

wire.go 파일이 있는 경로에서 wire . 명령어를 실행하면 wire-gen.go 파일이 생성된 모습을 확인 할 수있다.

자동으로 생성된 wire-gen.go

// Code generated by Wire. DO NOT EDIT.

//go:generate go run github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject

package module

import (
	"gorm.io/gorm"
	"login/controller"
	"login/core/repository"
	"login/service"
)

// Injectors from wire.go:

func InitUserController(db *gorm.DB) controller.UserController {
	userRepository := repository.NewUserRepository(db)
	userService := service.NewUserService(userRepository)
	userController := controller.NewUserController(userService)
	return userController
}

이제 자동으로 생성된 코드를 통해 사용하면 조금더 코드가 깔끔해지는 모습을 볼 수 있다.

profile
기록 그리고 기억

0개의 댓글