Computer Science/Spring

[자바 웹 개발 워크북] 1장: 웹 프로그래밍의 시작

무니화니 2024. 4. 10. 17:27

기존에 장고를 가지고 몇 번 제작을 해봤었는데, 자바 스프링으로 새롭게 코딩을 진행해보려고 한다.

이 책을 ebook으로 구매했고, 해당 책의 커리큘럼에 따라서 정리해볼 예정이다.

책에 있는 코드를 그대로 작성하는게 아니라, 내가 생각했을 때 더 중요하다고 생각이 드는 부분은 더 공부를 해서 정리해서 작성하려고 한다.


1.1 자바 웹 개발 환경 만들기

먼저, 웹 프로젝트의 기본적인 구조가 제시되어 있다. 웹 프로젝트는 브라우저, 서버, 데이터베이스의 상호연결로 이루어져있다.결국 브라우저는 서버에서 전달한 결과를 화면에 렌더링하고, 사용자의 작동을 통해 서버와 데이터를 주고받는다. 이때 사용자가 서버에 보내는 것을 요청 (Request), 서버가 사용자에게 보내는 것을 응답 (Response) (사용자 입장에서 생각하면, '요청'을 하고, '응답'을 하는거니까)이라 한다.

웹 서버랑 WAS (Web Application Server)는 둘 다 서버인데, 웹 서버는 '이미지, html'처럼 고정적인 (static)한 데이터를 제공하고, 매번 새로운 데이터가 가능한 동적인 데이터는 WAS가 맡는다. 하지만 WAS는 서버의 기능도 하기 때문에 WAS로만도 static한 데이터와 동적인 데이터가 모두 사용 가능하기에, WAS만 이용해서도 구성할 수 있다.

데이터베이스는 데이터를 저장하는 보관 프로그램이다. SQL와 NoSQL 두가지 종류가 있는데, SQL은 관계형 데이터베이스, 즉 행과 열로 이루어진 데이터베이스 형식이다. 그리고 쿼리를 이용해서 데이터를 저장, 변경, 삭제, 조회가 가능하다. MySQL, SQLite, MariaDB, PostgreSQL 등 다양한 종류들이 있다.NoSQL은 비관계형 데이터베이스로, 관계형이 아닌 모든 데이터베이스를 의미한다. 트리 형태, 키 밸류 형태, 문서형 형태 등 다양한 모양새가 가능하고, MongoDB, Redis가 대표적인 DB이다.

또한 이 실습에서는 톰캣 (Tomcat)이라는 WAS를 사용한다. JSP, 서블릿을 처리해주고, HTTP 요청 수신 및 응답, URL을 서블릿 코드로 매칭시켜주는 등 모든 서버의 역할을 톰캣이 해준다. 톰캣은 아파치 톰캣이라고도 불리는데, 이 톰캣은 아파치와 서로 정확히 다른 것이다. 아파치는 웹 서버, 즉 정적인 데이터를 다루는 서버이고, 아파치 톰캣은 동적인 데이터를 다루는 WAS이다. 그렇지만, 아파치 톰캣이라고 불리는 이유는 '아파치' 사에서 만들었기도 하고, 아파치의 기능을 하고 있기도 하기 때문이다.

현재 IDE는 IntelliJ Ultimate로 선정하였다. 하지만 IntelliJ에서 톰캣으로 실행을 할 때, 한국어가 잘 나오지 않는 경우가 있다. 이때, Edit Custom VM Options에서 UTF-8로 설정을 바꾸어줘야 한다. (구글에 IntellJ 한글 깨짐 이라고 검색할 것.)

이후 JSP 파일과 서블릿 파일을 만들어서 실행해본다.

서블릿 파일은 Java 파일과 유사하게 생겼다. HttpServlet이라는 클래스를 상속해서 작성하기 때문에, 서블릿 클래스를 생성한다고 말하기도 한다.

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="myServlet", urlPatterns = "/my")
public class Myservlet  extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws
            ServletException, IOException{
        PrintWriter out=resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>MyServlet</h1>");
        out.println("</body></html>");

    }
}

자바의 형태를 가지고, HTML을 다룬다라고 생각했다.

이후, JSP 코드를 작성해보았다.

이번에는 HTML의 형태를 가지고 있는 코드라고 상상하였다.

<%--
  Created by IntelliJ IDEA.
  User: a
  Date: 2024-04-04
  Time: 오후 4:22
  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>

1.2 웹 기본 동작방식 이해하기

먼저 Request와 Response에 대한 설명을 더욱 자세하게 해준다.

GET 방식은 주소창에 데이터를 적거나 링크를 클릭함으로서 호출되는 방식이다. ?, '&,='을 이용하여 전송하며, 바로 URL을 통해 공유가 가능하기 때문에 간편하다. 특정 정보의 조회 용도로 많이 사용된다.

POST 방식은 입력 화면에서 필요한 내용을 작성하고, '전송'버튼과 같은 것으로 호출한다. 주소와 데이터가 따로 전달된다.

이러한 GET 방식과 POST 방식을 통해, 사용자가 서버에 데이터를 요구하는 것을 요청, 서버가 이에 대한 응담을 한다고 할 수 있다.

여기서 서버는 정적인 데이터, 동적인 데이터인지를 확인하여 다르게 처리한다.

정적 (static) 데이터는 HTML, CSS, 이미지 파일 등 고정되어 있는 파일을 전송하는 식으로 보내는 것이 바로 웹 서버이고,

동적 (dynamic)한 데이터를 (매번 다른 내용을 가지는 데이터, ex) 메일함, 채팅로그)를 보내는 서버가 바로 WAS이다.

또한 프로토콜에 대해서 정의되어 있는데, 브라우저의 요청과 서버의 응답 사이에서 처리되기로 한 데이터 교환 약속을 프로토콜이라고 한다. 보통 http와 https를 의미하고, https는 http보다 보안이 강화된 프로토콜이다.

서로 서버와 클라이언트가 주고 받는 내용을 확인하고자 한다면, f12를 눌러서 network 탭을 선택하여 볼 수 있다.

1.3 Web MVC 방식

서블릿 코드와 jsp 코드 모두 자바 웹 프로그래밍에서 화면을 렌더링하는데 사용이 가능하다. 그렇지만 JSP는 GET과 POST의 호출을 구별하지 않아서 서버 오류가 날수도 있고, 유지 보수 차원에서도 불리하다. 따라서, JSP는 오로지 입력 화면을 보여줄 때만 사용하고, 나머지 로직들은 서블릿을 통해서 처리하도록 구현한다.

이러한 내용을 MVC 패턴을 이용하여 구현할 것이다. MVC 구조는 'Model, View, Controller'의 역할을 분리하여 처리하는 구조이다. 여기서 View의 역할을 JSP가, 서블릿이 Controller의 역할을 맡게 된다.

  • 서블릿
    • Request에 필요한 데이터 완성
    • 상속과 인터페이스 활용
  • JSP
    • EL을 이용하여 데이터를 출력
    • HTML 코드 활용
    • 브라우저 화면 구성 완성

'''
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
package org.zerock.w1;

import java.io.IOException;
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(
name = "calcController",
urlPatterns = {"/calc/makeResult"}
)
public class CalcController extends HttpServlet {
public CalcController() {
}

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");
}

'''

웹 MVC 구조에서 PRG 패턴을 자주 사용한다.
PRG 패턴 (Post-Redirect-GET)이란,

  • 사용자는 컨트롤러에 원하는 작업을 POST 방식으로 요청하고,
  • POST 방식을 컨트롤러에서 처리, 브라우저는 다른 경로로 이동 (GET)하라는 응답을 보내고,
  • 브라우저는 GET 방식으로 이동한다.

이후 본격적인 Todo App을 제작한다.
화면을 보여주는 것은 GET, 무언가를 입력해야 하는 것들은 다 POST로 선언할 것이다.

1.4 HttpServlet

HttpServlet은 클래스인데, GET과 POST를 doGET(), doPOST()와 같은 방식으로 제공한다. 그리고 HttpServlet을 오버라이드함으로서 자신만의 코드를 작성할 수 있다.

오버라이드?: 오버라이드 (Override)는 부모 클래스에서 상속받은 메서드를 자식 클래스에서 재정의하는 것이다.
오버로드?: 오버로드 (Overload)는 한 클래스에서 이미 사용하려는 이름과 같은 이름을 가진 메서드가 있을 때, 매개변수나 타입이 다르면 같은 이름을 사용하여 메서드를 정의할 수 있음을 의미한다.

HttpServlet의 라이프사이클:
0. ** 개발자가 객체를 직접 제작하는게 아니라, 톰캣에서 객체들을 관리해준다. **

  1. 브라우저가 톰캣에게 서블릿이 처리해야하는 경로를 제시한다.
  2. 톰캣이 경로에 맞는 서블릿 클래스를 로딩하고, 객체를 생성한다.
  3. init() 메서드가 실행된다.
  4. 만들어진 서블릿. 브라우저에 요청 (GET, POST)과 각종파라미터들을 전달받고, doGET, doPOST 등의 메서드들이 실행된다.
  5. 톰캣이 종료될 때 destory()가 실행된다.

HttpServletRequest / HttpServletResponse에 각종 함수들이 있다.

  • getParameter() : 쿼리 스트링에서 key를 이용해 값을 얻는 역할. (결과는 항상 string)
  • getParameterValues(): 동일한 파라미터가 여러 개 존재할 때 사용. String[] xkdlqdmfh qusghks.
  • setAttribute(): JSP로 데이터를 전달할 때 사용.
  • getRequestDispatcher(): RequestDispatcher 타입의 객체를 구할 수 있음.
    • forward(): 현재까지의 모든 응답을 무시하고 JSP가 작성하는 내용만을 브라우저로 전달
    • include(): 지금까지 만들어진 응답의 내용과 JSP가 만든 내용을 브라우저로 전달
  • sendRedirect(): 브라우저에게 지정된 주소로 가게끔 함

1.5 모델 (Model)

DTO를 통해서 프레젠테이션 계층, 서비스 계층, 영속 계층을 이동함. DTO (Data Transfer Object)를 이용하여 여러개의 데이터를 묶어서 필요한 곳에 전달하거나 호출을 결과를 얻는 방식으로 사용하고, Java Beans 형태로 대부분 사용함.