6장 Servlet 기초
WAS(Web Application Server)가 처음 등장했을 때 웹 브라우저의 요청을 스레드 방식으로 처리하는 기술이 Servlet이다. 모든 웹 프로그램은 아래에서 서술한 기능을 바탕으로 동작한다.
(1) Servlet의 세 가지 기본 기능
Client로부터 요청을 받아 비즈니스 로직을 처리하고 결과를 다시 클라이언트에게 돌려주는 과정
- Client로부터 요청을 받는다.
- DB 연동과 같은 비즈니스 로직 처리
- 처리된 결과를 Client에게 돌려준다.

ex. 로그인 과정
1. 사용자가 입력한 ID와 PW가 Server 쪽 Servlet으로 전송
Servlet은 메서드를 이용해 사용자가 전송한 ID와 PW를 받아 온다.
2. 사용자의 로그인 요청에 따라 DB와 연동해 사용자가 등록된 회원인지 확인
3. 그 결과에 따라서 다음 페이지로 가던지 ID/PW가 틀렸으니 다시 로그인하라는 오류메시지는 전송
(2) Servlet 응답과 요청 수행 API 기능
- 요청과 관련된 API : javax.servlet.http.HttpServletRequest 클래스
- 응답과 관련된 API: javax.servlet.http.HttpServletResponse 클래스
→ 요청이나 응답과 관련된 API는 모두 javax.servlet.http 패키지에 존재
- Client가 Servlet에 요청하면 먼저 Tomcat 컨테이너가 받음
- 사용자의 요청이나 응답에 관한 HttpServletRequst객체와 HttpServletResponse 객체를 만들고 Servlet의 doGet()/doPost() 메소드를 호출하면서 객체들을 전달
→ Tomcat이 사용자의 요청에 대한 정보를 모든 HttpServletRequest 객체의 속성으로 담아 메서드로 전달하므로 각 HttpServletRequst에서 제공하는 메서드들은 매개변수로 넘어온 객체들을 이용하여 사용자가 전송한 데이터를 받아 오거나 응답할 수 있는 것
HttpServletRequest 의 여러가지 메서드
반환형 | 메서드 이름 | 기능 |
boolean | authenticate(HttpServletResponse response) | 현재 요청한 사용자가 ServletContext 객체에 대한 인증을 하기 위한 컨테이너 로그인 메커니즘을 사용 |
String | changeSessionId() | 현재 요청과 연관된 현재 세션의 id를 변경하여 새 세션 id를 반환 |
String | getContextPath() | 요청한 컨텍스트를 가리키는 URI를 반환 |
Cookie[] | getCookies() | 클라이언트가 현재의 요청과 함께 보낸 쿠키 객체들에 대한 배열을 반환 |
String | getHeader(String name) | 특정 요청에 대한 헤더 정보를 문자열로 반환 |
Enumeration <String> | getHeaderNames() | 현재의 요청에 포함된 헤더의 name 속성을 enumeration으로 반환 |
String | getMethod() | 현재 요청이 GET, POST 또는 PUT 방식 중 어떤 HTTP 요청인지 반환 |
String | getRequestURI() | 요청한 URL의 컨텍스트 이름과 파일 경로까지 반환 |
String | getServletPath() | 요청한 URL에서 서블릿이나 JSP 이름 반환 |
HttpSession | getSession() | 현재의 요청과 연관된 세션을 반환합니다. 만약 세선이 없다면 새로 만들어 반환 |
HttpServletResponse 의 여러가지 메서드
반환형 | 메서드 이름 | 기능 |
void | addCookie(Cookie cookie) | 응답에 쿠키를 추가 |
void | addHeader(String name, String value) | name과 value를 헤더에 추가 |
String | encodeURL(String url) | 클라이언트가 쿠키를 지원하지 않을 때 세션 id를 포함한 특정 URL을 인코딩 |
Collection <String> | getHeaderNames() | 현재 응답의 헤더에 포함된 name을 얻어옴 |
void | sendRedirect(String location) | 클라이언트에게 redirect 응답을 보낸 후 특정 URL로 다시 요청 |
String | getPathInfo() | 클라이언트가 요청 시 보낸 URL과 관련된 추가 경로 정보를 반환 |
(3) <form> 태그로 Servlet에 요청하는 과정
: Servlet과 JSP은 HTML, CSS, JavaScript 기능에 자신의 기능을 추가하여 서로 연동하여 동작한다.
사용자의 요청은 HTML의 <form> 태그나 JavaScript로 부터 전송 받아 처리
클라이언트 웹 브라우저에서 Servlet에 요청하는 방법
- 웹 브라우저에서 여러 가지 입력 서식을 이용해 전송을 클릭하면 사용자가 입력한 데이터가 Servlet으로 전송
- Servlet은 여러 가지 메서드를 이용해서 전송된 데이터를 받음

<form> 태그의 여러 가지 속성
속성 | 기능 |
name | <form> 태그의 이름을 지정 여러 개의 form이 존재할 경우 구분하는 역할 JavaScript에서 <form>태그에 접근할 때 많이 사용 |
method | <form> 태그 안에서 데이터를 전송할 때 전송 방법 지정 GET/POST로 (아무것도 지정하지 않으면 GET) |
action | <form> 태그에서 데이터를 전송할 Servlet이나 JSP를 지정 Servlet으로 전송할 떄는 매핑 이름 사용 |
encType | <form> 태그에서 전송할 데이터의 encoding 타입을 지정 파일을 업로드할 때는 multipart/form-data 지정 |
<form> 태그 데이터가 전송되는 과정
사용자의 로그인 창의 HTML 태그의 구조는 아래와 같다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form name="frmLogin" method="get" action="login" enctype="UTF-8">
ID:<input type="text" name="user_id"><br>
PW:<input type="password" name="user_pw"><br>
<input type="submit" value="로그인"><input type="reset" value="다시 입력">
</form>
</body>
</html>
- 사용자가 ID,PW를 입력한 후 로그인을 클릭
- <form> 태그의 action 속성은 데이터를 전송할 Servlet이나 JSP의 이름을 지정
- 지정된 이름이 login인 Servlet으로 ID와 비밀번호 전송
- 실제 데이터틑 <input> 태그의 name 속성 값과 쌍으로 전송
- Servlet에서 name 속성 값으로 같이 전송된 입력 데이터를 받아 옴

<form> 태그로 전송된 데이터를 받아 오는 메서드
메서드 | 기능 |
String getParameter(String name) | name의 값을 알고 있을 때 그리고 name에 대한 전송된 값을 받아올 떄 사용 |
String[] getParameterValues(String name) | 같은 name에 대해 여러 개의 값을 얻을 때 사용 |
Enumeration getParameterNames() | name 값을 모를 때 사용 |
여러 개의 값을 전송할 때의 요청 처리
: 한 개씩 전송된 값은 getParameter() 이용, 하나의 name으로 여러 값을 전송하는 경우 getParameterValues()를 이용해 배열 형태로 반환
input.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<title>여러 가지 input 타입 표시창</title>
</head>
<body>
<form name="frmInput" method="get" action="input">
id: <input type="text" name="user_id"><br>
pw: <input type="password" name="user_pw"><br>
<input type="checkbox" name="subject" value="java" checked> 자바
<input type="checkbox" name="subject" value="C언어"> C언어
<input type="checkbox" name="subject" value="JSP"> JSP
<input type="checkbox" name="subject" value="안드로이드"> 안드로이드
<br><br>
<input type="submit" value="전송">
<input type="reset" value="초기화">
</form>
</body>
</html>
InputSevlet.java
package sec01.ex01;
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("/input")
public class InputServlet extends HttpServlet {
public void init() throws SecurityException{
System.out.println("init 메서드 호출");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
String user_id = request.getParameter("user_id");
String user_pw = request.getParameter("user_pw");
System.out.println("ID: "+ user_id);
System.out.println("PW: "+ user_pw);
String[] subject = request.getParameterValues("subject");
// 하나의 name 으로 여러 값을 전송하는 경우 getParameterValues()를 이용해 배열 형태 반환
for(String str : subject){
System.out.println("선택한 과목:"+ str);
}
}
public void destroy(){
System.out.println("destroy 메서드 호출");
}
}


getParameterNames() 메서드를 이용한 요청처리
: servlet에서 getParameter() 메서드를 이용해서 많은 정보를 처리하면 각 매개 변수를 모두 알아야한다. 전송할 데이터가 많아 name의 값을 모두 기억하기 어려울 때 getParameterNames() 메서드를 이용하면 편리하다.
InputSevlet2.java
package sec01.ex01;
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.util.Enumeration;
@WebServlet("/input2")
public class InputServlet2 extends HttpServlet {
public void init() throws ServletException{
System.out.println("init 메서드 호출");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
request.setCharacterEncoding("utf-8");
Enumeration enu = request.getParameterNames();
//전송 온 name 속성들만 Enumeration 타입으로 받아온다.
while (enu.hasMoreElements()){
// 각 name을 하나씩 가져와 대응해서 전송되어 온 값 출력
String name = (String) enu.nextElement();
String[] values = request.getParameterValues(name);
for(String value : values){
System.out.println("name="+ name+",value="+value);
}
}
}
public void destroy(){
System.out.println("destroy 메서드 호출");
}
}
getParameterNames()를 이용해 전송된 name과 값이 모두 출력된 것을 확인 할 수 있다.

(4) Servlet의 응답 처리 방법
-응답 처리-
doGet()/doPost() 매서드 안에서 처리
javax.servlet.http.HttpServletResponse 객체 이용
setContentType()을 이용해 클라이언트에게 전송할 데이터 종류(MIME-TYPE)를 지정
-응답 과정-
Client(웹 브라우저)와 Servlet의 통신은 자바 I/O의 스트림 이용
1. MIME-TYPE(마임타입)
서버(Servlet)에서 자바 I/O의 스트림 클래스를 이용하여 웹 브라우저로 데이터를 전송할 때는 MIME-TYPE을 설정해서 전송할 데이터의 종류를 지정
ex.
HTML로 전송: text/html
일반 텍스트로 전송: text/plain
XML 데이터로 전송: application/xml
이외에도 톰캣 컨테이너에서 자주 사용하는 데이터 종류를 MIME-TYPE으로 지정해 놓았으므로 서블릿에서 종류를 지정해서 사용하면 된다. 새로운 종류의 데이터 지정시 web.xml에 추가하면 된다.
2. HttpServletResponse를 이용한 Servlet 응답 과정
setContentType()을 이용해 MIME-TYPE을 지정 → 데이터를 출력한 PrintWriter 객체를 생성 → 출력 데이터를 HTML 형식으로 만듦 → PrintWriter의 print()나 println()을 이용해 데이터를 출력
package sec01.ex01;
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("/login2")
public class LoginServlet2 extends HttpServlet {
public void init() throws ServletException{
System.out.println("init 메서드 호출");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); // 웹 브라우저에서 전송된 데이터의 인코딩을 설정
response.setContentType("text/html;charset=utf-8"); //setContentType()을 이용해 응답할 데이터의 종류가 HTML임을 설정
PrintWriter out = response.getWriter();
String id = request.getParameter("user_id");
String pw = request.getParameter("user_pw");
//브라우저로 출력할 데이터를 문자열로 연결해서 html 태그로 만듦
String data = "<html>";
data += "<body>";
data += "아이디 : " + id;
data += "<br>";
data += "패스워드 :" + pw;
data += "</body>";
data += "</html>";
out.println(data); // PrintWriter의 print()를 이용해 HTML 태그 문자열을 웹 브라우저로 출력
}
public void destroy(){
System.out.println("destroy 메서드 호출");
}
}


위와 같이 서블릿이 ID와 비밀번호를 전달받아 브라우저로 출력하는 것을 볼 수 있다.
(5) 웹 브라우저에서 Servlet으로 데이터 전송
GET/POST 전송 방식
GET 방식 | POST 방식 |
servlet에 데이터를 전송할 때는 데이터가 URL 뒤에 name=value 형태로 전송 여러 개의 데이터를 전송할 때는 '&'로 구분해서 전송 보안이 취약 전송할 수 있는 데이터는 최대 255자 기존 전송 방식이고 사용이 쉽다 웹 브라우저에 직접 입력해서 전송할 수도 있다 servlet에서 doGet() 을 이용해 데이터를 처리 |
Servlet에서 데이터를 전송할때 TCP/IP 프로토콜 데이터의 body 영역에 숨겨진 채 전송 보안에 유리 전송 데이터 용량 무제한 전송시 Servlet에서는 또 다시 가져오는 작업을 해야 하므로 처리 속도가 GET 방식보다 느림 Servlet에서 doPost()를 이용해 데이터 처리 |
Servlet에서는 웹 브라우저에서 전송되는 방식에 따라 doGet()이나 doPost() 메서드로 대응해서 처리
전송방식과 다른 메서드를 사용하면 브라우저에서 아래와 같은 오류가 발생한다.

이 두 방식으로 전송된 데이터는 반드시 HttpServlet에서 오버라이딩된 doGet() 메서드나 doPost()를 사용해야한다.
메서드가 서블릿에 존재하지 않거나 사용자가 임의로 만든 메서드를 사용하면 오류 발생
GET과 POST 방식 요청 동시에 처리
login4.html
(1) method="get"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form name="frmLogin" method="get" action="login4" enctype="UTF-8">
ID:<input type="text" name="user_id"><br>
PW:<input type="password" name="user_pw"><br>
<input type="submit" value="로그인"><input type="reset" value="다시 입력">
</form>
</body>
</html>
(2) method="post"
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<form name="frmLogin" method="post" action="login4" enctype="UTF-8">
ID:<input type="text" name="user_id"><br>
PW:<input type="password" name="user_pw"><br>
<input type="submit" value="로그인"><input type="reset" value="다시 입력">
</form>
</body>
</html>
loginServlet4.java
package sec03.ex01;
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("/login4")
public class LoginServlet4 extends HttpServlet {
public void init() throws ServletException {
System.out.println("init 메서드 호출");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
System.out.println("doGet 메서드 호출");
doHandle(request, response); // GET 방식으로 요청시 다시 doHandle()를 호출
}
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
System.out.println("doPost 메서드 호출");
doHandle(request, response); // POST 방식으로 요청시 다시 doHandle()를 호출
}
private void doHandle(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
// 모든 방식으로 처리 가능
request.setCharacterEncoding("utf-8");
String user_id = request.getParameter("user_id");
System.out.println("doHandle 메서드 호출");
String user_pw = request.getParameter("user_pw");
System.out.println("ID: "+ user_id);
System.out.println("PW: "+ user_pw);
}
public void destroy(){
System.out.println("destroy 메서드 호출");
}
}


(6) JavaScript에서 Servlet 요청
전송 데이터에 대한 유효성 검사를 구현하기 위해서 자바스크립로 서블릿 요청
login5.html
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<script type="text/javascript">
function fn_validate(){
var frmLogin = document.frmLogin;
var user_id = frmLogin.user_id.value;
var user_pw = frmLogin.user_pw.value;
if((user_id.length == 0 || user_id =="")|| (user_pw.length == 0 || user_pw =="")){
alert("아이디랑 비밀번호 필수");
}else{
frmLogin.method="post"; // <form> 태그의 전송 방식을 post로 설정
frmLogin.action ="login5"; // action 속성을 서블릿 매핑 이름인 login5로 설정
frmLogin.submit(); // 자바스크립트에서 서블릿으로 전송
}
}
</script>
<title>로그인창</title>
</head>
<body>
<form name="frmLogin" method="post" action="login" enctype="UTF-8">
ID: <input type="text" name="user_id"><br>
PW: <input type="text" name="user_pw"><br>
<input type="button" onClick="fn_validate()" value="로그인">
<input type="reset" value="다시 입력">
<input type="hidden" name="user_address" value="서울시 성북구"/>
</form>
</body>
</html>
LoginServlet5.java
package sec03.ex01;
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("/login5")
public class LoginServlet5 extends HttpServlet {
public void init() throws ServletException {
System.out.println("init 메서드 호출");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8"); // 웹 브라우저에서 전송된 데이터의 인코딩을 설정
response.setContentType("text/html;charset=utf-8"); //setContentType()을 이용해 응답할 데이터의 종류가 HTML임을 설정
PrintWriter out = response.getWriter();
String id = request.getParameter("user_id");
String pw = request.getParameter("user_pw");
String address = request.getParameter("user_address");
System.out.println("id: "+id);
System.out.println("pw: "+ pw);
//브라우저로 출력할 데이터를 문자열로 연결해서 html 태그로 만듦
String data = "<html>";
data += "<body>";
data += "아이디 : " + id;
data += "<br>";
data += "패스워드 :" + pw;
data += "<br>";
data += "주소 :" + address;
data += "</body>";
data += "</html>";
out.println(data); // PrintWriter의 print()를 이용해 HTML 태그 문자열을 웹 브라우저로 출력
}
public void destroy(){
System.out.println("destroy 메서드 호출");
}
}


(참고: 자바 웹을 다루는 기술)
'Back-end > JSP' 카테고리의 다른 글
Servlet 비즈니스 로직 처리 (0) | 2023.01.24 |
---|---|
Servlet 이란? (0) | 2023.01.20 |
웹 애플리케이션 (0) | 2023.01.19 |
프로그램의 발전 과정, 웹 프로그래밍과 JSP (0) | 2023.01.19 |