Spring에서는 2-Layered 아키텍처를 자주 사용합니다.
2-Layered 아키텍처는 쉽게 말해서 MVC 를 이루는 Presentation Layer와 비지니스 기능을 수행하는 Business Layer 2계층으로 구성되어있는 구조를 말합니다.
앞선 포스트에서 왜 DAO 클래스를 바로 사용하면 안되고, 비지니스 컴포넌트를 사용해서 기능을 구현해야되는지 다루었습니다.
그럼 이번 포스트에서는 해당 과정에서 생기는 문제는 어떻게 해결해야 되는지에 대해서 다루어보겠습니다.
해당 구조를 구현하는데에서 가장 대표적으로 발생하는 문제점은 아마 @Autowired 에서 발생하는 NoSuchBeanDefinitionException 일 것입니다.
위의 문제는 어노테이션으로 의존성 주입을 하려할 때, 객체에 관련 타입의 메모리가 없어서 의존성을 주입할 수 없다는 메시지입니다.
즉 DispatcherServlet 관련 객체를 생성하는 스프링 설정 파일이 @Autowired 에서 사용되는 객체를 생성하는 스프링 설정 파일보다 먼저 불려서 문제가 발생하는 것입니다.
@Autowired 로 객체를 찾으려고 하는데, 아직 만들어지지 않아 문제를 발생하는 것이지요.
(Spring은 구조가 가장 어려운 것 같습니다. ㅜㅜ)
이를 해결하기 위해서는 @Autowired 에서 사용되는 객체를 먼저 만들어주어야 할 것입니다. 즉, Spring 설정 파일이 불리는 순서를 변경하면 되는 것입니다.
먼저 이를 부르기 위해서는 동일 위치에 ContextLoaderListener 를 등록해야합니다.
이는 클라이언트의 요청이 없어도 컨테이너가 구동될 때, Pre-Loading 되는 객체라고 생각하시면 됩니다.
기존에 존재하는 web.xml 에 아래의 코드를 작성해서 클래스를 등록하시면 됩니다.
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
근데 해당 코드만 작성하고 돌렸을 때, FileNotFoundException 문제가 발생한다면 아래와 같은 이유 때문일 것입니다.
이유는 ContextLoaderListener가 기본적으로 /WEB-INF/applicationContext.xml 파일을 읽는데, 설정 파일이 해당 위치에 없는 것입니다.
따라서 기존 위치의 applicationContext.xml을 복사해서 알맞은 위치에 붙여넣어도 되는데, 문제는 그러면 동일한 파일이 2개가 있어서 유지보수에 어려움이 발생할 수 있다는 것입니다.
그래서 위와 같이 복사를 통해 문제를 해결하기 보다는 아래의 코드를 역시 web.xml에 추가해서 문제를 깔끔하게 해결할 수 있습니다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value>
</context-param>
그러면 이제는 문제 없이 contextLoaderListner 객체를 생성하게 되고, applicationContext가 먼저 불려 관련 객체를 생성해서 2-Layered 아키텍처를 잘 구현할 수 있게 될 것입니다.