[SPRING] 웹 개발 환경 설정 파일

Q0. 개요

프로젝트에 투입되어 개발을 하다보면 이미 구축된 환경에서 반복적인 개발을 하는 경우가 많다. 
때문에 기본적인 환경 설정과 각 설정이 가지는 원리에 대해서는 생각을 해본 적이 없다

자바에서 Mybatis기반의 Mapper를 어떻게 찾는지, DB정보는 어디서 선언되어 실행되는지와 같은 설명들을 남들에게 설명해주려다 보니 말문이 막혔다. 애매하게 아는 것들이 많아서 오늘은 전체적인 스프링의 기본 환경 설정 파일에 대해 정리를 해보려고 한다.

참고로, 환경설정의 파일명과 위치가 달랐던 이유에 대한 부분에 초점을 맞춰서 주요 기능을 정리하였다.

 

Q1. 환경 설정 파일 정리

참고로, 웹 어플리케이션을 실행하는데 필요한 클래스 파일, 설정 파일은 WEB-INF 폴더에서 관리한다.

1. 자바 웹 애플리케이션 설정 파일

정의 : 스프링 프레임워크에서 WAS를 실행할 때, web.xml를 읽어서 메모리에 함께 올라가면서 동작을 준비하는(배포되는) 설정 파일. 때문에, 파일이 수정되면 꼭 재기동을 해야만 한다. 자바 웹 애플리케이션은 DD(Deployment Descriptor)파일이라는 배포설명자를 이용하다보니, 배포설명자라고도 불리는데 이를 사용하여 URL이 서블릿에 매핑되는 방법, 인증이 필요한 URL 등이 작성되어 있다. (브라우저가 Java Servlet에 접근하기 위해 WAS에게 필요한 정보를 알려줘서 Servlet의 호출을 돕는다고 보면 된다)
위치 : src/webapp/WEB-INF/web.xml
파일 : web.xml
용도 : ①ServletContext 초기 파라미터 ②Session의 유효시간 설정 ③Servlet/JSP에 대한 정의 ④ Mime Type 매핑 ⑤인코딩 설정  Welcome File List ⑦ Error Pages 처리  Listener/ Filter 설정 보안 제약 등
구조

더보기
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_1.xsd"
	version="3.1"><!-- 0. Servlet 버전은 3.1 -->

    <!-- 1. ServletContext 초기 파라미터 설정
    자바에서 아래와 같이 초기 설정된 파라미터를 사용할 수 있다
    String sample = getServletContext().getInitParameter("sampleParam1");   
    -->
    <context-param>
        <param-name>sampleParam1</param-name>
        <param-value>sampleValue</param-value>    
    </context-param>

    <!-- 2. Session의 유효시간 설정(단위: 분) 
    설정된 시간이 지나면 시스템에서 유지 중인 세션이 아웃된다.
    우선 순위 1. 자바에서 request.getSession().setMaxInactiveInterval(초 단위)
    우선 순위 2. web.xml에서 <session-timeout>분 단위</session-timeout>
    우선 순위 3. [톰캣 설치 디렉터리]/conf/web.xml에 설정된 timeout 분 단위 값
    -->
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>

    <!-- 3-1. Servlet 환경설정 
    Servlet 또는 JSP에 대한 환경설정을 제어한다.
    <servlet>: Servlet/JSP정의
    <servlet-mapping>: Servlet/JSP매핑
    contextConfigLocation: ServletContext관련 환경설정 xml파일의 위치를 설정한다. 
    load-on-startup: 실행 순서를 지정한다.
    --> 	
    <servlet> 
        <servlet-name>dispatcherServlet</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>dispatcherServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>    

	<!-- 3-2. Spring 환경설정 -->
	<context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>    

    <!-- 4. MIME 타입 매핑 
    선택적으로 요청된 파일 확장자에 따라 리소스의 유형을 정확하게 MIME 타입과 매핑을 한다. 
    Content-type은 서버에서 클라이언트로 응답되는 리소스의 타입이라면
    Mime-type은 주로 파일의 종류를 나타내는대에 사용된다.
    -->
    <mime-mapping>
        <extension>png</extension>
        <mime-type>image/png</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>jpg</extension>
        <mime-type>image/jpeg</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>txt</extension>
        <mime-type>text/plain</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>html</extension>
        <mime-type>text/html</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>css</extension>
        <mime-type>text/css</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>js</extension>
        <mime-type>application/javascript</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>json</extension>
        <mime-type>application/json</mime-type>
    </mime-mapping>
    <mime-mapping>
        <extension>pdf</extension>
        <mime-type>application/pdf</mime-type>
    </mime-mapping>
    
    <!-- 5. 필터를 이용한 인코딩 설정  
    CharacterEncodingFilter: 필터를 이용한 문자 인코딩 설정
    <filter-mapping>: 모든 요청에 대한 문자 인코딩 필터 매핑
    필터가 아닌 MIME를 이용하여 인코딩할 경우 <mime-type>text/html; charset=UTF-8</mime-type>
    필터는 요청 리소스를 보안/로깅/성능최적화 등에도 사용된다.
    --> 
    <filter>
        <filter-name>encodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>encodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--6. 초기 페이지 설정 
    시스템의 초기 주소를 입력했을때 표시할 페이지를 설정한다.
    -->
    <welcome-file-list>
        <welcome-file>index.html</welcome-file>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>    
    
    <!-- 7. 에러 페이지 설정 
    에러가 발생할경우 해당 파일로 이동하도록 설정한다.
    <error-code>: 에러코드에 따라 구분된다
    <exception-type>: 에러타입에 따라 구분된다
    코드,타입구분이 없으면 기본 에러페이지로 지정된다.
    -->
    <error-page>
        <error-code>403</error-code>
        <location>/error403.jsp</location>
    </error-page>    
    <error-page>
        <error-code>404</error-code>
        <location>/error404.jsp</location>
    </error-page>
    <error-page>
        <error-code>500</error-code>
        <location>/error500.jsp</location>
    </error-page>    
    <error-page>
        <exception-type>java.lang.NullPointerException</exception-type>
        <location>/nullPointerErr.jsp</location>
    </error-page>    
    <error-page>
        <location>/genericError.jsp</location>
    </error-page>

    <!-- 8. 리스너/필터 설정 
    스프링 컨텍스트(ApplicationContext)나 커스텀으로 MyContextListener등을 로딩하고 관리한다.
    각 클래스가 리스너로 실행될 때 스프링 컨텍스트가 초기화되어 빈들이 로드되고 관리된다.
    -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <listener>
        <listener-class>com.sample.SampleContextListener</listener-class>
    </listener>    

    <!-- 9. 보안 설정 
    <web-resource-collection>: 보안 범위를 지정
    <auth-constraint>: 보안 권한을 지정
    <form-login-config>: 로그인할 페이지와 로그인 에러페이지를 지정
    -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>security</web-resource-name>
            <url-pattern>/secured/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>USER</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>form</auth-method>
        <realm-name>realm</realm-name>
        <form-login-config>
            <form-login-page>/login.jsp</form-login-page>
            <form-error-page>/login-error.jsp</form-error-page>
        </form-login-config>
    </login-config>

</web-app>

 

 

2. 스프링 컨테이너 관련 xml 설정 파일 

정의 : 스프링 프레임워크에서 가장 핵심적인 컴포넌트인 스프링 컨테이너에서는 자바 객체(빈)의 생명주기(LifyCycle)를 관리하는 설정 파일. 스프링 컨테이너에는 Application Context와 Bean Factory 2가지 종류가 있는데, Bean Factory는 자바 객체(빈)을 생성하고 조회하는 역할을 하는 인터페이스. Application Context는 Bean Factory를 포함한 여러 인터페이스를 상속받는 인터페이스. 일반적으로 스프링 컨테이너는 Application Context를 의미하며, Bean Factory를 통해 빈을 관리/검색하지만 그 외 다른 인터페이스를 통한 부가 기능들이 제공된다.

[웹 애플리케이션 전체에 대한 스프링 설정 파일]
위치 : web.xml 파일에서 <context-param>요소의 contextConfigLocation속성에 지정된 classpath경로 내의 파일 위치.
파일 : 보편적으로 application-context.xml (사용자 정의에 따라 명칭과 파일 세분화 관리 가능)
용도 : ①WAS의 argument를 이용한 실행환경별 properties설정.  ② 접근할 DB정보들을 설정trace설정  ④자바와 SQL을 자동으로 매핑 설정 ⑤어노테이션 기반의 트랜잭션을 설정 ⑥Redis관련 설정 ⑥언어 정보 별 메시지 설정 ⑦스프링 시큐리티 설정 ⑧ Servlet설정 등
구조

더보기
<!-- Spring관련 설정의 applicationContext.xml -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 1.WAS의 argument를 이용한 실행환경별 properties설정 
    아래는 서버 타입별로 db와 그외의 properties정보를 분리해서 매핑하는 내용이다.
    <property name="location">을 생략하고 <property value="...">로 해도 동일하다.
    --> 
    <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property value="/properties/application-#{systemProperties['spring.profiles.active']:?'LOCAL'}.properties" />
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>    
    <util:properties id="DB" location="classpath:/properties/db-#{systemProperties['spring.profiles.active']?:'LOCAL'}.properties" />
    <!--<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location">
            <value>classpath:/properties/db-#{systemProperties['spring.profiles.active']:?'LOCAL'}.properties" />
        </property>
        <property name="ignoreUnresolvablePlaceholders" value="true" />
    </bean>-->


    <!-- 2. 접근할 DB정보들을 설정
    Maven의 경우에 프로젝트 설정파일에서 오라클JDBC(OJDBC)드라이버 사용을 위해
    프로젝트의 의존성에(=pom.xml) 오라클 DB의 JDBC 드라이버를 추가해야한다.
    여기서 의존성은 각 라이브러리(=dependency)를 의미하며, 적절한 버전을 사용한다

    <dependencies>
        <dependency>
            <groupId>com.oracle.database.jdbc</groupId>
            <artifactId>ojdbc8</artifactId>
            <version>19.3.0.0</version>
        </dependency>
    </dependencies>    
    -->    
    <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
        <property name="driverClassName" value="oracle.jdbc.OracleDriver" />
        <property name="url" value="#{DB['database.url]}"/> <!--${database.url}-->
        <property name="username" value="#{DB['database.username]}"/> <!--${database.username}-->
        <property name="password" value="#{DB['database.password]}"/> <!--${database.password}-->
    </bean>

    <!-- 3. trace설정 
    applicationContext에서의 trace설정은 로깅 프레임워크의 로그 레벨을 설정하는 것을 의미한다.
    로깅 프레임워크에서 가장 많이 사용되는 것 중 하나는 Log4j이다.
    해당 프레임워크에서의 로그 레벨은 TRACE, DEBUG, INFO, WARN, ERROR, FATAL등이 있다.
    여기서 TRACE는 가장 상세한 로그 레벨로서, 디버깅 및 세부적인 정보를 기록할 때 사용한다. 
    
    [Maven의 경우 Log4j의존성 추가 -> applicationContext로딩시 Log4j초기화되며 설정된 Log4j파일 로딩]
    pom.xml에 먼저 Log4j의존성이 필요하다.
    <dependencies>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>    

    그리고 src/main/resources폴더에 log4j.xml 또는 log4j.properties파일을 작성한다.
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE log4j:configuration PUBLIC "-//APACHE//DTD LOG4J 1.2//EN" "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
    <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">

        <appender name="console" class="org.apache.log4j.ConsoleAppender">
            <layout class="org.apache.log4j.PatternLayout">
                <param name="ConversionPattern" value="%d{ABSOLUTE} %5p %c{1}:%L - %m%n" />
            </layout>
        </appender>
        <root>
            <priority value="trace" />
            <appender-ref ref="console" />
        </root>
    </log4j:configuration>
    -->
    <bean id="log4jInitialization" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetClass" value="org.springframework.util.Log4jConfigurer"/>
        <property name="targetMethod" value="initLogging"/>
        <property name="arguments">
            <list>
                <value>classpath:log4j.xml</value>
            </list>
        </property>
    </bean>

    <!-- 4. 자바와 SQL을 자동으로 매핑 설정 
	먼저 1,2번의 DB세팅이 되어있어야 한다.
    
    그리고 Maven을 이용하는 경우 pom.xml에 Spring Mybatis 모듈 의존성(=라이브러리)를 추가한다.
    <dependencies>
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.2.0</version>
        </dependency>    
    </dependencies>    

    아래의 com.example.mapper패키지 경로에 자바 인터페이스를 
    sqlSessionFactory의 경로에 mapper.xml 파일을 작성하면 MVC패턴을 호출시 자동 매핑되어 SQL이 자바에서 호출된다.
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.mapper"/>
    </bean>    
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/>
        <property name="mapperLocations" value="classpath:/mapper/*.xml"/>
    </bean>
    
    <!-- 5. 어노테이션 기반의 트랜잭션을 설정 
    아래의 옵션만 지정하면 @Transactional 또는 @EnableTransactionManagement가 활성화된다.
    자바 비즈니스 로직의 메서드 단에서 @Transactional를 사용한다.
    해당 @Transactional 어노테이션에는 몇가지 옵션들이 있다.
    - propagation: 트랜잭션 전파 속성 설정
    - isolation: 격리 수준 설정
    - readOnly: 읽기 전용 트랜잭션 여부 설정
    - timeout: 트랜잭션 제한 시간 설정
    - rollbackFor: 예외 클래스를 이용한 트랜잭션 롤백 설정
    -->
    <context:annotation=config/>
    <tx:annotation-driven/>
    
    <!-- 5-1. 메서드 이름패턴에 따라 포인트컷을 이용한 트랜잭션 전파 설정 -->
	<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="dataSource"/>
	</bean>
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="*" rollback-for="Exception"/>
			<tx:method name="*" no-rollback-for="NoRollbackException"/>
		</tx:attributes>
	</tx:advice>
	<aop:config>
		<aop:pointcut id="requiredTx" expression="execution(* com.example.service.*Impl.*(..))"/>
		<aop:advisor advice-ref="txAdvice" pointcut-ref="requiredTx" />
	</aop:config>
   
    <!-- 6. 언어 정보 별 메시지 설정 
    defaultEncoding: 인코딩 설정
    cacheSeconds: 파일이 변경되었는지를 확인하기 위해 초 단위 캐시 설정
    basenames: WEB-INF밑의 message폴더 아래에 labels로 시작하는 모든 properties를 설정하여
               메시지 파일의 위치를 지정하고 message_언어.properties파일을 찾는다.
    messageSourceAccessor: MessageSourace사용을 위한 Accessor설정
    MessageUtils: 커스텀으로 MessageSource를 사용하기위한 MessageUtils 매핑
    localeResolver: 언어 정보를 세션에 저장하여 사용
    defaultLocale: 기본적인 언어 파일 인코딩을 설정
    -->
	<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
		<property name="cacheSeconds" value="60"/>
		<property name="basenames">
			<list>
				<value>/WEB-INF/resources/message/message</value>
			</list>
		</property>
	</bean>
	<bean id="messageSourceAccessor" class="org.springframework.context.support.MessageSourceAccessor">
		<constructor-arg ref="messageSource"/>
	</bean>
	<bean id="message" class="com.example.base.util.MessageUtils">
		<property name="messageSourceAccessor" ref="messageSourceAccessor"/>
	</bean>	
	<bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
		<property name="defaultLocale" value="ko"></property>
	</bean>

    <!-- 8-1. 스프링 시큐리티 설정  
    <mvc:annotation-driven/>: 스프링 MVC 어노테이션을 사용할 수 있다.
    <context:component-scan...: 경로에 어노테이션과 같은 스프링 컴포넌트를 시캔하여 빈으로 등록한다.
    restAuthenticationEntryPoint: 사용자 인증이 필요한 리소스에 접근 시 커스텀 entry Point를 사용할 수 있도록 설정한다.
    <security:http....: 여러 <intercept-url>을 추가 및 수정하여 보안 규칙을 설정한다.
    <security:authentication-manager>에서 authentication-provider>의 ref 속성을 사용하여 사용자 정의 인증 프로바이더를 등록한다.
    <beans:bean...>: 경로에 해당하는 클래스파일을 빈으로 등록한다.
    -->
    <mvc:annotation-driven/>
    <context:component-scan base-package="패키지경로"/>
    <security:http entry-point-ref="restAuthenticationEntryPoint" use-expressions="true">
        <csrf disabled="true"/>
        <headers>
            <frame-options disabled="true"/>
        </headers>
        <intercept-url pattern="/**" access="permitAll"/>
        <form-login
            login-processing-url="/api/loginProcess"
            username-parameter="username" password-parameter="password"
            authentication-success-handler-ref="mySuccessHandler"
            authentication-failure-handler-ref="myFailureHandler"
            default-target-url="/main"
            always-use-default-target="true"/>
        <logout
            invalidate-session="true"
            logout-url="/api/logoutProcess"
            success-handler-ref="myLogoutSuccessHandler"
            delete-cookies="JSESSIONID"/>
    </security:http>
    <authentication-manager>
        <authentication-provider ref="AuthenticationProvider"/>
    </authentication-manager>
    <beans:bean id="AuthenticationProvider" class="com.example.base.spring.security.AuthenticationProvider"/>
    <beans:bean id="mySuccessHandler" class="com.example.base.spring.security.ApiAuthenticationSuccessHandler"/>
    <beans:bean id="myFailureHandler" class="com.example.base.spring.security.ApiAuthenticationFailureHandler"/>
    <beans:bean id="myLogoutSuccessHandler" class="com.example.base.spring.security.ApiLogoutSuccessHandler"/>

</beans>

[특정 서블릿에 대한 스프링 설정 파일]
위치 : web.xml 파일에서 <servlet>요소의 contextConfigLocation속성에 지정된 classpath경로 내의 파일 위치.
파일 : 보편적으로 servlet-context.xml (사용자 정의에 따라 명칭과 파일 세분화 관리 가능)
용도
 : ①정적 리소스 핸들러 설정  ②뷰 리졸버 설정 ③인터셉터 설정 ④파일 업로드 설정 ⑤어노테이션을 이용한 빈 생성 ⑥다국어 지원 ⑥LocaleResolver 설정 ⑦HandlerExceptionResolver 
구조 

더보기
    <!-- 1. 정적 리소스 핸들러 설정 
    요청 경로의 mapping의 패턴을 실제 정적 리소스의 location경로로 정적리소스로 매핑한다.
    단, cache-period에 작성된 초단위 캐시동안은 서버에서 가져오지 않고 캐시된 데이터를 이용하여 로딩 시간을 단축시키는 성능향상의 옵션도 있다.
    -->
    <mvc:resources mapping="/resources/**" location="/resources/" cache-period="86400"/>
    <resources mapping="/js/**" location="/js/" cache-period="3600"/>
    <resources mapping="/web/**" location="/web/" cache-period="14400"/>
    <resources mapping="/css/**" location="/css/" cache-period="2592000"/>
    <resources mapping="/images/**" location="/images/" cache-period="2592000"/>
    <resources mapping="/lib/**" location="/lib/" cache-period="3600"/>

    <!-- 2. 뷰 리졸버 설정 
    뷰 리졸버란, 스프링MVC에서 컨트롤러가 반환하는 뷰 이름을 실제 뷰로 변환하는 역할을 한다.
    먼저 <bean>을 이용하여 InternalResourceViewResolver, BeanNameViewResolver 등을 뷰 리졸버로 등록시킨다.
	prefix와 suffix의 옵션에 따라 /WEB-INF/views/경로에 있는 jsp확장자가 뷰로 사용된다.    
    -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    또는
    <beans:bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="0"/>
    <beans:bean class="org.springframework.web.servlet.view.UrlBasedViewResolver" p:order="1" p:viewClass="org.springframework.web.servlet.view.JstlView" p:prefix="/WEB-INF/views/" p:suffix=".jsp"/>
    
    
    <!-- 3. 인터셉터 설정 
    스프링MVC에서 컨트롤러의 메서드 실행 전,후,뷰 렌더링 이후 등의 특정 시점에서 필요한 작업을 수행하는 기능이다.
    주로, 요청과 응답에 대한 처리를 수행하며 권한체크, 로깅, 캐싱, 트랜잭션 등의 공통작업을 주로 다룬다.
    실제 클래스 파일에서 implements HandlerInterceptor를 이용하여 preHandle, postHandle, afterCompletion 메서드를 사용한다.
    -->
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/api/loginCheck" />
            <mvc:mapping path="/**/*.properties" />
            <bean class="com.example.MyLogInterceptor" />
        </mvc:interceptor>
    </mvc:interceptors>
    또는
    <interceptors>
        <interceptor>
            <mapping path="/**/*"/>
    		<exclude-mapping path="/**/*.properties"/>
    		<beans:bean class="com.example.MyLoginChkInterceptor"></beans:bean>
        </interceptor>
    </interceptors>    
        
    <!-- 4. 파일 업로드 설정 
    CommonsMultipartResolver: 파일 업로드를 위한 MultipartResolver 설정
    maxUploadSize: 최대 업로드 크기 설정 (바이트 단위)
    maxInMemorySize: 최대 메모리 크기 설정 (바이트 단위)
    uploadTempDir: 업로드된 파일의 임시 저장 경로 설정
    -->
    <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
        <property name="maxUploadSize" value="10485760"/> <!-- 10MB -->
        <property name="maxInMemorySize" value="4096" /> <!-- 4KB -->
        <property name="uploadTempDir" value="/path/to/temp/directory" />
    </bean>

    <!-- 5. 어노테이션을 이용한 빈 생성 
    패키지 경로에 해당하는 어노테이션을 빈으로 생성시킨다.
    단, 필터를 이용하여 패키지 내에 스캔할 대상을 지정할 수 있으며, 생략시 기본 필터를 이용하여 전체 스캔된다.
    -->
 	<context:component-scan base-package="com.example" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
	</context:component-scan>
    또는
    <context:component-scan base-package="com.example" />

    
    <!-- 6. 다국어 지원 (LocaleResolver) 
    먼저 localeResolver 빈을 이용하여 사용자의 지역을 읽는다.
    sessionLocaleResolver 이용하여 기본적으로 한국어로 디폴트 세팅을 하고
    messageSource빈의 ReloadableResourceBundleMessageSource를 사용하여 메시지를 로드하는데 사용한다.
	basename속성을 통해 메시지 파일이 위치하는 경로를 지정할 수 있다.
    interceptor를 사용하여 LocaleChangeInterceptor 빈이 등록되고, URL에 포함된 lang파라미터를 통해 사용자의 지역을 변경할 수 있도록 설정한다.
    -->
    <bean id="localeResolver" class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <property name="defaultLocale" value="ko_KR" />
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="classpath:messages" />
        <property name="defaultEncoding" value="UTF-8" />
    </bean>
    <mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
                <property name="paramName" value="lang" />
            </bean>
        </mvc:interceptor>
    </mvc:interceptors>    

    <!-- 7.HandlerExceptionResolver 
    이는 예외 처리를 위한 HandlerExceptionResolver설정이다.
    예외코드와 예외명을 매핑 설정한다.
    그리고 예외를 로깅할 때 사용하는 로거 이름을 설정한다.
    -->
    <bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
        <property name="exceptionMappings">
            <props>
                <prop key="java.lang.Exception">error</prop>
            </props>
        </property>
        <property name="warnLogCategory" value="example.WarnLogger"/>
    </bean>
    
    <!-- 8. 정적 리소스 처리 
    Spring MVC에서 정적 리소스(예: 이미지, CSS, JavaScript 파일)를 처리하는 기본 서블릿 핸들러를 활성화한다. 
    이 핸들러는 웹 애플리케이션 서버의 디폴트 서블릿을 사용하여 정적 리소스를 제공한다.
    -->
    <default-servlet-handler/>

    <!-- 9-1. 스케줄러 설정 (네임스페이스 기반)
    Spring Task 네임스페이스를 사용하여 스케줄러를 설정한다.
    id 속성은 스케줄러의 고유한 식별자를 나타내며, pool-size 속성은 동시에 실행되는 작업 스레드의 수를 설정한다.    
    -->
	<task:scheduler id="scheduler" pool-size="10"/>
    
    <!-- 9-2. 스케줄러 설정 (어노테이션 기반)
    애노테이션 기반의 스케줄링을 활성화한다. 
    scheduler 속성은 사용할 스케줄러의 빈 ID를 지정한다. 
    이를 통해 @Scheduled 어노테이션이 붙은 메소드들을 사용하여 주기적인 작업을 정의할 수 있다.
    -->    
    <task:annotation-driven scheduler="scheduler"/>

    <!-- 10. AOP 활성화 
    Spring AOP(Aspect-Oriented Programming)을 활성화한다.
    그리고 AspectJ 프록시를 생성하는 데 필요한 빈을 자동으로 생성한다. 
    이를 통해 @Aspect 어노테이션이 붙은 클래스들을 사용하여 애플리케이션에서 관점 지향 프로그래밍을 사용할 수 있다.      
    -->    
    <aop:aspectj-autoproxy />

3. 메이븐 프로젝트 설정 파일

정의 : 메이븐이라는 빌드 자동화 도구를 이용하기 위한 빌드 정보가 작성된 설정 파일. 일반적으로 pom.xml을 의미하며, 해당 파일은 미리 작성된 라이브러리를 자동으로 다운받고 빌드 정보를 이용하여 자바 프로젝트 소스를 컴파일->패키지->deploy까지 자동화하는 등 옵션을 설정한다.
위치 : 프로젝트 소스 밑. src와 같은 폴더 경로에 존재.
파일 : pom.xml.
용도 :  라이브러리 자동 다운로드    프로젝트 기본정보 프로젝트 배포 
구조 :

더보기
    <!-- 1. 라이브러리 자동 다운로드
    의존성 라이브러리를 관리한다. 여기서 추가하여 라이브러리를 내려받을 수 있다.
    여기서 한 개의 dependency는 한 개의 의존성 (라이브러리)이다.
    -->
    <dependencies>
        <dependency>
            <groupId>group-id</groupId>
            <artifactId>artifact-id</artifactId>
            <version>1.0.0</version>
        </dependency>        
    </dependencies>

    <!-- 2. 프로젝트의 기본 정보 -->
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.example</groupId>
    <artifactId>my-project</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>
    
    <!-- 3. 프로젝트 배포/빌드 설정 
    빌드에 필요한 메이븐 플러그인과 리포지터리를 설정한다.
    -->
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>central</id>
            <url>https://repo.maven.apache.org/maven2</url>
        </repository>
    </repositories>

4. 정리하자면