- ···
- 17.
[멀티캠퍼스] 풀스택 개발자 아카데미 (17) - Servlet/JSP(1) - 18.[멀티캠퍼스] 풀스택 개발자 아카데미 (18) - Servlet/JSP(2)현재
- 19.
[멀티캠퍼스] 풀스택 개발자 아카데미(19) - Servlet/JSP(3) - ···
1. 서버와의 대화
저번 글에서는 Servlet과, JSP의 기본 개념을 통해 동적 웹 애플리케이션의 동작 과정에 대한 큰 그림을 그려보았다. 서블릿이 서버에서 실행되는 자바 클래스라는 점과, JSP가 결국 서블릿으로 변환된다는 사실을 알게 되었다. 하지만 "Hello World"만 출력하는 것으로는 사용자와 소통하는 웹 애플리케이션이라고 할 수 없다. 진정한 동적 웹이란 사용자의 입력에 따라 각기 다른 결롸를 보여주는, 즉 '대화'가 가능한 웹을 의미한다.
이번 글에서는 클라이언트(웹 브라우저)가 보낸 데이터를 서버에서 어떻게 받고 처리하는지, 그리고 그 처리 결과를 어떻게 다시 클라이언트에게 보여주는지에 대해 자세히 알아본다. 이를 위해 웹 통신의 핵심 메서드인 GET과 POST의 차이점을 명확히 구분하고, 서블릿의 HttpServletRequest와 HttpServletResponse 객체를 활용하는 구체적인 방법을 다룬다. 이를 통해 단순한 페이지 요청을 넘어, 데이터를 주고받으며 상호작용하는 웹 애플리케이션의 기본을 알게 될 것이다.
또한, 초기 웹 애플리케이션 구조의 하나인 MVC Model 1 아키텍처의 개념과 그 장단점을 파악하여 앞으로 배울 MVC Model 2의 필요성을 자연스럽게 이해하는 것이 목적이다.
2. 요청(Request) 처리
웹 애플리케이션의 가장 기본적인 역할은 사용자의 요청을 받아 그에 맞는 응답을 주는 것이다. 사용자가 로그인 폼에 아이디와 비밀번호를 입력하고 '로그인' 버튼을 누르는 행위, 게시판에서 특정 게시글 제목을 클릭하는 행위 모두 서버로 보내는 '요청'이다. 서버는 이 요청에 담긴 데이터를 올바르게 해석하고 처리할 수 있어야 한다.
2.1. 데이터 전송 방식: GET vs. POST
클라이언트가 서버로 데이터를 전송하는 방식은 여러 가지가 있지만, 가장 대표적인 것이 GET과 POST 방식이다. 이 둘의 차이점을 이해하는 것은 웹 개발의 기본 중의 기본이다.
GET 방식: 서버로부터 정보를 **조회(Retrieve)**하기 위해 사용되는 메서드이다. 데이터를 URL의 끝에 쿼리스트링(Query String) 형태로 붙여서 전송한다. 예를 들어,
http://example.com/search?query=자바와 같은 형태이다.- 장점: URL에 데이터가 포함되어 있어 해당 페이지를 북마크하거나 다른 사람에게 링크를 공유하기 용이하다. 또한, 브라우저에 의해 캐시될 수 있어 같은 요청에 대해 더 빠르게 응답할 수 있다.
- 단점: URL에 데이터가 그대로 노출되므로 아이디, 비밀번호와 같은 민감한 정보를 보내기에는 보안에 매우 취약하다. 또한, URL의 길이에 제한이 있어 전송할 수 있는 데이터의 양이 한정적이다.
POST 방식: 서버에 데이터를 **전달(Submit)**하여 어떤 작업을 처리하도록 요청하기 위해 사용된다. 데이터는 URL에 표시되지 않고, HTTP 요청 메시지의 본문(Body)에 담겨서 서버로 전송된다.
- 장점: 데이터가 요청 본문에 숨겨져 전송되므로 GET 방식보다 보안에 유리하다. 또한, 전송할 수 있는 데이터의 양에 제한이 거의 없다. 회원가입, 로그인, 파일 업로드 등 서버의 상태를 변경하는 작업에 주로 사용된다.
- 단점: URL에 데이터가 드러나지 않으므로 해당 페이지를 북마크하거나 공유할 수 없다.
정리하자면, 단순히 서버의 데이터를 가져와 보여주는 경우에는 GET을, 사용자의 데이터를 서버로 보내 무언가를 생성하거나 수정하는 등 중요한 작업을 처리할 때는 POST를 사용하는 것이 일반적인 원칙이다.
서블릿에서는 이 두 가지 요청을 처리하기 위해 각각 doGet()과 doPost() 메소드를 제공한다. HTML의 <form> 태그에서 method 속성을 이용해 어떤 방식으로 요청을 보낼지 지정할 수 있다.
2.2. HttpServletRequest 객체
클라이언트가 요청을 보내면, 웹 컨테이너는 해당 요청에 대한 모든 정보를 HttpServletRequest 객체에 담아 서블릿의 doGet() 또는 doPost() 메소드에 인자로 전달한다. 개발자는 이 객체를 통해 사용자가 보낸 데이터를 포함한 다양한 요청 정보를 얻을 수 있다.
request.getParameter(String name):<input>태그의name속성값에 해당하는 데이터를 문자열(String)로 받아온다. 가장 기본적이고 많이 사용되는 메소드다.request.getParameterValues(String name): 체크박스처럼 하나의name으로 여러 값이 전송될 때, 모든 값을 문자열 배열(String[])로 받아온다.request.getParameterNames(): 어떤name들이 있는지 모를 때, 요청으로 들어온 모든name들을Enumeration<String>타입으로 받아온다.request.setCharacterEncoding("UTF-8"): POST 방식으로 전송된 한글 데이터가 깨지는 것을 방지하기 위해 반드시 호출해야 하는 메소드다. 요청 본문의 인코딩을 지정하며,getParameter()를 호출하기 전에 실행되어야 한다.
server.xml)을 통해 URIEncoding을 설정하는 방식으로 해결하는 것이 일반적이다.3. 응답(Response) 처리
서버가 클라이언트의 요청을 처리한 후에는 그 결과를 다시 클라이언트에게 보내주어야 한다. 이때 사용되는 것이 바로 HttpServletResponse 객체이다. 이 객체는 서블릿 컨테이너에 의해 생성되며, 개발자는 이 객체를 통해 응답의 형식, 내용, 상태 등을 제어할 수 있다.
response.setContentType("text/html;charset=UTF-8"): 클라이언트(웹 브라우저)에게 보낼 데이터의 종류(MIME-TYPE)와 문자 인코딩을 알려주는 중요한 메소드다. 이 설정을 통해 브라우저는 "이제부터 오는 내용은 HTML 문서이고, UTF-8로 해석해야 한다"는 것을 인지하게 된다.response.getWriter(): 응답 내용을 작성할 수 있는PrintWriter객체를 반환한다. 이 객체의print()또는println()메소드를 사용해 클라이언트에게 보낼 HTML 코드를 작성할 수 있다.
다음 4.2.의 doPost()에서 나올 3번 부분이 바로 HttpServletResponse를 사용하여 클라이언트에게 동적인 HTML 페이지를 생성하여 보내는 코드이다.
4. 로그인 폼으로 데이터 주고 받기
이제 이러한 이론을 바탕으로 사용자의 아이디와 비밀번호를 입력받아 처리하는 간단한 로그인 폼을 만들어 볼 수 있다.
저번 글과 마찬가지로, 멀티캠퍼스의 강의는 JDK 11, Eclipse IDE, Apache Tomcat 9.0, javax를 사용하며, 필자는 JDK 21, IntelliJ IDEA, Apache Tomcat 10.0, jakarta를 사용한다.
4.1. 로그인 화면 (HTML) 작성
먼저 사용자로부터 입력을 받을 login.html 파일을 src/main/webapp 디렉터리 내에 만들고 다음과 같이 작성한다.
action="login": 폼 데이터가/login이라는 URL로 전송된다method="pose": 데이터를 POST 방식으로 전송한다.name="user_id",name="user_pw": Servlet에서 이name값을 이용해 데이터를 꺼낸다.
4.2. 요청 처리 Servlet 작성
이제 login.html에서 보낸 쵸청을 처리할 LoginServlet을 작성한다.
@WebServlet("/login"): 이 서블릿이/login경로의 요청을 처리하도록 매핑한다.doPost():<form>의method가post이므로doPost()메소드에서 요청을 처리한다.
4.3. 실행 결과 확인
서버를 실행하고 login.html에 접속하여 아이디와 비밀번호를 입력한 후 '로그인' 버튼을 클릭하면, LoginServlet이 이를 받아 처리한 결과가 화면에 출력된다.
5. MVC Model1 Architecture
지금까지 우리는 HTML로 화면을 만들고, Servlet으로 로직을 처리하는 역할을 분리했다. 하지만 자바 코드 안에서 println()으로 복잡한 HTML 구조를 만드는 것은 매우 번거롭고 가독성이 떨어지기 때문에, 초창기 웹 개발에서는 이보다 더 단순한 구조를 사용했는데, 바로 MVC Model 1 아키텍처이다.
Model 1 구조에서는 JSP 페이지가 클라이언트의 요청을 직접 받고, 비즈니스 로직 처리(Controller 역할)와 결과 화면 생성(View 역할)을 모두 담당한다. 데이터베이스와의 연동이 필요할 경우, JSP는 자바빈(JavaBean)이나 DAO(Data Access Object)와 같은 모델(Model) 객체를 사용한다.
5.1. Model 1의 장점과 단점
- 장점: 구조가 단순하여 개발 속도가 빠르고 배우기 쉽다. 소규모 프로젝트나 간단한 기능 구현에 적합하다.
- 단점: JSP 페이지 하나에 프레젠테이션 로직(HTML/CSS/JS)과 비즈니스 로직(Java 코드)이 뒤섞이게 된다. 이로 인해 프로젝트의 규모가 커질수록 코드가 복잡해져 가독성이 떨어지고, 유지보수와 재사용이 매우 어려워진다. 디자이너와 개발자의 작업 영역이 명확히 분리되지 않아 협업에도 어려움이 따른다. 흔히 말하는 '스파게티 코드'가 되기 쉽다.
5.2. JSP로 퀴즈 페이지 만들기 (Model 1)
Model 1 구조를 이해하기 위해, 퀴즈를 보여주고, 정답을 입력받은 뒤, 오답인지를 판별하여 보여주는 페이지를 JSP만으로 작성해 본다.
5.2.1. response.jsp 작성
5.2.2. responseOk.jsp 작성
이 jsp 페이지는 response.jsp가 보낸 POST 요청을 받아 처리하는 페이지 이다. answer 파라미터를 직접 받아 오답 여부를 판별한 뒤, pass.jsp 또는 fail.jsp로 보낸다.
5.2.3. pass/fail.jsp 작성
5.2.4. 결과
responseOk.jsp를 보면, HTML 코드 중간에 <% %> 스크립틀릿을 사용하여 자바 코드가 삽입되어 있는 것을 볼 수 있다. 이처럼 요청 처리, 로직 수행, 화면 출력이 한 파일에 모두 섞여 있는 것이 바로 MVC Model 1 구조의 전형적인 모습이다.
6. 결론
이번 2편에서는 클라이언트의 요청을 처리하는 GET/POST 방식의 차이점부터 시작하여, HttpServletRequest와 HttpServletResponse 객체를 이용해 데이터를 주고받는 구체적인 방법을 실습을 통해 알아보았다. 이를 통해 웹 애플리케이션의 기본적인 데이터 흐름을 이해할 수 있었다.
또한, 초기 웹 개발 방식인 MVC Model 1 아키텍처에 대해 학습했다. JSP가 컨트롤러와 뷰의 역할을 모두 담당하는 Model 1은 간단한 애플리케이션을 빠르게 개발할 수 있다는 장점이 있지만, 로직과 화면이 뒤섞여 애플리케이션이 복잡해질수록 유지보수가 어려워진다는 명확한 한계를 가지고 있다.
이러한 Model 1의 한계를 극복하기 위해 등장한 것이 바로 역할을 명확하게 분리하는 MVC Model 2 아키텍처이다. 다음 글에서는 Model 1의 문제점을 해결하고 보다 체계적이고 확장 가능한 애플리케이션을 만들기 위한 MVC Model 2 아키텍처와, 이를 효율적으로 구현하기 위한 프론트 컨트롤러(Front Controller) 패턴에 대해 다루어 볼 것이다.