Spring - 기본구조와 Tomcat(서블릿) 그리고 GET/POST

HI_DO·2024년 6월 5일
post-thumbnail

스프링 부트가 2버전은 jdk 11버전
스프링 부트가 3버전은 jdk 17버전이어야 한다

웹프로그래밍은 직접 작성하는 main()을 실행하지도 않고, 단순히 JDK만으로 모든 개발이 완료되지 않는다. 개발자가 모든 처리 과정을 직접 설계하는 방식이 아니라 반대로 개발자의 코드를 정해진 구조에 넣는 방식이기 때문에 전체적인 구조와 흐름을 이해해야만 한다.

웹 프로젝트의 기본구조

  • 대부분의 웹 프로젝트들은 기본적으로 여러 프로그램이 같이 네트워크를 통해서 연결되는 구조로 이루어진다.
  • 브라우저(클라이언트)
    -> 서버에서 전송한 결과를 화면에 보여주고(렌더링) 사용자의 화면 조작을 이용해서 서버에 원하는 데이터를 보내고(REQUEST) 받는(response) 프로그램
  • 관련 기술 : html, css, javascript
  • 웹 서버 혹은 WAS(Web Application Server) : 동적으로 매번 새로운 데이터를 만들어 낼 수 있는 웹 서버 (실제 운영환경에서는 보통 웹 서버와 was를 분리해서 운영하지만, 대부분의 WAS는 웹 서버 기능도 겸하고 있으므로 우리는 WAS만으로 구성 가능)
    -> 관련 기술 : 서블릿/JSP, 각종 프레임 워크
  • 데이터 베이스 : 영구적으로 데이터를 보관하고 운영하기 위한 프로그램으로 기본적으로 관계형 데이터 베이스를 사용
    -> 관련 기술: SQL, 데이터베이스 설계/구현

https://www.jetbrains.com/ko-kr/idea/download/?section=windows

Tomcat

tomcat.apache.org 에서 Tomcat.zip 다운로드
-> c드라이브에 Tomcat폴더 만들어서 폴더 안에 zip 풀기




인텔리제이 설정

  1. 한글로 설정

    -> 한글로 변경
    help->find action ->vm 검색 ->edit custom VM option -> 아래 코드로 수정
-Xmx2048m
-Dfile.encoding=UTF-8
-Dconsole.encoding=UTF-8
  1. 프로젝트의 경로 설정

실행중인 톰캣 중지 -> run -> edit configurations 선택 -> 탭메뉴에서 [Deployment]를 선택하고 기존에 있는 Gradle: org.zerock:w1-,,,,를 [-]를 눌러 제거하고 -> 다시[+]를 눌러서 'Artifact'를 '(exploded)'가 포함된 항목으로 지정 -> 아래쪽에 'Application context의 값을 '/'로 지정 ->localhost가 8080으로 변경 됨










ctrl+마우스휠 로 확대 축소 가능

서블릿

  • Tomcat에서 작성하는 자바코드는 HttpServlet라는 클래스를 상속해서 작성하는데 흔히 서블릿 클래스를 생성한다고 표현한다
  • 서버에서 동적으로 요청과 응답을 처리할 수 있는 API들을 정의하는 것
  • 서블릿을 지원하는 환경에서 개발자들은 서블릿에서 제공하는 API를 이용해서 코드를 작성하고 이를 설정하는 방식으로 서블릿 프로그램을 작성하게 된다.
  • 서블릿의 실행은 Tomcat과 같이 서블릿을 실행할 수 있는 환경에서 실행이 가능한데 이것을 '서블릿 컨테이너'(이것의 역할을 Tomcat이 해주고 있다)
  • 서블릿 코드를 실행하는 주체는 Tomcat(서블릿 컨테이너)
  • 객체를 생성하거나 호출하는 주체가 자바는 개발자나 사용자가 한다. 반면 서블릿은 서블릿 컨테이너가 한다.
  • 서블릿 클래스에서 생성하는 객체의 관리 ->서블릿 컨테이너가 함 (API도 서블릿 컨테이너가 한다)
package org.zerock.w1;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
//WebServlet은 브라우저의 경로와 해당 서블릿을 연결하는 설정을 위해서 사용
// name은 웹 애플리케이션 내에서 서블릿을 고유하게 식별하는데 사용
@WebServlet(name="myServlet", urlPatterns = "/my")
public class MyServlet extends HttpServlet {
    @Override       // doGet: 브라우저의 주소를 직접 변경해서 접근하는 경우에 호출되는 메서드
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>MyServlet</h1>");
        out.println("</body><html>");
    }
}
  • 결과

JSP작성

  • 서블릿 기술과 동일하게 서버에서 동적으로 데이터를 구성하는 기술
  • 서블릿이 있는데도 불구하고 '동일한 목적'으로 jsp가 제공되는 이유는 두 기술의 목적 자체가 다르기 때문이다. -> jsp는 서블릿 기술과 같은 목적이지만, 브라우저에 보내는html데이터를 만들어내는데 좀 더 특화된 기술
  • JSP파일은 서블릿 코드로 변환되어 컴파일되서 실행된다. JSP파일은 자바파일로 생성되고 이를 컴파일해서 class파일로도 만들어진다.
  • JSP(Java Server Pages)는 근본적으로 서블릿과 같은 원리지만 좀 더 HTML을 쉽게 이용할 수 있는 방식으로 코드를 작성할 수 있기 때문에 서블릿으로는 코드를 이용한 처리
    JSP로는 화면 개발과 같이 역할을 분담해서 개발하는 것이 일반적이다
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 2:35
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>Test JSP PAGE</h1>
</body>
</html>
  • 결과

웹 기본동작 방식

  • 웹 애플리케이션을 작성하려면 브라우저와 서버의 관계를 이해해야만 한다.
  • 서블릿과 jsp가 어떤 과정을 통해서 브라우저에 데이터를 전달하고 브라우저에서 어떤식으로 사용하게 되는지 알아야한다.

Request(요청) / Response(응답)

브라우저는 자신이 원하는 정보를 전달하기 위해서 두가지 방식을 이용한다.

  • GET방식 : 주소창에 직접 원하는 데이터를 적거나 링크를 클릭해서 호출 원하는 웹의 주소를 호출할때 필요한 데이터를 '?','&'를 이용해서 전송하는 방식
    주소와 필요한 데이터를 한번에 같이 보내기 때문에 단순링크로 처리되므로 다른 사람들에게 메신저나 SNS등을 통해 쉽게 공유가 가능하다.(주로 정보를 조회하는 용도)
  • POST방식 : 입력화면에서 필요한 내용을 작성한 후에 '전송'과 같은 버튼 등을 클릭해서 호출.
    주소와 데이터를 따로 보내는 방식.(회원가입, 로그인 등)
  • 브라우저에서 서버에 방식으로 데이터를 요구하는 것을 요청(Request)라고 하고, 서버는 이에 대한 응답(Response) 데이터를 만들어서 브라우저로 보내게 된다. 하나의 서버에 여러 브라우저가 무언가를 요청하고 응답받는 구조
  • 서버에서는 브라우저로 응답(Response)을 보내는데 서버에서는 정적인 데이터인지 동적인 데이터인지애 따라 다르게 처리한다.
  • 정적(static) 데이터: 항상 동일하게 고정된 데이터를 전송하는 방식 html, css, 이미지.
  • 동적(dynamic) 데이터 : 매번 필요할 때마다 다른 데이터를 동적으로 구성해서 전송하는 방식. 예를 들어 메일함처럼 상황에 따라 동적으로 서버에서 데이터를 만들어 보내는 방식(서버 사이드 프로그래밍)
  • 항상 같은 정적데이터를 보내는 역할만 수행하는 서버는 '웹 서버(Web Server)라고 하고 동적데이터를 만들어 보내는 경우는 '웹 애플리케이션 서버,WAS'로 구분한다.

HTTP

  • 브라우저의 요청과 서버의 응답에는 약속을 통해서 처리가 되는데 이러한 데이터 교환약속을 '프로토콜(protocol)' 이라고 하고, 웹에서는 HTPP(Hyper Text Transfer Protocol)이라는 방식으로 데이터를 주고 받는다.

JSP를 이용해서 GET/POST 처리

GET방식

GET방식은 입력과 조회 : 원하는 데이터를 조회, 사용자가 입력할 수 있는 화면

  • calc폴터와 input.jsp 생성
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form>
    <input type="number" name="num1">
    <input type="number" name="num2">
    <button type="submit">SEND</button>
</form>
</body>
</html>
  • 실행 및 결과



    -> 웹에서 주소창 뒤에 '?'로 시작하는 내용을 쿼리 스트링(query string)이라고 한다.
    무언가를 요구하거나 물어보는 용도로 데이터를 전달하기 위해서 사용.
    쿼리스트링은 '키=값'의 형태로 데이터를 전달하는데 여러 개의 데이터가 필요한 경우에는 '&'를 이용해서 연결한다.

POST방식

<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="calcResult.jsp" method="post">
    <input type="number" name="num1">
    <input type="number" name="num2">
    <button type="submit">SEND</button>
</form>
</body>
</html>
  • 실행 및 결과
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>NUM1 ${param.num1}</h1>
<h1>NUM2 ${param.num2}</h1>
</body>
</html>
  • 실행 및 결과


  • 복잡한 처리결과(할 수는 있지만 적합하지 않음)
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:56
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<h1>NUM1 ${param.num1}</h1>
<h1>NUM2 ${param.num2}</h1>
<h1>SUM ${Integer.parseInt(param.num1)+Integer.parseInt(param.num2)}</h1>
</body>
</html>
  • 실행 및 결과


    -> JSP는 기본적으로 GET/POST방식의 호출을 구분하지 않기 때문에 POST방식으로 접근해야 하는 calcResult.jsp를 GET방식으로도 호출할 수 있다는 문제가 있다.
  • 윗글을 참고하여 post를 get으로 바꿨을 때
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="calcResult.jsp" method="get">
    <input type="number" name="num1">
    <input type="number" name="num2">
    <button type="submit">SEND</button>
</form>
</body>
</html>
  • 실행 및 결과


    -> 차이점이 전혀 없다
    -> 유지 보수 측면에서도 문제가 발생하는데 예를 들어 input.jsp 대신에 input2.jsp와 같이 다른 jsp파일로 변경했을 경우 사용자들에게는 다시 주소가 변경되엇다는 점을 알려줘야 하는 번거로움이 발생하게 된다.
    -> 결론!!!!
    JSP에서 쿼리스트링이나 파라미터를 처리하지 않는다(서블릿을 통해서 처리)
    JSP는 입력화면을 구성하거나 처리 결과를 보여주는 용도로만 사용
    브라우저는 직접 JSP경로를 호출하지 않고 서블릿 경로를 통해서 JSP를 보는 방식으로 사용
    -> 이러한 문제를 해결하기 위해 등장한 방식이 웹 MVC방식으로 JSP는 결과만 출력하고 처리는 서블릿을 이용하는 방식으로 진행한다.

Web MVC

  • MVC형식으로 서블릿과 JSP를 같이 이용하는 형태로 개발
  • 서블릿 코드는 자바코드를 그대로 이용할 수 있고, 상속이나 인터페이스의 처리도 가능하다.
  • JSP의 경우 반대로 HTML 코드를 바로 사용할 수 있으므로 HTML메시지 작성에는 적합하지만 그 안에 자바코드를 재사용하는 문제나 자바코드와 HTML코드를 혼용하는 것 같은 여러 문제가 존재한다.

    -> 요청오면 서블릿은 준비한 데이터들을 JSP로 전달하고 JSP는 생성된 결과화면을 Tomcat을 통해서 브라우저로 전송된다.
  • 웹 MVC라는 구조는 Modle-View-Controller의 역할을 분리해서 처리하는구조
  • 데이터는 컨트롤러에서 처리하고 결과는 뷰에서 처리한다
  • 서블릿이 컨트롤러 역할이고 JSP가 뷰 역할이라고 할 수 있다.
  • 컨트롤러 역할을 하는 서블릿은 JSP에 필요한 데이터를 가공하는 역할을 하는데 이때 필요한 데이터를 제공하는 객체를 모델(Model)이라고 한다.

package org.zerock.w1.calc;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "inputController" , urlPatterns = "/calc/input")
public class InputController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("InputController...doGet...");
        // 서블릿에 전달된 요청(request)을 다른 서버쪽으로 전달 혹은 배포하는 역할.
        RequestDispatcher dispatcher = req.getRequestDispatcher("/WEB-INF/calc/input.jsp");
        // 현재까지 모든 응답의 내용은 무시하고 jsp가 작성하는 내용만을 브라우저로 전달.
        dispatcher.forward(req,resp);
    }
}


-> 브라우저가 호출하면 8KB를 한꺼번에 몰아서 가져옴
입출력이 자주 일어나느 것보다 한번에 데이터를 가져오는게 효율적 (이 공간을 버퍼라고 함)
서블릿 만들어 놓은 결과가 어느정도 데이터를 담아 input.jsp를 호출하면 forward를 통해서 넘겨주게 됨.
post는 처리를 하게 되고 jsp는 보여주는 공간으로 분리가 되어져 있다.

  • WEB-INF는 브라우저에서 직접 접근이 불가능한 경로
    WEB-INF 밑에 JSP파일을 둔다는 의미는 브라우저에서 JSP로 호출이 불가능하다는 것을 의미한다.
  • 실행 및 결과

doPost 메서드

  • CalcController 생성
package org.zerock.w1.calc;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "calcController", urlPatterns = "/calc/makeResult")
public class CalcController extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        String num1 = req.getParameter("num1");
        String num2 = req.getParameter("num2");
        System.out.printf(" num1: %s", num1);
        System.out.printf(" num2: %s", num2);
    }
}
  • input.jsp -> post로 수정
<%--
  Created by IntelliJ IDEA.
  User: EZEN
  Date: 2024-06-05
  Time: 오후 3:45
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="/calc/makeResult" method="post">
    <input type="number" name="num1">
    <input type="number" name="num2">
    <button type="submit">SEND</button>
</form>
</body>
</html>
  • 실행 및 결과

sendRedirect()

  • post방식의 처리는 가능하면 빨리 다른 페이지를 보도록 브라우저 화면을 이동시키는 것이 좋다
package org.zerock.w1.calc;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "calcController", urlPatterns = "/calc/makeResult")
public class CalcController extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
        String num1 = req.getParameter("num1");
        String num2 = req.getParameter("num2");
        System.out.printf(" num1: %s", num1);
        System.out.printf(" num2: %s", num2);
        resp.sendRedirect("/index");
    }
}
  • 입력 및 결과

PRG패턴(post-redirect-get)

  • 대표적인 예시가 게시판
    사용자가 새로운 게시글을 작성하고 post방식으로 전송 -> 서버에서 입력된 게시글을 처리한 후 브라우저의 주소를 목록 화면경로로 이동하도록 Redirect -> 브라우저는 목록화면을 보여주고 사용자는 자신이 추가한 게시글의 결과를 확인

  • TodoListController.java 생성


package org.zerock.w1.todo;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "todoListController", urlPatterns = "/todo/list")
public class TodoListController extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println(("/todo/list"));
        req.getRequestDispatcher("/WEB-INF/todo/list.jsp").forward(req, resp);
    }
}
profile
하이도의 BackEnd 입문

0개의 댓글