[Java] 39. Spring web framework를 이용해서 웹 서비스 프로젝트를 만드는 법


Study/Java  2021. 6. 2. 13:44

안녕하세요. 명월입니다.


이 글은 Spring web framework를 이용해서 웹 서비스 프로젝트를 만드는 법에 대한 글입니다.


이전 글에서 Java의 Servlet를 이용해서 웹서비스를 구축하는 방법에 대해서 설명했습니다.

link - [Java] 38. Java에서 웹 서비스 프로젝트(JSP Servlet)를 작성하는 방법


JSP Servlet이라는 것은 먼저 Java에서 웹서비스를 사용할 수 있게 하는 플렛폼이라고 할 수 있습니다.

즉, 서버와 클라이언트(Browser)간의 소켓 통신으로 http 프로토콜을 이용하여 통신하는 웹 서비스를 따로 구축할 필요없이 Servlet을 이용해서 간단하게 통신할 수 있게 도와주는 플렛폼입니다.

라이브러리와 플렛폼의 차이는 라이브러리는 여러가지 규약과 API를 사용하기 위한 클래스와 함수를 만들어 놓은 것이고 플렛폼은 어떤 환경을 사용하기 위해 미리 구축해 놓은 환경입니다. 그러니 Servlet은 플랫폼이라는 뜻에 더 가까울 수 있겠네요.


이러한 Servlet은 웹을 사용할 수 있게 만들어 놓은 환경이라고는 하지만 그것을 사용하기에 매우 불친절합니다.

예를 들면 브라우져로 요청을 받아 Servlet으로 응답하게 하면 html 데이터를 전부 String 형식으로 반환해야 합니다.

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

// 페이지 요청 호스트
@WebServlet("/Test")
// 호스명과 클래스 이름은 꼭 같은 필요는 없다. 그러나 클래스 관리가 쉽게 하기 위해서는 맞추는 게 좋다.
public class Test extends HttpServlet {
  // 직렬화 키, HttpServlet 클래스는 기본적으로 Serializable를 상속 받고 있다
  private static final long serialVersionUID = 1L;
  // 생성자
  public Test() {
    super();
  }
  // 브라우저에서 method가 get방식으로 호출할 때, 실행되는 함수
  // 파라미터 request는 브라우저에서 요청하는 값이 있는 파라미터
  // 파라미터 response는 브라우저로 응답할 값을 저장해야하는 파라미터
  protected void doGet(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
    // response.getWriter()함수로 데이터 영역의 Stream를 받는다.
    PrintWriter out = response.getWriter();
    // out 변수에 html태그를 넣습니다.
    out.append("<!DOCTYPE html>");
    out.append("<html>");
    out.append("<head>");
    out.append("<meta charset=\"UTF-8\">");
    out.append("<title>Test</title>");
    out.append("</head>");
    out.append("<body>");
    out.append("<label>");
    // 파라미터의 data값을 넣는다.
    out.append(request.getParameter("data"));
    out.append("</label>");
    out.append("</body>");
    out.append("</html>");
  }

  // 브라우저에서 method가 post방식으로 호출할 때, 실행되는 함수
  // 파라미터 request는 브라우저에서 요청하는 값이 있는 파라미터
  // 파라미터 response는 브라우저로 응답할 값을 저장해야하는 파라미터
  protected void doPost(HttpServletRequest request, HttpServletResponse response) 
      throws ServletException, IOException {
    // doGet함수를 실행한다.
    // 즉, get방식 요청이나 post방식 요청이나 결과값은 같다.
    doGet(request, response);
  }
}

위 예제를 보시면 doGet함수에 Response값에 html 태그를 string 값으로 넣습니다. 간단한 html값이라도 꽤 많은 스탭이 들어가네요.

그렇다면 좀 더 복잡해진다면 한 페이지 만드는 데 엄청 복잡해 질 것입니다.

그렇다면 html 파일로 만들어서 FileStream으로 읽어와서 String으로 변환하여 넣는 것?

가능합니다. 그러나 위처럼 파라미터의 값이나 Post 데이터값을 넣을 때는 Replace로 치환해야 하겠네요. 또 String으로 다루다 보니 eclipse에서 Debug 에러 체크를 안 해줍니다.

그러니 Servlet를 그대로 사용하기에는 매우 불편합니다.또 이것을 해결하기 위해 매번 Framework를 만들기에는 개발 공수가 매우 많이 발생할 것입니다.


Java에는 이런 것을 줄이기 위한 Open framework가 많이 있는데 그 중 제가 소개할 것은 Spring Framework입니다.

개인적인 의견으로 많은 framework 중에서 이 Spring이 버그가 매우 적고 가볍고 사용하기 쉬웠습니다. 개인적인 느낌이기 때문에 사람마다 불편할 수도 있습니다.


스프링을 사용하기 위해서는 많은 라이브러리가 필요하니 maven을 연결해 놓는 것이 좋습니다.

link - [Java] 33. 오픈 라이브러리를 참조하는 방법(eclipse에서 maven 연결)


먼저 Spring 프레임 워크를 만들기 위해서 Servlet 환경부터 만듭니다.

그리고 maven 환경도 추가합니다.

그리고 pom.xml에서 Spring framework와 관계된 라이브러리를 연결합니다.

<dependencies>
  <!-- Spring 프레임워크 라이브러리 -->
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.1.1.RELEASE</version>
  </dependency>
  <!-- jsp에서 변수 치환하는 라이브러리 -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
  </dependency>
  <!-- servlet에서 자주 사용되는 api 라이브러리 -->
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
  </dependency>
</dependencies>

라이브러리를 다운로드하고 의존성을 연결합니다.

웹 환경을 설정하는 파일은 web.xml이지만 spring 프레임워크를 설정하는 파일은 mvc-config.xml입니다.

WebContent -> WEB-INF 폴더 안에 mvc-config.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:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/mvc
                           http://www.springframework.org/schema/mvc/spring-mvc.xsd
                           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.xsd">
  <!-- 컨트럴러 패키지 설정 -->
  <context:component-scan base-package="controller"/>
  <!-- 서블릿에서 jsp파일을 읽어서 변환하는 인코딩 타입 -->
  <mvc:annotation-driven>
    <mvc:message-converters>
      <bean class="org.springframework.http.converter.StringHttpMessageConverter">
        <property name="supportedMediaTypes">
          <list>
            <value>text/html;charset=UTF-8</value>
          </list>
        </property>
      </bean>
    </mvc:message-converters>
  </mvc:annotation-driven>
  <!-- view 폴더 설정 -->
  <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/view/"/>
    <property name="suffix" value=".jsp"/>
  </bean>
</beans>

그리고 웹 환경 web.xml에서 mvc-config.xml를 연결한다.

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">
  <!-- 프로젝트 이름 -->
  <display-name>SpringTestWeb</display-name>
  <!-- 루트(/)일때의 페이지 -->
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <!-- mvc-config.xml 설정 -->
  <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/mvc-config.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <!-- web url 패턴, *.html 확장자로 request가 오면 spring framework로 읽어드린다. -->
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>*.html</url-pattern>
  </servlet-mapping>
  <!-- encoding 패턴 (Post 등의 헤더 값 인코딩 설정) -->
  <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>
  <!-- 인코딩 url 패턴 -->
  <filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>
</web-app>

여기까지 Spring Framework 환경 설정했습니다.


이제 브라우저에서 웹 서버로 요청이 오면 html로 파싱을 할 클래스를 설정합니다.

mvc-config.xml에서 파싱 클래스 패키지를 「controller」로 했기 때문에 패키지가 controller인 클래스를 작성합니다.

package controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class Helloworld {
  // 요청 url 패턴
  @RequestMapping(value = "/index.html")
  public String index(ModelMap modelmap, HttpSession session, HttpServletRequest req, HttpServletResponse res) {
    // view(.jsp)로 데이터를 넘기기 위한 modelmap
    modelmap.addAttribute("Data", "Helloworld");
    // view의 파일명
    return "index";
  }
}

controller 클래스에서 중요한 것은 @Controller를 넣는 것입니다. 그래야 spring framework에서 파싱 클래스로 인식합니다.

그리고 브라우저에서 요청하면 호출될 함수를 작성하고 @RequestMapping 어트리뷰트로 요청 페이지를 설정합니다.

위 소스의 경우는 /index.html가 오면 저 index 함수가 호출됩니다. 참고로 루트의 경우는 index.html을 지정했기 때문에 루트가 저 함수가 호출됩니다.

modelmap에 key와 데이터를 넣으면 view에서 사용할 수 있습니다.

return 값은 string인데 view 파일명을 지정합니다. 저는 index라고 리턴했습니다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
  </head>
  <body>
    <!-- modelmap으로 넘겨 받는 데이터  -->
    ${Data}
  </body>
</html>

여기까지 기동을 하기 위해 작성이 끝났습니다. 제가 예상하는 건 기동하면 바로 Hello world 페이지가 보이는 것입니다.

Hello world가 브라우저에 나오는 것을 확인했습니다.


Spring Framework를 처리 순서를 요약하면 다음과 같습니다.

1. 브라우저에서 url로 요청을 한다.

2. 호스트명을 제외한 address 주소를 파싱한다. 위 예제는 /index.html를 찾습니다.

3. index.html은 확장자가 html이기 때문에 web.xml의 설정 값에 의해 mvc-config.xml 처리로 넘깁니다.

4. Spring Framework와 관계된 요청이니 controller에서 /index.html와 매핑된 함수를 찾습니다. 위 예제에서는 Helloworld클래스의 index함수를 요청하겠네요.

5. 함수를 처리하고 return 값으로 view 파일을 찾습니다. 위 예제에서는 index를 리턴하네요.

6. 다시 mvc-config.xml의 설정으로 view파일은 /WEB-INF/view/의 디렉토리에서 index.jsp파일 찾습니다.

7. index.jsp파일을 요청해서 최종 html 데이터로 파싱합니다.

8. 브라우저로 응답합니다.


결과 브라우저에서는 최종 파싱된 결과를 받고 화면에 표시를 하는 것입니다.


다른 포스트에서 좀 더 Spring에 대해서 자세히 설명하겠습니다.


여기까지 Spring web framework를 이용해서 웹 서비스 프로젝트를 만드는 법에 대한 글이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.