본문 바로가기
교재 실습/자바 웹 프로그래밍 Next Step

4.2.1.2 요구사항 2 - GET 방식으로 회원가입하기

by Jint 2025. 2. 17.
요구사항 "회원가입" 메뉴를 클릭하면 http://localhost:8080/user/form.html 으로 이동하면서 회원가입할 수 있다. 회원가입 한다.
회원가입을 하면 다음과 같은 형태로 사용자가 입력한 값이 서버에 전달된다.

/user/create?userId=javajigi&password=password&name=JaeSung&email=javajigi%40slipp.net

HTML과 URL을 비교해 보고 사용자가 입력한 값을 파싱(문자열을 원하는 형태로 분리하거나 조작하는 것을 의미)해 model.User 클래스에 저장한다.

 

"회원가입" 메뉴를 클릭하면 회원가입 화면에 접근할 수 있다. 회원가입 버튼을 클릭해 회원가입을 한다. 회원가입을 할 경우 사용자가 입력한 데이터를 웹 서버에 전달해야 한다. 이클립스 콘솔을 통해 사용자가 입력한 데이터가 어떻게 전달되는지 확인해 볼 수 있다.

요청 메세지를 분석해보면, 첫 번째 라인에 사용자가 입력한 데이터가 다음과 같은 구조로 전달되는 것을 확인할 수 있다.

 

GET /user/create?userId=javajigi&password=password&name=JaeSung&email=javajigi%40slipp.net HTTP/1.1

 

위와 같이 요청이 보내진 이유는 user/form.html 파일을 열어보면 알 수 있다. form.html 파일의 form 태그를 보면 다음과 같이 구현되어 있다.

 

- webapp/user/form.html

...
<form name="question" method="get" action="/user/create">
    <div class="form-group">
        <label for="userId">사용자 아이디</label>
        <input class="form-control" id="userId" name="userId" placeholder="User ID">
    </div>
    <div class="form-group">
        <label for="password">비밀번호</label>
        <input type="password" class="form-control" id="password" name="password" placeholder="Password">
    </div>
    <div class="form-group">
        <label for="name">이름</label>
        <input class="form-control" id="name" name="name" placeholder="Name">
    </div>
    <div class="form-group">
        <label for="email">이메일</label>
        <input type="email" class="form-control" id="email" name="email" placeholder="Email">
    </div>
    <button type="submit" class="btn btn-success clearfix pull-right">회원가입</button>
    <div class="clearfix" />
</form>
...

 

웹 브라우저는 회원가입 버튼을 클릭하면 HTML form 태그 구현에 따라 요청 라인을 생성해 서버에 요청을 보낸다.

요청 라인의 "GET"은 form 태그 method 속성 값이고, 요청 URI는 action 속성 값(/user/create)이다. GET 메서드 방식으로 요청을 보낼 경우 사용자가 입력한 값을 물음표 뒤에 '매개변수명1=값1&매개변수명2=값2' 형식으로 전송한다.

앞의 회원가입을 위한 요청 URI에 대해 더 자세하게 살펴보자. "/user/create"는 요청 자원의 위치를 나타내는 경로(path)라 부르고, 물음표 뒤에 전달되는 매개변수를 쿼리 스트링(query string)이라고 부른다.

회원가입 기능을 구현하려면 먼저 경로와 쿼리 스트링을 분리해야 한다. 이후 쿼리 스트링에서 사용자가 입력한 값은 매개변수와 값으로 분리해 User 객체에 저장하는 방식으로 구현해야 한다. 물음표(?)를 기준으로 경로와 쿼리 스트링으로 분리하는 방법은 물음표 기준으로 split(), 정규표현식 사용, 물음표가 위치하는 위치 값(index)을 사용하는 방법 등 여러가지가 있다. 힌트에서는 물음표가 위치하는 위치 값을 찾아 분리하는 방법으로 구현했다. 쿼리 스트링을 매개변수와 값으로 분리해 Map<String, Object>에 저장하는 API는 이미 프로젝트 소스에 구현되어 있다. 힌트를 참고해 구현한 결과는 다음과 같다.

 

- RequestHandler.java

package webserver;

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.File;
import java.nio.file.Files;
import java.net.Socket;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RequestHandler extends Thread {
    private static final Logger log = LoggerFactory.getLogger(RequestHandler.class);

    private Socket connection;

    public RequestHandler(Socket connectionSocket) {
        this.connection = connectionSocket;
    }

    public void run() {
        log.debug("New Client Connect! Connected IP : {}, Port : {}", connection.getInetAddress(), connection.getPort());

        try (InputStream in = connection.getInputStream(); OutputStream out = connection.getOutputStream()) {
            // TODO 사용자 요청에 대한 처리는 이 곳에 구현하면 된다.
            BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
            String line = br.readLine();
            log.debug("request line : {}", line);

            if (line == null) {
                return;
            }

            String[] tokens = line.split(" ");

            while (!line.equals("")) {
                line = br.readLine();
                log.debug("header : {}", line);
            }

            String url = tokens[1];
            if (url.startsWith("/user/create")) {
                int index = url.indexOf("?");
                String queryString = url.substring(index + 1);
                Map<String, Object> params = HttpRequestUtils.parseQueryString(queryString);
                User user = new User(params.get("userId"), params.get("password"), params.get("name"), params.get("email"));
                log.debug("User : {}", user);
            } else {
                DataOutputStream dos = new DataOutputStream(out);
                // byte[] body = "Hello World".getBytes();
                byte[] body = Files.readAllBytes(new File("./webapp" + tokens[1]).toPath());
                response200Header(dos, body.length);
                responseBody(dos, body);
            }
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    private void response200Header(DataOutputStream dos, int lengthOfBodyContent) {
        try {
            dos.writeBytes("HTTP/1.1 200 OK \r\n");
            dos.writeBytes("Content-Type: text/html;charset=utf-8\r\n");
            dos.writeBytes("Content-Length: " + lengthOfBodyContent + "\r\n");
            dos.writeBytes("\r\n");
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }

    private void responseBody(DataOutputStream dos, byte[] body) {
        try {
            dos.write(body, 0, body.length);
            dos.flush();
        } catch (IOException e) {
            log.error(e.getMessage());
        }
    }
}

 

위와 같이 구현한 후 회원가입을 하면 사용자가 입력한 값이 서버에 전달되는지 이클립스 콘솔을 통해 확인할 수 있다. 데이터가 서버에 정상적으로 전달되었는지 확인할 수 있는데 브라우저에서 "수신된 데이터 없음"과 같은 형태로 에러 메시지가 출력된다. 그 이유는 회원가입에 대한 처리를 끝낸 후 응답을 보내지 않았기 때문이다. 위 소스코드를 수정해 index.html을 응답으로 보내도록 구현해 본다.

GET 방식으로 사용자가 입력한 데이터를 전달하는 데는 몇 가지 문제점이 있다. 대표적으로 사용자가 입력한 데이터가 브라우저 URL 입력창에 표시된다. 회원가입을 하는 경우 비밀번호까지 URL에 노출되기 때문에 보안 측면에서도 좋지 않다. 또한 요청 라인의 길이에 제한이 있다. 따라서 GET 방식으로 사용자가 입력할 수 있는 데이터 크기에도 제한이 있다.

따라서 GET 방식은 회원가입, 블로그 글쓰기, 질문하기 등과 같이 사용자가 입력한 데이터를 서버에 전송해 데이터를 추가할 때는 적합하지 않다. 이 같은 GET 방식의 한계를 극복하기 위해 HTTP는 POST 방식을 지원한다. HTTP의 POST 방식은 어떻게 데이터를 전달하는지 다음 요구사항을 구현하면서 알아본다.



참고도서 : https://roadbook.co.kr/169

 

[신간안내] 자바 웹 프로그래밍 Next Step

● 저자: 박재성 ● 페이지: 480 ● 판형: 사륙배변형(172*225) ● 도수: 1도 ● 정가: 30,000원 ● 발행일: 2016년 9월 19일 ● ISBN: 978-89-97924-24-0 93000 [강컴] [교보] [반디] [알라딘] [예스24] [인터파크] [샘

roadbook.co.kr

댓글