관리 메뉴

거니의 velog

(12) 스프링으로 답변형 게시판 만들기 1 본문

Java_Spring Framework part2

(12) 스프링으로 답변형 게시판 만들기 1

Unlimited00 2023. 11. 20. 18:22

* 일반적인 웹 애플리케이션은 여러 기능들이 합쳐져 만들어진다. 즉, 개발자들이 기능들을 각각 구현한 다음 이를 합쳐서 하나의 웹 애플리케이션을 만드는 것이다. 우리는 지금까지 회원 관리 기능을 구현하면서 스프링 기능을 익혔다. 이번에는 이제까지 구현한 회원 관리 기능에 답변형 게시판 기능을 추가해 보자. 이를 통해 일반적인 웹 애플리케이션 구현 과정에 한 발 더 다가갈 수 있을 것이다.


1. 기존 소스 코드 변경하기

* 새 프로젝트 pro30을 만든 후 이전에 만든 회원 기능 소스 코드를 복사해 수정하는 방식으로 실습을 진행해 보자.

1. pro30의 pom.xml에 타일즈와 마이바티스 관련 라이브러리를 추가한다.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.myspring</groupId>
	<artifactId>pro30</artifactId>
	<name>pro30</name>
	<packaging>war</packaging>
	<version>1.0.0-BUILD-SNAPSHOT</version>
	<properties>
		<java-version>1.6</java-version>
		<org.springframework-version>3.1.1.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
	</properties>
	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				 </exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
				
		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>	
		
		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>
				
		<!-- Servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>jsp-api</artifactId>
			<version>2.1</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
	
		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>  
		
		<!-- 마이바티스 -->
		<dependency>
			<groupId>commons-beanutils</groupId>
			<artifactId>commons-beanutils</artifactId>
			<version>1.8.0</version>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
		</dependency>
		<dependency>
			<groupId>cglib</groupId>
			<artifactId>cglib-nodep</artifactId>
			<version>2.2</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.1.0</version>
		</dependency>
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>1.1.0</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.29</version>
		</dependency>
		<dependency>
			<groupId>jdbc.oracle</groupId>
			<artifactId>OracleDriver</artifactId>
			<version>12.1.0.2.0</version>
			<scope>system</scope>
			<systemPath>${basedir}/src/main/webapp/WEB-INF/lib/ojdbc6.jar</systemPath>
		</dependency>

		<!-- 타일즈 관련 라이브러리 -->
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-core</artifactId>
			<version>2.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-jsp</artifactId>
			<version>2.2.2</version>
		</dependency>
		<dependency>
			<groupId>org.apache.tiles</groupId>
			<artifactId>tiles-servlet</artifactId>
			<version>2.2.2</version>
		</dependency>
		<!-- 파일 업로드 -->
		<dependency>
    <groupId>commons-fileupload</groupId>
    <artifactId>commons-fileupload</artifactId>
    <version>1.2.1</version>
  </dependency>

  <dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.4</version>
  </dependency>
  
  
	<!-- AspectJ -->
<!-- 	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjrt</artifactId>
	    <version>${org.aspectj-version}</version>
	</dependency>
	 
	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjweaver</artifactId>
	    <version>${org.aspectj-version}</version>
	</dependency>
	 
	<dependency>
	    <groupId>org.aspectj</groupId>
	    <artifactId>aspectjtools</artifactId>
	    <version>${org.aspectj-version}</version>
	</dependency>
		 -->
		      
	</dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. lib 폴더를 만든 후 오라클 드라이버를 복사하여 붙여 넣는다.

3. 인터셉터를 추가하자. com/myspring/pro30 패키지 하위에 다시 common/interceptor 패키지를 만든 후 이전의 인터셉터 실습 파일을 참고하여 복사 붙여 넣는다.

4. 이전의 회원 관리 기능에 사용된 XML 설정 파일, 자바 클래스, JSP 파일 순으로 동일한 패키지와 폴더를 만든 후 복사하여 붙여 넣는다. 화면에 나타낼 이미지도 resources 폴더에서 복사한 후 동일한 폴더에 붙여 넣는다.

5. 회원 기능 중 게시판 실습에 필요한 자바 코드와 JSP 파일을 수정해 보자. 컨트롤러에 /main.do로 요청하면 main.jsp를 표시해주는 main() 메서드를 추가한다.

[MemberControllerImpl.java]

package com.myspring.pro30.member.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.myspring.pro30.member.service.MemberService;
import com.myspring.pro30.member.vo.MemberVO;

@Controller("memberController")
//@EnableAspectJAutoProxy
public class MemberControllerImpl implements MemberController {
	@Autowired
	private MemberService memberService;
	@Autowired
	private MemberVO memberVO;

	@RequestMapping(value = { "/", "/main.do" }, method = RequestMethod.GET) // /pro30/main.do로 요청 시 메인 페이지를 보여 준다.
	private ModelAndView main(HttpServletRequest request, HttpServletResponse response) {
		String viewName = (String) request.getAttribute("viewName");
		ModelAndView mav = new ModelAndView();
		mav.setViewName(viewName);
		return mav;
	}

}

* /main.do로 요청하면 메인 페이지를 나타내 주는 기능을 추가했다. 이어서 마이바티스와 타일즈 기능도 설정해 보자.


2. 마이바티스 관련 XML 파일 설정하기

1. src/main/resources/ 패키지에 게시판 기능 관련 매퍼 파일인 board.xml을 추가한다.

2. member.xml 위에 마우스 오른쪽 버튼을 클릭한 후 Copy를 선택하고 다시 Paste를 선택한다.

3. 복사한 member.xml의 파일 이름을 board.xml로 변경한 후 OK를 클릭한다.

4. 게시판 관련 매퍼 파일인 board.xml이 생성된 것을 확인할 수 있다.

5. 기존의 파일 내용을 삭제한 후 <select> 태그로 id가 selectAllArticleList인 SQL문을 추가한다.

[board.xml]

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
      PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 네임스페이스를 변경한다. -->
<mapper namespace="mapper.board">
	<resultMap id="articlesResult" type="articleVO">
		<result property="level" column="level" />
		<result property="articleNO" column="articleNO" />
		<result property="parentNO" column="parentNO" />
		<result property="title" column="title" />
		<result property="content" column="content" />
		<result property="writeDate" column="writeDate" />
		<result property="imageFileName" column="imageFileName" />
	</resultMap> <!-- 글 정보를 저장할 resultMap을 설정한다. -->

	<resultMap id="imgResult" type="imageVO">
		<result property="imageFileNO" column="imageFileNO" />
		<result property="articleNO" column="articleNO" />
		<result property="imageFileName" column="imageFileName" />
	</resultMap>

	<select id="selectAllArticlesList" resultMap="articlesResult">
	    <![CDATA[
	      SELECT level, articleNO, parentNO, title, content, writeDate, imageFileName, id
	      from t_board
	      START WITH  parentNO=0
	      CONNECT BY PRIOR articleNO=parentNO 
	      ORDER SIBLINGS BY articleNO DESC		
	    ]]>
	</select> <!-- 모든 글을 조회하는 SQL문을 작성한다. -->

</mapper>

6. modelConfilg.xml에는 매퍼 파일에서 사용할 articleVO를 추가한다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration 	PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-config.dtd">

<configuration>
	<typeAliases>
		<typeAlias type="com.myspring.pro30.member.vo.MemberVO"
			alias="memberVO" />
		<typeAlias type="com.myspring.pro30.board.vo.ArticleVO"
			alias="articleVO" /> <!-- 매퍼 파일에서 사용할 articleVO를 설정한다. -->
		<typeAlias type="com.myspring.pro30.board.vo.ImageVO"
			alias="imageVO" />
	</typeAliases>
</configuration>

3. 타일즈 설정하기

* 이번에는 게시판 화면을 나타내 줄 타일즈 설정 파일을 만들어 보자.

1. 이전과 마찬가지로 tiles_member.xml을 복사해 붙여 넣은 후 파일 이름을 tiles_board.xml로 변경한다.

2. 기존 내용을 삭제한 후 게시판 화면 기능은 tiles_board.xml에 설정해서 사용한다. 글목록창을 <definition> 태그로 설정한다.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE tiles-definitions PUBLIC
"-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN"
"http://tiles.apache.org/dtds/tiles-config_2_0.dtd">
<tiles-definitions>
	<!-- /board/listArticles 요청에 대해 같은 경로의 listArticles.jsp를 표시한다. -->
	<!-- tiles_member.xml의 기본 레이아웃을 상속받는다. -->
	<definition name="/board/listArticles" extends="baseLayout">
		<put-attribute name="title" value="글목록창" />
		<put-attribute name="body"
			value="/WEB-INF/views/board/listArticles.jsp" />
	</definition>

	<definition name="/board/articleForm" extends="baseLayout">
		<put-attribute name="title" value="글쓰기창" />
		<put-attribute name="body"
			value="/WEB-INF/views/board/articleForm.jsp" />
	</definition>

	<definition name="/board/viewArticle" extends="baseLayout">
		<put-attribute name="title" value="글상세창" />
		<put-attribute name="body"
			value="/WEB-INF/views/board/viewArticle.jsp" />
	</definition>

</tiles-definitions>