intelij(프리미엄판)를 막 도입해서 사용하는 회사에 다닐 때, eclipse에서 쓰던 프로젝트를 intelij로 옮겼을때가 있었는데,
거기서 보면 Sping의 의존주입 방식을 Warning으로 처리되는 경우가 있다.
inteij는 굉장히 assist가 좋은 ide tool이기 때문에 현재 코드보다 더 나은 코드 방향을 제시해준다.
중복되는 코드를 하나의 클래스로 묶어준다던지, 더 좋은 제안을 tool자체에서 해준다.
어째든 사설이 길었는데, eclipse에서는 @Autowired를 이용해서 DI를 했었다.
근데 이게 intelij로 오니 Warning으로 나오는 것이다.
예를 들어, 어떤 클래스에 Spring Bean 객체를 생성하는데,
@Autowired를 이용해서
@Controller
public class ExampleController {
@Autowired
private ExampleService exampleService;
...생략
}
이렇게 코딩을 해놓으면
intelij에서는
@Controller
public class ExampleController {
private final ExampleService exampleService;
@Autowired
public void ExampleController(ExampleService exampleService) {
this.exampleService = exampleService;
}
...생략
}
이런 식의 의존 주입을 하기를 원한다.
이제 그래서 이유를 알아야 하는데 생성자를 이용한 의존 주입(DI)을 하게 되면,
첫 번째, 불변 객체를 만들 수 있다.
-> final을 이용한 코딩이 가능해진다.
두 번째, 순환 참조를 막아 준다.
-> A Service에서 B Service를 부르고, 다시 B Service에서 A Service를 불렀을 때, 그리고 해당 빈을 사용하는 타이밍에 코드를 실행하게 되면(보통 이런 식으로 코딩하는 경우가 있나?), 스택에 계속 데이터가 쌓여서 결국
StackOverflowError: null
위와 같은 스택이 터졌다는 문구와 함께 에러가 나게 된다.
생성자를 사용하면 컨테이너가 빈을 생성하는 시점에서 객체 생성에 사이클 관계가 생기기 때문에, 오류가 없이 잘 구동될 것이다.
세 번째, 객체가 생성될 때 의존 객체의 null여부를 검사해서, 컴파일 시에 오류를 발생시키니 런타임 때 오류가 발생하는 경우를 미연에 방지해준다.
-> 가끔 저 빈을 부르는 타이밍이 이상하면 nullPointerException이 나는 경우들이 있다.
하지만, 생성자로 의존 주입을 하게 되면 그걸 미연에 방지해주는 역할을 한다.
네 번째, 테스트 코드를 작성하기 좋아진다.
-> 테스트 코딩을 잘 작성하지 않아서 뭔가 살로 와닿지는 않는데, (테스트 코딩을 많이 하는 게 나중에 회사를 들어가서도 괜찮은 개발자라는 칭호를 들을 가능성이 점점 높아진다. -> 테스트 코딩해야겠지?) 첫 번째와 같은 @Autowired 주입을 하는 경우가 field injection을 사용한 주입으로 불러지는데, field injection을 하게 되면, 스프링의 IoC 컨테이너가 다 생성해서 주입해 주는 방식이 되어 버려서 외부로 노출되는 것이 하나도 없다. 그래서 의존관계를 가지고 있는 메서드의 단위 테스트를 하면 NullpointerException이 발생하게 된다.
예전 회사를 다니면서, 해당 코드로 쓰게 되었는데, 정리를 하는 건 참 늦어졌다. 그때그때 정리하면 좋은데, 그 당시에 일도 바쁘고, 이해하는데도 시간이 걸리니 한참을 미뤄놓았다가 쓰게 되는 것 같다. (사실 근데 돈 주고 사용하는 인텔리제이에서 더 선호하는 방식으로 주는데 안 할 이유가 ㅋㅋ..)
코드를 짜는 것도 좋지만 왜 구조가 더 좋아지는지, 이걸 더 선호하는지 알고 짜는 게, 확실히 코딩에 이유가 생기게 되는 것 같다. 위에도 말했다시피 테스트 코드도 많이 짜는 사람이 되어야 할 것 같다..(테스트 코드 진짜 쉽지 않다.. 난 syso("@@@ : " + 변수) 뿐인데.. ㅋㅋ)
댓글