ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 231212_Maven, REST API, 스프링 프레임워크와 스프링부트
    카테고리 없음 2023. 12. 12. 17:54

    CHAPTER07-6 Maven 기반 프로젝트 구성

    Maven 은 자바 빌드 도구로, 스프링 프레임 워크 개발에서 기본 빌드 도구로 활용되었다. 이후 Gradle가 나오고나서 안드로이드 앱 기발의 기본 빌드 도구가 되었다. Mavem과 Gradle은 현재 가장 대표적인 빌드 도구다. 이클립스에서 Maven 프로젝트를 사용할 땐 주로 웹 프젝트를 Maven기반으로 변환해 사용한다. 

    jwbook 폴더에서 configure-convert to maven Project 선택

    프로젝트에서 우클릭, Configure →Convert to Maven Project을 선택하면 POM을 생성하는 창이 뜬다. 필요한 사항을 등록한 뒤 Finish를 클릭하면 pom.xml 이 자동으로 생성된 것을 볼 수 있다. 이후 메이븐 리포지터리(https://mvnrepository.com/) 에 접속해서 JSTL을 검색해 코드를 붙여넣는다. 

    이하 더보기는 메이븐 리포지터리에서 코드를 복사하는 방법이다.

    더보기

     

    https://mvnrepository.com/artifact/javax.servlet/jstl/1.2

     

     

     

      <!--라이브러리 추가-->
      <dependencies>
    	<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    	<dependency>
    	    <groupId>javax.servlet</groupId>
    	    <artifactId>jstl</artifactId>
    	    <version>1.2</version>
    	</dependency>
      </dependencies>

    생성된 pom.xml 파일에 라이브러리를 추가 끝났다면 pom.xml 우클릭-maven-update project 해야한다.

     

    이전 수업에서 학생명단으로 작업할 때 사용했던 라이브러리들을 모두 추가했다. (모두 추가한 뒤 Maven 폴더를 열어봤을 때 아래와 같이 확인 된다. 이전에는 별도로 라이브러리를 폴더에 넣어서 사용했으나, 지금은 Maven에 사용하던 라이브러리를 코드로 넣었고 문제없이 작동되는걸 확인했다.)

    뭔가 많다.

     


    CHAPTER12 REST API 개발

    pom.xml 에 라이브러리를 추가했으나 최신 버전은 호환이 되지 않아 2.33 버전으로 수정해서 업데이트 했다. 이후, 12장 실습을 위해 ch10 폴더를 추가하고서 ch12챕터의 코드를 추가했다.

    	<!--12장-->
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-servlet -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.containers</groupId>
    	    <artifactId>jersey-container-servlet</artifactId>
    	    <version>2.33</version>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.inject</groupId>
    	    <artifactId>jersey-hk2</artifactId>
    	    <version>2.33</version>
    	</dependency>
    
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.media</groupId>
    	    <artifactId>jersey-media-json-jackson</artifactId>
    	    <version>2.33</version>
    	</dependency>
    package ch12;
    
    import java.util.HashMap;
    import java.util.Map;
    
    import javax.ws.rs.ApplicationPath;
    import javax.ws.rs.core.Application;
    
    @ApplicationPath("/api")
    public class RestConfig extends Application{	
        public Map<String, Object> getProperties() {
            Map<String, Object> properties = new HashMap<String, Object>();
            properties.put("jersey.config.server.provider.packages", "ch12");
            return properties;
        }
    }
    package ch12;
    
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.Path;
    import javax.ws.rs.Produces;
    import javax.ws.rs.QueryParam;
    import javax.ws.rs.core.MediaType;
    
    @Path("/test")
    public class RestApiExample {
    
    //	@GET
    	@POST
    	@Produces(MediaType.TEXT_PLAIN)
    	public String sayHello() {
    		return "Hello API Service"; //.../api/test
    	}
    	// .../api/test?msg="abc"
    //	@POST
    	@GET
    	public String sayHello(@QueryParam("msg") String msg) {
    		return msg+" API Service";
    	}
    }

     

    HTTP @POST 요청 결과
    HTTP @GET 요청 결과

     

     


    CHAPTER13 스프링 프레임워크와 스프링부트

    pom.xml 에 아래 라이브러리를 추가했다.

    <dependency>
             <groupId>org.apache.tomcat.embed</groupId>
             <artifactId>tomcat-embed-jasper</artifactId>
             <scope>provided</scope>
          </dependency>
          <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>jstl</artifactId>
             <version>1.2</version>
          </dependency>

    application.properties 파일에 아래 내용을 추가했다.

    spring.mvc.view.prefix=/WEB-INF/views/
    spring.mvc.view.suffix=.jsp

    이후 테스트를 위한 컨트롤러 (TestWebController.java) 를 작성한다. 위의 설정이 모두 끝난 뒤, 이클립스 콘솔에서 스프링부트 실행했다. 결과를 확인하려면 Run→Run on Server로 실행하는 것이 아닌, 웹 브라우저에서 경로(http://localhost:8080/test/hello)를 직접 작성해서 결과를 확인해야 한다. (경로가 test/hello 인 이유는 TestWebController.java 에서 확인 가능.)

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <title>Hello World</title>
    </head>
    <body> 
    	<h2>Hello World</h2>
    	<hr>
    	현재 날짜와 시간은 <%=java.time.LocalDateTime.now()%> 입니다.
    	<hr>
    	메시지: ${msg}
    </body>
    </html>

    실행 결과

    `


    CHAPTER10 뉴스기사 관리 웹 서비스

     

    뉴스 등록 시 페이지
    뉴스목록을 통해 위와 같이 접속, 다만 이미지는 에러가 뜬다.

     

    뉴스기사 관리 웹 서비스에 사용된 파일들은 더보기 참고.

    더보기

    newsView.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
    <title>뉴스 관리 앱</title>
    </head>
       <body>
       <div class="container w-75 mt-5 mx-auto">
        <h2>뉴스 목록</h2>
        <hr>
        <ul class="list-group">
    		<c:forEach var="news" items="${newslist}" varStatus="status">
    		  <li class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"><a href="news.nhn?action=getNews&aid=${news.aid}" class="text-decoration-none">[${status.count}] ${news.title}, ${news.date}</a>
    		  <a href="news.nhn?action=deleteNews&aid=${news.aid}"><span class="badge bg-secondary">&times;</span></a>
    		  </li>
    		</c:forEach> 
    	</ul>
    	<hr>
    	<c:if test="${error != null}">
    		<div class="alert alert-danger alert-dismissible fade show mt-3">
    				에러 발생: ${error}
    			<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    		</div>
    	</c:if>
    	<button class="btn btn-outline-info mb-3" type="button" data-bs-toggle="collapse" data-bs-target="#addForm" aria-expanded="false" aria-controls="addForm">뉴스 등록</button>
    	<div class="collapse" id="addForm">
    	  <div class="card card-body">
    		<form method="post" action="/jwbook/news.nhn?action=addNews" enctype="multipart/form-data">
    			<label class="form-label">제목</label>
    			<input type="text" name="title" class="form-control">
    			<label class="form-label">이미지</label>
    			<input type="file" name="file" class="form-control">
    			<label class="form-label">기사내용</label>
    			<textarea cols="50" rows="5" name="content" class="form-control"></textarea>
    			<button type="submit" class="btn btn-success mt-3">저장</button>
    		</form>
    	  </div>
    	</div>
    	</div>
    </body>
    </html>

     

    newsList.jsp

    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8"%>
    <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    
    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BmbxuPwQa2lc/FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH/Ev+nYRRuWlolflfl" crossorigin="anonymous">
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta2/dist/js/bootstrap.bundle.min.js" integrity="sha384-b5kHyXgcpbZJO/tY9Ul7kGkf1S0CWuKcCD38l8YkeH8z8QjE0GmW1gYU5S9FOnJ0" crossorigin="anonymous"></script>
    <title>뉴스 관리 앱</title>
    </head>
       <body>
       <div class="container w-75 mt-5 mx-auto">
        <h2>뉴스 목록</h2>
        <hr>
        <ul class="list-group">
    		<c:forEach var="news" items="${newslist}" varStatus="status">
    		  <li class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"><a href="news.nhn?action=getNews&aid=${news.aid}" class="text-decoration-none">[${status.count}] ${news.title}, ${news.date}</a>
    		  <a href="news.nhn?action=deleteNews&aid=${news.aid}"><span class="badge bg-secondary">&times;</span></a>
    		  </li>
    		</c:forEach> 
    	</ul>
    	<hr>
    	<c:if test="${error != null}">
    		<div class="alert alert-danger alert-dismissible fade show mt-3">
    				에러 발생: ${error}
    			<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
    		</div>
    	</c:if>
    	<button class="btn btn-outline-info mb-3" type="button" data-bs-toggle="collapse" data-bs-target="#addForm" aria-expanded="false" aria-controls="addForm">뉴스 등록</button>
    	<div class="collapse" id="addForm">
    	  <div class="card card-body">
    		<form method="post" action="/jwbook/news.nhn?action=addNews" enctype="multipart/form-data">
    			<label class="form-label">제목</label>
    			<input type="text" name="title" class="form-control">
    			<label class="form-label">이미지</label>
    			<input type="file" name="file" class="form-control">
    			<label class="form-label">기사내용</label>
    			<textarea cols="50" rows="5" name="content" class="form-control"></textarea>
    			<button type="submit" class="btn btn-success mt-3">저장</button>
    		</form>
    	  </div>
    	</div>
    	</div>
    </body>
    </html>

     

    news.sql

    drop table news;
    
    CREATE TABLE news (
    	aid INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
    	title VARCHAR NOT NULL,
    	img VARCHAR NOT NULL,
    	date TIMESTAMP,
    	content VARCHAR NOT NULL
    );

     

    News,java

    package ch10;
    
    /**
     * @author dinfree
     *
     */
    public class News {
    	private int aid;
    	private String title;
    	private String img;
    	private String date;
    	private String content;
    	
    	public int getAid() {
    		return aid;
    	}
    	public void setAid(int aid) {
    		this.aid = aid;
    	}
    	public String getTitle() {
    		return title;
    	}
    	public void setTitle(String title) {
    		this.title = title;
    	}
    	public String getImg() {
    		return img;
    	}
    	public void setImg(String img) {
    		this.img = img;
    	}
    	public String getDate() {
    		return date;
    	}
    	public void setDate(String date) {
    		this.date = date;
    	}
    	public String getContent() {
    		return content;
    	}
    	public void setContent(String content) {
    		this.content = content;
    	}
    }

     

    NewsController.java

    img를 저장하는 폴더를 찾지 못해 그 부분의 절대 경로를 업로드했다. 

    package ch10;
    
    import java.io.IOException;
    import java.lang.reflect.Method;
    import java.sql.SQLException;
    import java.util.List;
    import java.util.StringTokenizer;
    
    import javax.servlet.RequestDispatcher;
    import javax.servlet.ServletConfig;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.annotation.MultipartConfig;
    import javax.servlet.annotation.WebServlet;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.Part;
    
    import org.apache.commons.beanutils.BeanUtils;
    
    import ch10.News;
    import ch10.NewsDAO;
    
    @WebServlet("/news.nhn")
    @MultipartConfig(maxFileSize=1024*1024*2, location="D:\\Dev-Fullstack2023\\img")
    public class NewsController extends HttpServlet {
    	private static final long serialVersionUID = 1L;
           
    	private NewsDAO dao;
    	private ServletContext ctx;
    	
    	// 웹 리소스 기본 경로 지정
    	private final String START_PAGE = "ch10/newsList.jsp";
    	
    	public void init(ServletConfig config) throws ServletException {
    		super.init(config);
    		dao = new NewsDAO();
    		ctx = getServletContext();		
    	}
    
    	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    		request.setCharacterEncoding("utf-8");
    		String action = request.getParameter("action");
    		
    		dao = new NewsDAO();
    		
    		// 자바 리플렉션을 사용해 if, switch 없이 요청에 따라 구현 메서드가 실행되도록 함.
    		Method m;
    		String view = null;
    		
    		// action 파라미터 없이 접근한 경우
    		if (action == null) {
    			action = "listNews";
    		}
    		
    		try {
    			// 현재 클래스에서 action 이름과 HttpServletRequest 를 파라미터로 하는 메서드 찾음
    			m = this.getClass().getMethod(action, HttpServletRequest.class);
    			
    			// 메서드 실행후 리턴값 받아옴
    			view = (String)m.invoke(this, request);
    		} catch (NoSuchMethodException e) {
    			e.printStackTrace();
    			// 에러 로그를 남기고 view 를 로그인 화면으로 지정, 앞에서와 같이 redirection 사용도 가능.
    			ctx.log("요청 action 없음!!");
    			request.setAttribute("error", "action 파라미터가 잘못 되었습니다!!");
    			view = START_PAGE;
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    	
    		// POST 요청 처리후에는 리디렉션 방법으로 이동 할 수 있어야 함.
    		if(view.startsWith("redirect:/")) {
    			// redirect/ 문자열 이후 경로만 가지고 옴
    			String rview = view.substring("redirect:/".length());
    			response.sendRedirect(rview);
    		} else {
    			// 지정된 뷰로 포워딩, 포워딩시 컨텍스트경로는 필요없음.
    			RequestDispatcher dispatcher = request.getRequestDispatcher(view);
    			dispatcher.forward(request, response);	
    		}
    	}
        
        public String addNews(HttpServletRequest request) {
    		News n = new News();
    		try {						
    			// 이미지 파일 저장
    	        Part part = request.getPart("file");
    	        String fileName = getFilename(part);
    	        if(fileName != null && !fileName.isEmpty()){
    	            part.write(fileName);
    	        }	        
    	        // 입력값을 News 객체로 매핑
    			BeanUtils.populate(n, request.getParameterMap());
    			
    	        // 이미지 파일 이름을 News 객체에도 저장
    	        n.setImg("/img/"+fileName);
    
    			dao.addNews(n);
    		} catch (Exception e) {
    			e.printStackTrace();
    			ctx.log("뉴스 추가 과정에서 문제 발생!!");
    			request.setAttribute("error", "뉴스가 정상적으로 등록되지 않았습니다!!");
    			return listNews(request);
    		}
    		
    		return "redirect:/news.nhn?action=listNews";
    		
    	}
    
    	public String deleteNews(HttpServletRequest request) {
        	int aid = Integer.parseInt(request.getParameter("aid"));
    		try {
    			dao.delNews(aid);
    		} catch (SQLException e) {
    			e.printStackTrace();
    			ctx.log("뉴스 삭제 과정에서 문제 발생!!");
    			request.setAttribute("error", "뉴스가 정상적으로 삭제되지 않았습니다!!");
    			return listNews(request);
    		}
    		return "redirect:/news.nhn?action=listNews";
    	}
    
    	public String listNews(HttpServletRequest request) {
        	List<News> list;
    		try {
    			list = dao.getAll();
    	    	request.setAttribute("newslist", list);
    		} catch (Exception e) {
    			e.printStackTrace();
    			ctx.log("뉴스 목록 생성 과정에서 문제 발생!!");
    			request.setAttribute("error", "뉴스 목록이 정상적으로 처리되지 않았습니다!!");
    		}
        	return "ch10/newsList.jsp";
        }
        
        public String getNews(HttpServletRequest request) {
            int aid = Integer.parseInt(request.getParameter("aid"));
            try {
    			News n = dao.getNews(aid);
    			request.setAttribute("news", n);
    		} catch (SQLException e) {
    			e.printStackTrace();
    			ctx.log("뉴스를 가져오는 과정에서 문제 발생!!");
    			request.setAttribute("error", "뉴스를 정상적으로 가져오지 못했습니다!!");
    		}
    
        	return "ch10/newsView.jsp";
        }
            
        // multipart 헤더에서 파일이름 추출
    	private String getFilename(Part part) {
            String fileName = null;   
            // 파일이름이 들어있는 헤더 영역을 가지고 옴
            String header = part.getHeader("content-disposition");
            //part.getHeader -> form-data; name="img"; filename="사진5.jpg"
            System.out.println("Header => "+header);
    
            // 파일 이름이 들어있는 속성 부분의 시작위치를 가져와 쌍따옴표 사이의 값 부분만 가지고옴
            int start = header.indexOf("filename=");
            fileName = header.substring(start+10,header.length()-1);        
            ctx.log("파일명:"+fileName);        
            return fileName; 
    	}
    }

     

    NewsDAO.java

    getAll 에서 날짜부분 쿼리에서 에러가 떠 String sql = "select aid, title, date from news"; 로 수정했다. 그 외에 날짜가 관련되는 부분들을 전체적으로 수정하고,   cdate는 date로 수정했다.

    package ch10;
    
    import java.sql.Connection;
    import java.sql.DriverManager;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.SQLException;
    import java.util.ArrayList;
    import java.util.List;
    
    public class NewsDAO {
    	final String JDBC_DRIVER = "org.h2.Driver";
    	final String JDBC_URL = "jdbc:h2:tcp://localhost/~/jwbookdb";
    	
    	// DB 연결을 가져오는 메서드, DBCP를 사용하는 것이 좋음
    	public Connection open() {
    		Connection conn = null;
    		try {
    			Class.forName(JDBC_DRIVER);
    			conn = DriverManager.getConnection(JDBC_URL,"jwbook","1234");
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		return conn;
    	}
    	
    	public List<News> getAll() throws Exception {
    		Connection conn = open();
    		List<News> newsList = new ArrayList<>();
    		
    		String sql = "select aid, title, date from news";
    		PreparedStatement pstmt = conn.prepareStatement(sql);
    		ResultSet rs = pstmt.executeQuery();
    		
    		try(conn; pstmt; rs) {
    			while(rs.next()) {
    				News n = new News();
    				n.setAid(rs.getInt("aid"));
    				n.setTitle(rs.getString("title"));
    				n.setDate(rs.getString("date")); 
    				
    				newsList.add(n);
    			}
    			return newsList;			
    		}
    	}
    	
    	public News getNews(int aid) throws SQLException {
    		Connection conn = open();
    		
    		News n = new News();
    		String sql = "select aid, title, img, date, content from news where aid=?";
    	
    		PreparedStatement pstmt = conn.prepareStatement(sql);
    		pstmt.setInt(1, aid);
    		ResultSet rs = pstmt.executeQuery();
    		
    		rs.next();
    		
    		try(conn; pstmt; rs) {
    			n.setAid(rs.getInt("aid"));
    			n.setTitle(rs.getString("title"));
    			n.setImg(rs.getString("img"));
    			n.setDate(rs.getString("date"));
    			n.setContent(rs.getString("content"));
    			pstmt.executeQuery();
    			return n;
    		}
    	}
    	
    	public void addNews(News n) throws Exception {
    		Connection conn = open();
    		
    		String sql = "insert into news(title,img,date,content) values(?,?,CURRENT_TIMESTAMP(),?)";
    		PreparedStatement pstmt = conn.prepareStatement(sql);
    		
    		try(conn; pstmt) {
    			pstmt.setString(1, n.getTitle());
    			pstmt.setString(2, n.getImg());
    			pstmt.setString(3, n.getContent());
    			pstmt.executeUpdate();
    		}
    	}
    	
    	public void delNews(int aid) throws SQLException {
    		Connection conn = open();
    		
    		String sql = "delete from news where aid=?";
    		PreparedStatement pstmt = conn.prepareStatement(sql);
    		
    		try(conn; pstmt) {
    			pstmt.setInt(1, aid);
    			// 삭제된 뉴스 기사가 없을 경우
    			if(pstmt.executeUpdate() == 0) {
    				throw new SQLException("DB에러");
    			}
    		}
    	}
    }

     

    뉴스 목록에서 이미지를 불러오지 못하는 문제가 있다. 수업 시간이 끝나서 문제점을 더 찾아보지는 못하고 다음 수업 때 이미지를 불러올 수 있는 방법이 있는지 다시 찾아볼 계획이다.


    사용된 pom.xml 코드 전문

    <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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>jwbook</groupId>
      <artifactId>jwbook</artifactId>
      <version>0.0.1-SNAPSHOT</version>
      <packaging>war</packaging>
      <build>
        <plugins>
          <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
              <release>17</release>
            </configuration>
          </plugin>
          <plugin>
            <artifactId>maven-war-plugin</artifactId>
            <version>3.2.3</version>
          </plugin>
        </plugins>
      </build>
      
      <!--라이브러리 추가-->
      <dependencies>
    	<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
    	<dependency>
    	    <groupId>javax.servlet</groupId>
    	    <artifactId>jstl</artifactId>
    	    <version>1.2</version>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
    	<dependency>
    	    <groupId>com.h2database</groupId>
    	    <artifactId>h2</artifactId>
    	    <version>2.2.224</version>
    	    <scope>runtime</scope>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/commons-beanutils/commons-beanutils -->
    	<dependency>
    	    <groupId>commons-beanutils</groupId>
    	    <artifactId>commons-beanutils</artifactId>
    	    <version>1.9.4</version>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
    	<dependency>
    	    <groupId>org.apache.commons</groupId>
    	    <artifactId>commons-collections4</artifactId>
    	    <version>4.4</version>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/commons-logging/commons-logging -->
    	<dependency>
    	    <groupId>commons-logging</groupId>
    	    <artifactId>commons-logging</artifactId>
    	    <version>1.3.0</version>
    	</dependency>
    	
    	<!--12장-->
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.containers/jersey-container-servlet -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.containers</groupId>
    	    <artifactId>jersey-container-servlet</artifactId>
    	    <version>2.33</version>
    	</dependency>
    	
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.inject/jersey-hk2 -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.inject</groupId>
    	    <artifactId>jersey-hk2</artifactId>
    	    <version>2.33</version>
    	</dependency>
    
    	<!-- https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-json-jackson -->
    	<dependency>
    	    <groupId>org.glassfish.jersey.media</groupId>
    	    <artifactId>jersey-media-json-jackson</artifactId>
    	    <version>2.33</version>
    	</dependency>
    
    
      </dependencies>
    </project>
Designed by Tistory.