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를 할 수 있도록 도와준다.
위의 라이브러리 사용법은 간략하게 정리하면 아래 순서와 같다
- wire.go 파일에 DI 해야하는 부분을 정의
- 제공해주는 명령어를 통해 wire-gen.go 생성
- 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 파일이 생성된 모습을 확인 할 수있다.
// 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
}
이제 자동으로 생성된 코드를 통해 사용하면 조금더 코드가 깔끔해지는 모습을 볼 수 있다.
끗