Request & Response
HttpServletRequest, HttpServletResponse는 각각 HTTP의 Request, Response를 추상화하기 위한 JEE 인터페이스다.
HTTP 프로토콜 이해
HTTP는 Stateless 프로토콜이다. 각 요청은 독립적이며 이전 요청을 기억하지 않는다.
HTTP 메시지 구조
- Start Line: 메서드, URL, 버전 정보 (POST /api/data HTTP/1.1)
- Headers: 메타데이터 (Content-Type, User-Agent, Cookie 등)
- Body: 실제 데이터 (POST, PUT 요청에서 주로 사용)
HttpServletRequest
주요 메서드
String getMethod(): HTTP 메서드 확인 (GET, POST 등)- 파라미터 조회:
String getParameter(String name): 단일 값String[] getParameterValues(String name): 체크박스 등 다중 값Enumeration<String> getParameterNames(): 모든 파라미터 이름
Request Parameter
<form>또는 queryString을 통해서 클라이언트가 전달한 값으로 언제나 문자열getParameterMap(): 모든 파라미터를 Map으로 받기
AddServlet.java
@WebServlet("/live/add")
public class AddServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
System.out.println("AddServlet doGet 메서드 호출됨");
// 파라미터 받기
String num1Str = request.getParameter("num1");
String num2Str = request.getParameter("num2");
int num1 = Integer.parseInt(num1Str);
int num2 = Integer.parseInt(num2Str);
int sum = num1 + num2;
// 파라미터 로깅
Map<String, String[]> params = request.getParameterMap();
params.forEach((key, values) -> {
for (String value : values) {
System.out.println("Key: " + key + ", Value: " + value);
}
});
response.setContentType("text/plain");
response.getWriter().write("Sum: " + sum);
}
}HTML Form
<!DOCTYPE html>
<html>
<body>
<form action="/live/add" method="get">
<input name="num1" id="num1Id"/> +
<input name="num2" id="num2Id"/> = ?
<button type="submit">조회</button>
</form>
</body>
</html>- form action은 server의 액션
- id는 client에서 사용
- 서버에서는 name을 사용
HttpServletResponse
주요 메서드
setStatus(): HTTP 상태 코드 설정setHeader(): 헤더 설정setContentType(): Content-Type 설정getWriter(): 응답 출력 스트림
HTTP 상태 코드
- 2xx: 성공
- 3xx: 리다이렉션
- 4xx: 클라이언트 에러
- 401: 인증 실패 (누구세요?)
- 403: 권한 없음
- 404: 요청한 리소스 없음
- 405: 허용되지 않는 메서드
- 5xx: 서버 에러
Content-Type과 Character Encoding
서버가 전송하는 데이터의 MIME 타입:
text/plain: 일반 텍스트로 형식이 없는 데이터text/html: HTML 문서application/json: JSON 형식의 데이터
데이터를 컴퓨터가 이해하고 처리할 수 있는 형태로 변환하는 방법:
- content type과 함께 charset까지 지정해줘야 한다
text/html; charset=UTF-8- 기본은 ISO-8859-1 (한국어 인코딩 불가)
HelloServlet.java
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// Content-Type과 인코딩 설정 (한글 깨짐 방지)
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<h1>안녕하세요!</h1>");
out.println("<p>한글이 정상적으로 출력됩니다.</p>");
}
}Servlet에서 할 일 정리
- 요청 파라미터 조회: 파라미터에 대한 Logging 및 validation 포함
- 요청에 대한 business logic 처리
- 필요 시 persistence logic 연동
- 응답 준비: content type 및 encoding 설정
- 응답을 위한 presentation logic 처리
HTTP 메서드 특성
HTTP 메서드 특성 표
| HTTP 메서드 | RFC | 요청에 Body가 있음 | 응답에 Body가 있음 | 안전 | 멱등(Idempotent) | 캐시 가능 |
|---|---|---|---|---|---|---|
| GET | RFC 9110 | 선택 사항 | 예 | 예 | 예 | 예 |
| POST | RFC 9110 | 예 | 예 | 아니요 | 아니요 | 아니요* |
| PUT | RFC 9110 | 예 | 예 | 아니요 | 예 | 아니요 |
| DELETE | RFC 9110 | 선택 사항 | 예 | 아니요 | 예 | 아니요 |
| CONNECT | RFC 9110 | 선택 사항 | 예 | 아니요 | 아니요 | 아니요 |
| OPTIONS | RFC 9110 | 선택 사항 | 예 | 예 | 예 | 아니요 |
| TRACE | RFC 9110 | 아니요 | 예 | 예 | 예 | 아니요 |
| PATCH | RFC 5789 | 예 | 예 | 아니요 | 아니요 | 아니요 |
| HEAD | RFC 9110 | 선택 사항 | 아니요 | 예 | 예 | 예 |
* 명시적인 Cache-Control, Expires 등 캐시 지시자가 있을 때에만 캐시 가능
멱등성 (Idempotent)
개념: 특정 연산을 동일한 파라미터로 여러 번 연산하더라도 그 결과는 동일하다.
HTTP 메서드별 멱등성 설명
- GET: 멱등 (조회만 하므로 여러 번 호출해도 결과 동일)
- POST: 비멱등 (매번 새로운 리소스 생성)
- PUT: 멱등 (동일한 리소스를 업데이트)
- DELETE: 멱등 (이미 삭제된 것을 다시 삭제해도 결과 동일)
안전성 (Safe)
개념: 서버의 상태를 변경하지 않는 읽기 전용 메서드
- 안전한 메서드: GET, HEAD, OPTIONS, TRACE
- 안전하지 않은 메서드: POST, PUT, DELETE, PATCH
실무 활용
- 재시도 로직 구현 시 멱등성 고려
- 중복 요청 방지를 위한 API 설계 시 필수 고려사항
- 캐시 가능한 메서드는 성능 최적화에 활용
정리
- Request를 통해 클라이언트의 데이터를 받고
- Response를 통해 결과를 전송한다
- 한글 처리를 위해 반드시 UTF-8 인코딩 설정
- 파라미터는 항상 문자열이므로 필요시 형변환
Last updated on