의존 관계 자동 설정
24 Nov 2019 | SpringBoot의존 관계 자동 설정
앞서 포스팅한 PathVariable 간단한 예제의 예제 코드는 다음과 같습니다.
SimpleService.kt
@Service
class SimpleService {
    fun hello(name: String): String {
        return "hello $name"
    }
}
SimpleController.kt
@Controller
class SimpleController(val simpleService: SimpleService) {
    @RequestMapping(value = ["/user/{name}"], method = arrayOf(RequestMethod.GET))
    @ResponseBody
    fun hello(@PathVariable name: String): String {
        return simpleService.hello(name)
    }
}
SimpleController 클래스에서 SimpleService 인스턴스를 클래스 생성자의 매개변수로 전달하고 있습니다.
만약 해당 인자를 생성자의 매개 변수를 전달하고 싶지 않을 때는 다음과 같이 @Autowired 어노테이션을 이용할 수 있습니다.
@Controller
class SimpleController() {
    @Autowired
    private lateinit var service: SimpleService
    @RequestMapping(value = ["/user/{name}"], method = arrayOf(RequestMethod.GET))
    @ResponseBody
    fun hello(@PathVariable name: String): String {
        return service.hello(name)
    }
}
이와 같이 사용하는 것을 의존성 삽입(Dependency Injection)이라고 합니다.
인터페이스와 구현체 분리
위에서 만들었던 SimpleService 클래스를 다음과 같이 인터페이스와 구현체로 분리할 수 있습니다.
interface SimpleService {
    fun hello(name: String): String
}
@Service
class SimpleServiceImpl : SimpleService {
    override fun hello(name: String): String {
        return "hello $name"
    }
}
그리고 SimpleController도 다음과 같이 수정합니다.
@Controller
class SimpleController() {
    @Autowired
    private lateinit var service: SimpleService
    @RequestMapping(value = ["/user/{name}"], method = arrayOf(RequestMethod.GET))
    @ResponseBody
    fun hello(@PathVariable name: String): String {
        return service.hello(name)
    }
}
위 SimpleController 코드 안에는 SimpleServiceImpl과 관련된 코드가 하나도 없습니다. 
그런데도 스프링 부트가 SimpleService 인터페이스를 구현하는 적절한 인스턴스를 연결해서 매핑하는 것을 확인할 수 있습니다.
만약 SimpleService 인터페이스를 구현한 SimpleServiceImpl2 클래스를 추가로 생성하면 
실행할 때 다음과 같은 오류가 발생합니다.
Field service in com.snowdeer.board.controller.SimpleController required a single bean, but 2 were found:
	- simpleServiceImpl: defined in file [/Users/snowdeer/Workspace/SpringBoot/board/build/classes/kotlin/main/com/snowdeer/board/service/SimpleServiceImpl.class]
	- simpleServiceImpl2: defined in file [/Users/snowdeer/Workspace/SpringBoot/board/build/classes/kotlin/main/com/snowdeer/board/service/SimpleServiceImpl2.class]
의존 관계 자동 설정을 통한 장점
이와 같이 의존 관계 자동 설정을 이용하면 다음과 같은 장점을 얻을 수 있습니다.
- 세부 구현 정보 숨기기: 서비스 구현체에 종속성이 없더라도 해당 인스턴스를 사용가능하며, 따라서 서비스 작동 방식을 외부에 노출하지 않음
- 디커플링: 기존 서비스에 영향을 주지 않고, 새로운 서비스 변경이나 구현의 사용이 가능
- 쉬운 변경 처리: 스프링 설정을 통해 코드 수정 없이 서비스 변경이 가능함
