Chapter#01 : [Spring] IntelliJ를 사용한 Spring Project 생성 및 설정(Maven)
Chapter#02 : [Spring] Spring MVC 패턴 적용하기
Chapter#03 : [Spring] Component-Scan을 사용하는 Annotation 기반 설정
Chapter#04 : [Spring] MyBatis를 사용한 DataBase 연동
#1. 컴포넌트 개념 요약
1) 컴포넌트란?
(#1. 공통 컴포넌트개념, #2. 공통 컴포넌트 구성 별도 정리 .p595)
2) 프레젠테이션 레이어와 비즈니스 레이어 통합
스프링 프레임워크 기반의 웹 프로그램은 두 개의 레이어(프레젠테이션 레이어, 비즈니스 레이어)로 아키텍처를 나눈다.
- 프레젠테이션 레이어는 DispatcherServlet과 Controller, JSP등으로 구성된다.
- 비즈니스 레이어는 Service 인터페이스와 ServiceImpl 클래스 등으로 구성된다.
그림 - p596 공통 컴포넌트 아키텍처
개발 프레임워크 기반 공통 서비스는 개발 프레임워크의 개발 환경을 고려해
모델( View ), 뷰( View ), 컨틀럴러( Controller )를 분리해서 개발되었다.
또한 데이터 처리 계층 및 SQL의 분리를 통해서 데이터베이스 변동에 유연하게 대응할 수 있게 설계되었다.
그림 - 개발 프레임워크 - 기반 공통 서비스
2) 2-Layered 아키텍처란?( p.518 )
3) @Component 어노테이션 확장
프레젠테이션 레이어는 사용자와의 커뮤니케이션을 담당하는 화면이고,
비즈니스 레이어는 사용자의 요청에 대한 비즈니스 로직 처리를 담당한다.
이 구조에서 핵심 요소는 Controller, ServiceImpl, DAO 클래스이다.
Controller 클래스는 사용자의 요청을 제어하며,
ServiceImpl 클래스는 실질적인 비즈니스 로직을 처리한다.
그리고 마지막으로 DAO 클래스는 실질적인 데이터 베이스 연동을 담당한다.
@Component 어노테이션은 스프링컨테이너가 해당 클래스 객체를 생성하도록 설정할 수 있다.
그런데 시스템을 구성하는 이 모든 클래스에 @Component를 할당하면
어떤 클래스가 어떤 역할을 수행하는지 파악하기 어렵다.
스프링 프레임워크는 이런 클래스들을 분류하기 위해 @Comonent를 상속하여
다음과 같은 세개의 어노테이션을 추가로 제공한다.
어노테이션 | 위치 | 의미 |
@Service | XXXServiceImpl | 비즈니스 로직을 처리하는 Service 클래스 |
@Repository | XXXDAO | 데이터베이스 연동을 처리하는 DAO |
@Controller | XXXController | 사용자 요청을 제어하는 Controller |
물론 어노테이션을 나눈 이유가 단순히 해당 클래스를 분류하기 위해서만은 아니다
@Controller는 해당 객체를 MVC( Model - Vew - Controller ) 아키텍처에서 컨트롤러 객체로 인식하도록 해주며,
@Repository는 DB 연동 과정에서 발생하는 예외를 변화해주는 특별한 기능이 추가되어 있다.
#2. 리스너를 등록하여 비즈니스 컴포넌트 호출 설정
( web.xml에 ContextLoaderListener 적용하기)
DispatcherServlet이 생성한 스프링 컨테이너는 Controller 객체들만 생성한다.
하지만 Controller 객체들이 생성되기 전에 누군가 먼저 resources 소스 폴더에 있는
context-XXX.xml 파일들을 읽어 비즈니스 컴포넌트들을 메모리에 생성해야 한다.
이때 사용하는 클래스가 스프링에서 제공하는 ContextLoaderListener다.
ContextLoaderListenr도 DispatcherServlet과 마찬가지로 스프링 컨테이너를 구동하는 기능이 구현되어 있다.
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
version="4.0">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/context-*.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- 서블릿 설정 -->
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
1) Lisener 등록
Lisener는 Servlet이나 Filter 클래스와 마찬가지로 web.xml 파일에 등록한다.
<listener> 태그 하위에 <listener-class> 태그를 이용하여 스프링에서 제공하는
ContextLoaderListenr 클래스를 등록하면 된다.
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
중요한 것은 ContextLoaderListener 클래스는 servlet 컨테이너가 web.xml 파일을 읽어서 구동될 때,
자동으로 메모리에 생성된다.
즉 ContextLoaderListener는 클라이언트의 요청이 없어도 컨테이너가 구동될 때 Pre-Loading되는 객체이다.
2) ContextLoaderListenr 등록
web.xml 파일에 ContextLoaderListenr 클래스를 서블릿 설정위에 등록한다.
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:spring/context-*.xml</param-value>
</context-param>
contextLoaderListenr가 Pre-Loading되어 스프링 컨테이너를 구동할 때,
src/main/resources 소스 폴더에 작성한 스프링 설정 파일들( 'context'로 시작하는 모든 XML )을 로딩하도록
엘리먼트위에 을 추가했다.
이제 web.xml을 파일을 저장하고 서버를 재구동해보자.
그러면 ContextLoaderListenr 객체가 Pre-Loading되어 스프링 컨테이너를 먼저 구동하고 이때,
비즈니스 컴포넌트 객체들이 생성된는 것을 확인 할 수 있다.
#3. 비즈니스 컴포넌트 설정
( 어노테이션 기반의 Service, Repository 구현하기 )
대부분의 컨테이너는 컨테이너가 구동될 때 XML 설정 파일( Servlet 컨테이너는 web.xml )을 읽어들인다.
그리고 읽어들인 XML 파일로부터 자신이 생성하고 관리할 객체들의 정보를 확인한다.
스프링 프레임워크는 스프링 컨테이너의 동작과 기능을 XML 설정파일을 통해 제어하므로 XML 설정이 매우 중요하다.
하지만 이런 XML 설정이 너무 복잡하고 방대하다면 오히려 프레임워크 사용을 어렵게 만들 수도 있다.
따라서 Spring Framework에서는 어노테이션( Annotation )을 이용한 설정을 통해 이런 XML 부담을 줄여준다.
1) context-common.xml 파일 생성하기
먼저 필요없는 applicationContext.xml 파일을 삭제한다.
그럼 본격적으로 context-common.xml 파일을 생성한다.
먼저 context-common.xml의 경로를 잡아주어야 하는데
프로젝트를 선택하고 마우스 우클릭하여 resources
이제 생성한 resources 디렉토리를 Resources Root 디렉토리로 지정을 해 주어야 한다.
Project Structure 팝업창이 뜨면 다음순서로 작업을 진행한다.
먼저 위에서 생성한 resources 디렉토리를 선택하고 상단 메뉴의 Mark as : Resources를 선택해준다.
Resources Root 디렉토리 설정을 완료하면
이제 다시 resources 디렉토리를 선택하고 spring 디렉토리를 추가해준다.
다시 spring 디렉토리를 선택하고 마우스 우클릭하여 context-common.xml 파일을 생성한다.
2) 컴포넌트 스캔 설정( p.306 )
스프링 설정 파일에 Application에서 사용할 클래스들을 <bean> 등록하지 않고 자동으로 객체로 생성하려면
<context:component-scan/>이라는 엘리먼트를 설정해야 한다.
이 설정을 추가하면 스프링 컨테이너는 class 경로에 있는 class들을 스캔하여
@Component가 정의된 클래스들을 자동으로 객체로 생성한다.
context-common.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.2.xsd
">
<!-- @Service, @Repository만 include -->
<context:component-scan base-package="org.spring.example.*" use-default-filters="true">
<!-- Controller는 자동 스캔에 포함시키지 않는다. -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
</beans>
여기서 중요한것은 <context:component-scan> 엘리먼트의 base-package 속성인데,
만약 속성값을 「 org.spring.example.service 」형태로 지정하면
org.spring.example.service 패키지로 시작하는 모든 패키지를 스캔대상에 포함하게 된다.
따라서 다음과 같은 클래스들이 대상이 된다.
- org.spring.example.service
- org.spring.example.service.imp
- org.spring.example.service.common
하지만 실제 작성한 소스의 base-package 속성값은 「 org 」 이므로
org로 시작하는 모든 패키지들의 클래스들이 대상이 되는것이다.
<context:omponent-scan> 엘리먼트는 <context:exclude-filter>와 <context:include-filter>를 자식으로 가질 수 있다.
<context:exclude-filter>는 특정 어노테이션을 배제할 때 사용하고,
반대로 <context:include-filter>는 포함시킬 때 사용한다.
<!-- @Service, @Repository만 include -->
<context:component-scan base-package="org.spring.example.*" use-default-filters="true">
<!-- Controller는 자동 스캔에 포함시키지 않는다. -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
위 설정은 @Controller라는 어노테이션은 컴포넌트 스캔할 때 제외하고
@Controller 이외의 다른 어노테이션( @Service, @Repository )은 컴포넌트 스캔에 포함시키라는 의미의 설정이다.
#4. 프레젠테이션 컴포넌트 설정
( 어노테이션 기반의 Controller 구현 )
Spring MVC에서는 어노테이션을 사용하여 복잡한 XML 설정을 최소화할 수 있다.
스프링에서 사용하려면 먼저 <beans>루트 엘리먼트에 context 네임스페이스를 추가하고
<context:component-scan>엘리먼트를 추가한다.
dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/mvc
https://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven></mvc:annotation-driven>
<context:component-scan base-package="org.spring.example.controller" use-default-filters="true">
<!-- Controller는 자동 스캔에 포함 시킨다. -->
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:include-filter>
<!-- Service, Repository는 자동 스캔에 제외 시킨다. -->
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"></context:exclude-filter>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"></context:exclude-filter>
</context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"></property>
<property name="suffix" value=".jsp"></property>
<property name="order" value="1"/>
</bean>
</beans>
위 설정은 모든 Controller 클래스들을 스캔 범위에 포함시키기 위해
<context:component-scan>엘리먼트의 base-package 속성값을 org.spring.example.controller 로 등록했다.
( 추후 * 사용에대하여 테스트 해볼것 )
그리고 스캔 대상에서 Controller 클래스들만 포함시키고 ServiceImpl 클래스와 DAO 클래스는 제외시키기 위해서
<context:include-filter>엘리먼트로 Controller( org.springframework.stereotype.Controller )를 설정하였고
<context:exclude-filter>엘리먼트는 Service( org.springframework.stereotype.Service )와
Repository( org.springframework.stereotype.Repository )를 설정하였다.
해당 포스팅의 내용을 다 적용한 상태에서 Tomcat을 실행하여 브라우저의 결과를 확인 하였을때
이전 포스팅과 같은 결과물이 나와야 문제없이 다음 MyBatis를 이용한 DataBase 연결 작업을 진행 할 수 있다.
'Spring Web > Spring Framework' 카테고리의 다른 글
[Spring] src/main/resources 경로 폴더 형태로 노출 (2) | 2023.03.30 |
---|---|
[Spring] MyBatis를 사용한 DataBase 연동 - MySQL (0) | 2022.12.09 |
[Spring] Spring MVC 패턴 적용 (0) | 2022.12.08 |
[Spring] IntelliJ를 사용한 Spring Project 생성 및 설정(Maven) (2) | 2022.11.29 |
[Spring] Android Studio GIT - Clone 기존 GIT 프로젝트와 연결 (0) | 2022.11.08 |