์Šคํ”„๋ง ๊ฐœ๋ฐœ ์ดˆ๊ธฐ ์„ค์ •

1. facet ๋ฒ„์ „ ๋งž์ถ”๊ธฐ

ํ”„๋กœ์ ํŠธ ์šฐ ํด๋ฆญ > Properties > Project Facets > Dynamic Web Module ๋ฒ„์ „ ์„ค์ •, Java ๋ฒ„์ „ ์„ค์ •


2. pom.xml ์„ค์ •

  • Maven : ์ž๋ฐ” ์ž๋™ํ™” build tool.
  • Project Object Model : ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ ๋ฐ ๋นŒ๋“œ์— ํ•„์š”ํ•œ ํ™˜๊ฒฝ ์„ค์ •, ์˜์กด์„ฑ ์„ค์ •, ๋ผ์ดํ”„ ์‚ฌ์ดํด ๊ด€๋ฆฌ ๋“ฑ

์ฆ‰, maven์„ ํ†ตํ•ด ๋นŒ๋“œ๋ฅผ ์ž๋™ํ™”ํ•˜๊ธฐ ์œ„ํ•ด ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ pom.xml์ด๋ผ๋Š” ์„ค์ • ํŒŒ์ผ์— ์ •์˜ํ•ด๋‘๋ฉด, ๋„คํŠธ์›Œํฌ๋ฅผ ํ†ตํ•ด ์ž๋™์œผ๋กœ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ค์šด๋ฐ›์•„ ํ”„๋กœ์ ํŠธ๋ฅผ ์†์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ”„๋กœ์ ํŠธ ์ดˆ๊ธฐ ์ƒ์„ฑ ์ดํ›„ ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” MVN Repository๋ฅผ ํ†ตํ•ด ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜๋Š” ํ”„๋กœ์ ํŠธ ๊ฐœ๋ฐœ ์‹œ ์‹ค์ œ๋กœ ์ถ”๊ฐ€ํ–ˆ๋˜ dependency๋“ค์ด๋‹ค.

<!-- for MySQL -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.24</version>
</dependency>

<!-- for Datasource -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-dbcp2</artifactId>
    <version>2.8.0</version>
</dependency>

<!-- for mybatis -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.6</version>
</dependency>

<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.6</version>
</dependency>

<!-- for Transaction -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

<!-- for jdbc -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${org.springframework-version}</version>
</dependency>

<!-- for File upload -->
<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>${commons-fileupload-version}</version>
</dependency>

<!-- for JSON -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency> 

<dependency>
    <groupId>org.json</groupId>
    <artifactId>json</artifactId>
    <version>${json-version}</version>
</dependency>

<!-- for lombok -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.22</version>
    <scope>provided</scope>
</dependency>

3. web.xml ์„ค์ •

sts์— ์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์€ ํŒŒ์ผ ๊ตฌ์กฐ๋กœ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

Spring Project Structure

  • web.xml : ์›น ํ™˜๊ฒฝ ์„ค์ • ํŒŒ์ผ
  • WAS(Web Application Server)๊ฐ€ ๊ตฌ๋™๋˜๋ฉด ์ตœ์ดˆ๋กœ web.xml์„ ์ฝ์–ด ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์— ํ•„์š”ํ•œ ํ™˜๊ฒฝ ์„ค์ •์„ ๋งˆ์นœ ๋’ค ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œํ•œ๋‹ค.
  • DispatcherServlet, Root Context์™€ ContextLoaderListener, Filter ๋“ฑ์„ ๋“ฑ๋กํ•œ๋‹ค.

DispatcherServlet ์„ค์ •

DispatcherServlet์€ ์—ฌ๋Ÿฌ๊ฐœ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ๊ฐ DispatcherServlet ๋งˆ๋‹ค ์„œ๋กœ ๋‹ค๋ฅธ ApplicationContext๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

<!-- Processes application requests -->
<servlet>
    <servlet-name>appServlet</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>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Root Context ์„ค์ •

์ตœ์ƒ์œ„ context๋ฅผ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋กœ๋“œํ•  ์„ค์ • ํŒŒ์ผ(root-context.xml)์„ ์ง€์ •ํ•œ๋‹ค. ์ด๋ฅผ ํฌํ•จํ•œ context ์„ค์ • ํŒŒ์ผ๋“ค์„ ๋กœ๋“œํ•˜๊ธฐ ์œ„ํ•ด ContextLoaderListener๋ฅผ ์„ค์ •ํ•œ๋‹ค.

<!-- The definition of the Root Spring Container shared by all Servlets and Filters -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

Filter ์„ค์ •

ํด๋ผ์ด์–ธํŠธ์˜ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ฒŒ ๋˜๋ฉด DispatcherServlet์— ์š”์ฒญ์„ ์ „๋‹ฌํ•˜๊ธฐ ์ „์— ํ•„ํ„ฐ ๊ณผ์ •์„ ๊ฑฐ์ณ ์š”์ฒญ์— ๋งž๋Š” ๋ถ€๊ฐ€ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์—ญํ• . ๋ง ๊ทธ๋Œ€๋กœ โ€œํ•„ํ„ฐโ€.

์•„๋ž˜๋Š” ๊ฑฐ์˜ ํ•„์ˆ˜์ ์œผ๋กœ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ์ธ์ฝ”๋”ฉ ํ•„ํ„ฐ

<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>
</filter>
     
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

4. servlet-context.xml ์„ค์ •

web๊ณผ ๊ด€๋ จ๋œ context ์„ค์ • ํŒŒ์ผ. Controller, View, Interceptor ๊ด€๋ จ ์„ค์ •์„ ๋งก๋Š”๋‹ค.

  • Controller๋ฅผ ๋“ฑ๋กํ•ด๋‘๋ฉด ์ž๋™์œผ๋กœ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ DI๋ฅผ ํ•œ๋‹ค.
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<context:component-scan base-package="com.capo.myapp.controller" />
  • Controller์™€ ์‘๋‹ต ํ™”๋ฉด(ํŽ˜์ด์ง€)๋ฅผ ์—ฐ๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ViewResolver๋ฅผ ์„ค์ •ํ•œ๋‹ค.
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <beans:property name="prefix" value="/WEB-INF/views/" />
    <beans:property name="suffix" value=".jsp" />
</beans:bean>

<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<view-controller path="/user/loginView" view-name="login"/>
<view-controller path="/user/auth/listView" view-name="list"/>
<view-controller path="/user/registerView" view-name="register"/>
  • Interceptor ์„ค์ •๋„ ์—ฌ๊ธฐ์„œ ํ•œ๋‹ค.
<interceptors>
    <interceptor>
        <mapping path="/*/auth/**"/>
        <beans:ref bean="loginInterceptor"/>
    </interceptor>
</interceptors>

5. root-context.xml ์„ค์ •(web์ด ์•„๋‹Œ ๊ฒƒ๋“ค)

web ์ด์™ธ์˜ ์„ค์ •์„ ์œ„ํ•œ ํŒŒ์ผ. ํŠนํžˆ Model, AOP, Advice ๊ด€๋ จ ์„ค์ •์€ ์—ฌ๊ธฐ์— ํ•œ๋‹ค.

<!-- Root Context: defines shared resources visible to all other web components -->
<context:component-scan base-package="com.capo.myapp.model"></context:component-scan>
<context:component-scan base-package="com.capo.myapp.advice"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • MyBatis๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ๊ด€๋ จ ๊ฐ์ฒด ์ฃผ์ž…๋„ ์—ฌ๊ธฐ์„œ ์„ค์ •ํ•œ๋‹ค.
<context:property-placeholder location="classpath:db.properties"/>
	
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource"
        p:driverClassName="${db_driver}"
        p:url="${db_url}"
        p:username="${db_username}"
        p:password="${db_password}">
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"
        p:dataSource-ref="dataSource"
        p:typeAliasesPackage="com.capo.myapp.model.dto"
        p:mapperLocations="classpath:mapper/**/*.xml">
</bean>
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"
        c:sqlSessionFactory-ref="sqlSessionFactory">
</bean>

<mybatis-spring:scan base-package="com.capo.myapp.model.dao"/>

6. DI(Controller, Service, Repository)

์Šคํ”„๋ง ํ”„๋กœ์ ํŠธ ํŒŒ์ผ ๊ตฌ์กฐ์—์„œ ์œ— ๋ถ€๋ถ„์€ ์‹ค์ œ ์›น ์„œ๋ฒ„์™€ ๊ด€๋ จ๋œ ์ž๋ฐ” ์†Œ์Šค๋“ค์ด ์žˆ๋Š” ๋””๋ ‰ํ„ฐ๋ฆฌ๋‹ค. src/main ์•„๋ž˜์—๋Š” ์‹ค์ œ ๋ฐฐํฌ๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ด€๋ จ ์ž๋ฐ” ์†Œ์Šค๋ฅผ, src/test ์•„๋ž˜์—๋Š” ํ…Œ์ŠคํŒ… ์šฉ๋„์˜ ์ž๋ฐ” ์†Œ์Šค๋ฅผ ์ €์žฅํ•œ๋‹ค.

Spring Project Structure

์ค‘์ ์ ์œผ๋กœ ๋ณผ ๋ถ€๋ถ„์€ src/main/java ๋””๋ ‰ํ„ฐ๋ฆฌ! MVC ํŒจํ„ด์„ ๋”ฐ๋ผ ํŒจํ‚ค์ง€๋ฅผ ๊ตฌ์„ฑํ•  ๋•Œ๋„ Controller์™€ Model๋ถ€๋ถ„์„ ๋‚˜๋ˆ„๋ฉด servlet-context.xml๊ณผ root-context.xml ์„ค์ •ํ•  ๋•Œ๋„ ์‰ฝ๋‹ค.

์ถ”๊ฐ€ + interceptor๋Š” Controller์™€ ํ•จ๊ป˜ servlet-context.xml์— ์„ค์ •ํ•˜์—ฌ ๊ด€๋ฆฌ ๋ฐ›์•„์•ผ ํ•˜๋ฏ€๋กœ controller ํŒจํ‚ค์ง€ ์•„๋ž˜์— ๊ตฌ์„ฑํ•œ๋‹ค.

์Šคํ”„๋ง์˜ ์ตœ๋Œ€ ๊ฐ•์ ์ด์ž ํŠน์ง•์ธ DI๋ฅผ ์œ„ํ•ด XML์—์„œ Bean์œผ๋กœ ์ง์ ‘ ์„ค์ •ํ•  ์ˆ˜๋„ ์žˆ๊ณ  ํด๋ž˜์Šค์— Annotation์„ ํ‘œ์‹œํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Annotation์€ ์ปจํŠธ๋กค๋Ÿฌ๋Š” @Controller๋กœ, ์„œ๋น„์Šค๋Š” @Service๋กœ, ๋ชจ๋ธ์€ @Repository๋กœ ์„ค์ •ํ•˜๋ฉด ๋œ๋‹ค.