본문 바로가기
공부/Spring

[Spring/Kotlin] Java와 Kotlin의 의존성 주입 방법 비교

by 웅대 2024. 4. 4.
728x90
반응형

이번에 프로젝트로 코틀린 + 스프링부트를 사용하게 되어서 자바 + 스프링부트와의 차이점을 비교해보려고 한다.

 

이전에 자바 + 스프링부트에서 의존성 주입 방법들과 그 특징들에 대해서 포스팅을 한 적이 있다.

 

(만약 의존성 주입 방법에 대해 잘 모른다면 아래 포스팅을 참고)

https://growth-coder.tistory.com/73

 

[Spring][스프링 핵심 원리] 의존 관계 주입 방법 및 옵션 처리

본 포스팅은 김영한 강사님의 인프런 강의 "스프링 핵심 원리 - 기본편"을 정리한 포스팅으로 강의 자료에서 사용한 자료를 사용했음을 밝힙니다. https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%E

growth-coder.tistory.com

 

코틀린도 크게 다르진 않지만 자바와의 약간의 차이점이 있어서 이번 포스팅에서 정리해보려고 한다.

 

생성자 주입과 필드 주입에 대해서만 알아보자.

 

HelloService라는 서비스가 이미 빈으로 등록되어있다고 가정한다.

1. 생성자 주입 

먼저 java에서 생성자 주입 방식으로 의존성을 주입하는 방식을 알아보자.

<Java>

@RestController
public class HelloController {
    private HelloService helloService;
    @Autowired
    public HelloController(HelloService helloService){
        this.helloService = helloService;
    }
}

 

생성자의 파라미터로 HelloService를 받는 모습을 볼 수 있고 생성자에 @Autowired가 붙어있는 모습을 확인할 수 있다.

 

참고로 생성자가 하나라면 @Autowired를 붙이지 않아도 된다.

 

그런데 만약 주입받아야 할 서비스가 늘어난다면 생성자를 수정해야하는 번거로움이 있다.

 

이럴 때는 @RequiredArgsConstructor를 사용하면 편하게 사용할 수 있다.

@RestController
@RequiredArgsConstructor
public class HelloController {
    private final HelloService helloService;
}

 

final, @NonNull이 붙은 필드에 대해 생성자 주입을 자동으로 생성해준다.

 

다음은 kotlin에서 생성자 주입 방식으로 의존성을 주입하는 방식을 알아보자.

<Kotlin>

@RestController
class HelloController(val helloService: HelloService) {
}

java에 비해서 간단한 모습을 볼 수 있다.

 

java는 생성자 파라미터로 받아서 필드에 저장을 하지만 kotlin에서는 클래스의 프로퍼티를 정의할 수 있기 때문에 따로 필드를 만들지 않아도 된다.

 

2. 필드 주입

<Java>

@RestController
public class HelloController {
    @Autowired private HelloService helloService;
}

 

필드에 대해서 직접 @Autowired를 붙여서 주입을 받는 방식이다.

 

<Kotlin>

@RestController
class HelloController {
    @Autowired
    lateinit var helloService: HelloService
}

 

코틀린은 기본적으로 프로퍼티를 사용하지 않는 이상 필드를 초기화하지 않고 생성하는 것이 불가능하다.

 

그럴 때 나중에 초기화하겠다는 뜻인 lateinit을 사용할 수 있다.

 

lateinit을 사용한 필드는 나중에 반드시 초기화를 해야 한다.

 

lateinit을 사용하지 않고 null로 초기화해도 된다.

@RestController
class HelloController {
    @Autowired
    var helloService: HelloService? = null;
}

 

코틀린은 기본적으로 null을 허용하지 않아서 null을 허용한다는 의미로 타입에 물음표를 붙여야 한다.

 

그런데 서비스에 null을 허용하는 순간 그 서비스에서 나오는 모든 반환 값은 null을 포함할 수 있기 때문에 해당 서비스를 사용할 때 null 가능성을 고려해야 한다.

 

lateinit을 사용한 필드는 사용하려는 클래스가 Bean에 등록되지 않았다면 주입을 할 수 없게되고 초기화 되지 않았다는 에러를 뱉으며 서버가 실행되지 않는다.

 

그런데 null을 허용했다면 사용하려는 클래스가 Bean에 등록되지 않았더라도 일단 null로 초기화 한 후 서버가 실행된다.

 

즉, 필드가 주입되지 않았다는 것을 컴파일 시점이 아닌 런타임 시점에 알 수 있다.

 

코틀린을 사용하는 장점이 없어지기 때문에 만약 필드 주입을 사용한다면 lateinit을 사용하는 것이 좋아보인다.

 

물론 필드 주입보다는 생성자 주입을 사용하는 것이 좋다.

 

728x90
반응형

댓글