Day 35 - JSP Rest API

haxxru log;·2026년 4월 20일
post-thumbnail

이 글은 2026년 04월 20일 작성된 글입니다.

오늘은 폼 처리와 자바스크립트 유효성 검사, REST API와 HTTP 요청 흐름,
그리고 게시물 작성부터 상세페이지까지의 웹 흐름을 정리했다.


1. 폼 학습과 자바스크립트 체크

폼은 사용자가 입력한 값을 서버로 보내기 위한 기본적인 수단이다.
이번에는 폼 자체를 익히고, 자바스크립트로 입력값을 미리 검사하는 흐름까지 함께 학습했다.

<form>
  <input type="text" name="title" placeholder="제목을 입력해주세요">
  <button type="submit">등록</button>
</form>

자바스크립트 폼 체크를 적용하면
제목이나 내용이 비어 있는 상태에서 바로 제출되는 상황을 미리 막을 수 있다.

  • 폼은 입력값을 서버로 전달하는 역할을 한다.
  • 자바스크립트 검사는 사용자 입력 실수를 먼저 걸러준다.

2. 게시물 작성폼에 자바스크립트 유효성 검사 적용

게시물 작성폼에 자바스크립트 검사를 붙여서
제목이나 내용이 비어 있으면 제출되지 않도록 만들었다.

<script>
function checkForm(form) {
  if (form.title.value.trim() === "") {
    alert("제목을 입력해주세요.");
    form.title.focus();
    return false;
  }

  if (form.content.value.trim() === "") {
    alert("내용을 입력해주세요.");
    form.content.focus();
    return false;
  }

  return true;
}
</script>
<form onsubmit="return checkForm(this);">

이렇게 하면 서버에 요청이 가기 전에 1차 검증이 가능하다.
물론 최종 검증은 서버에서도 다시 해야 한다.

  • 클라이언트에서 1차 검증
  • 서버에서 2차 검증

3. REST API와 HTTP 메서드

REST는 자원을 URL로 표현하고,
HTTP 메서드로 어떤 작업을 할지 구분하는 방식이다.

예를 들면 다음과 같다.

GET /articles
POST /articles
PUT /articles/1
PATCH /articles/1
DELETE /articles/1

각 메서드의 의미는 보통 이렇게 나눈다.

  • GET : 조회
  • POST : 생성
  • PUT : 전체 수정
  • PATCH : 부분 수정
  • DELETE : 삭제

같은 URL이라도 메서드가 다르면 역할이 달라진다.

GET /usr/article/write
POST /usr/article/write
  • GET은 작성 폼을 보여주는 역할
  • POST는 실제 작성 데이터를 처리하는 역할

4. URL 입력 시 브라우저에서 일어나는 일

브라우저에 URL을 입력하면 단순히 페이지가 바로 뜨는 것이 아니라
여러 단계를 거쳐 요청과 응답이 오간다.

예를 들어 /usr/article/list를 입력하면 다음과 같은 흐름이 진행된다.

  1. 브라우저가 URL을 HTTP 요청으로 바꾼다.
  2. 도메인을 DNS를 통해 IP 주소로 변환한다.
  3. 서버에 요청을 보낸다.
  4. 서버는 라우팅 규칙에 따라 적절한 코드를 실행한다.
  5. 비즈니스 로직이 수행된다.
  6. 서버가 응답을 보낸다.
  7. 브라우저가 응답 결과를 화면에 보여준다.

이 흐름을 이해하면
웹 개발에서 클라이언트와 서버가 어떻게 연결되는지 훨씬 잘 보인다.


5. 게시물 작성 라우팅 처리

디스패처 서블릿에서 요청 메서드와 URI에 따라
적절한 컨트롤러 메서드로 분기하도록 구성했다.

@WebServlet("/usr/*")
public class DispatcherServlet extends HttpServlet {
    private MemberController memberController;
    private ArticleController articleController;

    @Override
    public void init(ServletConfig config) throws ServletException {
        this.memberController = Container.memberController;
        this.articleController = Container.articleController;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        Rq rq = new Rq(req, resp);

        switch (rq.getMethod()) {
            case "GET" -> {
                switch (rq.getURIPath()) {
                    case "/usr/article/list" -> articleController.showList(rq);
                    case "/usr/article/write" -> articleController.showWrite(rq);
                    case "/usr/member/join" -> memberController.showJoin(rq);
                }
            }
            case "POST" -> {
                switch (rq.getURIPath()) {
                    case "/usr/article/write" -> articleController.doWrite(rq);
                }
            }
        }
    }
}

이 구조를 적용하면 요청이 어디로 들어왔고,
어떤 메서드로 처리해야 하는지가 명확해진다.

  • GET 요청은 주로 화면 노출
  • POST 요청은 주로 데이터 처리

6. 게시물 작성 처리와 계층 분리

게시물 작성을 실제로 처리하는 기능을 만들고,
서비스와 리포지터리 계층도 함께 도입했다.

  • Controller는 요청을 받는다.
  • Service는 핵심 로직을 처리한다.
  • Repository는 데이터를 저장하고 조회한다.

이렇게 역할을 나누면
기능이 늘어나도 구조가 덜 무너지고,
수정 범위도 명확해진다.


7. GET과 POST를 함께 쓰는 이유

게시물 작성 기능은 GET과 POST 둘 다 필요하다.

GET /usr/article/write
POST /usr/article/write

GET은 작성 폼을 보여주는 역할이고,
POST는 사용자가 입력한 데이터를 실제로 저장하는 역할이다.

웹에서는 같은 기능처럼 보여도
화면 노출과 데이터 처리는 분리해서 보는 것이 일반적이다.

  • GET : 페이지 보여주기
  • POST : 데이터 저장하기

8. getActionPath 도입

전체 URI에서 공통 경로를 제외하고
실제로 어떤 동작을 해야 하는지 더 쉽게 꺼내기 위해 getActionPath를 도입했다.

예를 들어 /usr/article/write 같은 경로가 있을 때
액션 경로를 따로 다루면 라우팅 코드가 더 간결해질 수 있다.

  • URI 전체를 직접 계속 비교하지 않아도 됨
  • 라우팅 코드가 더 읽기 쉬워짐

9. 게시물 상세페이지

게시물 목록만 보는 것이 아니라
각 게시물 하나를 자세히 볼 수 있는 상세페이지를 만들었다.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<h1>게시물 상세</h1>
<div>
    <h1>제목 1</h1>
    <div>
        <span>번호 : 1</span>
    </div>

    <div>
        <span>내용 : 내용 1</span>
    </div>

    <div>
        <span>작성일 : 2025-00-00 00:00</span>
    </div>

    <div>
        <a href="/usr/article/list">목록</a>
    </div>
</div>

상세페이지가 생기면서
목록 → 상세 → 다시 목록으로 돌아가는 기본 흐름이 만들어졌다.


10. 게시물 상세페이지 벨리데이션

상세페이지는 단순히 보여주기만 하면 끝나는 것이 아니라
잘못된 요청이 들어왔을 때도 처리할 수 있어야 한다.

예를 들면 이런 경우를 검증해야 한다.

  • id가 없는 경우
  • 숫자가 아닌 값이 들어온 경우
  • 존재하지 않는 게시물 번호인 경우

이런 검증이 있어야 잘못된 URL 요청에도
프로그램이 안전하게 동작한다.


11. 리스트에 상세보기 링크 연결

게시물 목록에서 각 항목을 클릭하면
상세페이지로 이동할 수 있도록 링크를 연결했다.

<a href="/usr/article/detail?id=1">상세보기</a>

이렇게 연결하면
단순한 목록 출력이 아니라 실제 웹 서비스처럼 흐름이 이어지게 된다.

  • 목록에서 상세페이지로 이동 가능
  • 사용자 입장에서 탐색이 쉬워짐

12. Path Variable 방식 도입

기존에는 쿼리스트링 방식으로 값을 전달했다.

/usr/article/detail?id=1

여기서 더 나아가 path variable 방식도 다루기 위해
getLongPathValueByIndex를 도입했다.

/usr/article/detail/1

이 방식은 URL만 봐도 어떤 자원을 가리키는지 더 직관적으로 보인다.

  • 쿼리 파라미터 방식보다 URL이 깔끔함
  • REST 스타일 URL에 더 가깝게 구성 가능

✅ 정리

  • 폼은 사용자 입력을 서버로 전달하는 기본 구조이고, 자바스크립트 검사는 그 전에 1차로 값을 확인하는 역할을 한다.
  • GET과 POST를 분리해서 사용하면 화면 출력과 데이터 처리를 명확하게 나눌 수 있다.
  • DispatcherServlet과 라우팅 구조를 통해 요청을 체계적으로 분기할 수 있게 되었다.
  • 게시물 상세페이지와 링크 연결까지 구현하면서 웹 서비스의 기본 흐름이 점점 완성되어 갔다.
  • 쿼리스트링과 path variable 방식을 비교하면서 URL 설계 방식도 함께 이해할 수 있었다.

0개의 댓글