[스프링부트 #1] 서블릿 기반 웹 요청/응답 흐름 완전 정복
버퍼 코드 구현, Content-Type, MIME 정리, 서블릿 기반 웹 요청 및 응답 실습을 진행하였고 그것들을 정리하였습니다.
Aug 01, 2025
![[스프링부트 #1] 서블릿 기반 웹 요청/응답 흐름 완전 정복](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog-custom%3Ftitle%3D%255B%25EC%258A%25A4%25ED%2594%2584%25EB%25A7%2581%25EB%25B6%2580%25ED%258A%25B8%2B%25231%255D%2B%25EC%2584%259C%25EB%25B8%2594%25EB%25A6%25BF%2B%25EA%25B8%25B0%25EB%25B0%2598%2B%25EC%259B%25B9%2B%25EC%259A%2594%25EC%25B2%25AD%252F%25EC%259D%2591%25EB%258B%25B5%2B%25ED%259D%2590%25EB%25A6%2584%2B%25EC%2599%2584%25EC%25A0%2584%2B%25EC%25A0%2595%25EB%25B3%25B5%26tag%3DTemplate%2B1%26description%3D%26template%3D3%26backgroundImage%3Dhttps%253A%252F%252Fsource.inblog.dev%252Fog_image%252Fdefault.png%26bgStartColor%3D%252323ec86%26bgEndColor%3D%252323ec86%26textColor%3D%2523000000%26tagColor%3D%2523000000%26descriptionColor%3D%2523000000%26logoUrl%3D%26blogTitle%3DGyeongwon%2527s%2Bblog&w=2048&q=75)
1. 버퍼 코드 구현, readLine() 메서드
버퍼를 쓰는 이유
HttpServletRequest.getReader()
를 통해 클라이언트의 body 데이터를 읽어올 수 있다.
BufferedReader
는 한줄씩 읽기 위해 사용 →readLine
호출로 문자열 한 줄을 가져옴
BufferedReader br = request.getReader();
String data;
while ((data = br.readLine()) != null) {
System.out.println("read buffer data: " + data);
}
POST 방식일 때만 body가 있음
readLine()
한 번 읽으면, 다시는 못 읽음 (스트림 소모됨)2. request
, 그리고 주요 메서드
HttpServletRequest
역할
: 클라이언트가 보낸 요청(Request)에 대한 모든 정보를 담고 있음
자주 쓰는 메서드
메서드 | 설명 |
getParameter(String) | form-data 또는 query string에서 키 값 읽기 |
getReader() | body를 직접 읽을 수 있는 Reader 반환 |
getRequestURI() | 요청 URI 경로 ( /hello.do ) |
getHeader(String) | 요청 헤더 값 읽기 ( User-Agent , Content-Type 등) |
getMethod() | HTTP 메서드 타입 (GET, POST 등) |
3. response
, 그리고 주요 메서드
HttpServletResponse
역할
: 서버가 클라이언트에게 보내는 응답(Response)을 구성하는 객체
자주 쓰는 메서드
메서드 | 설명 |
setContentType(String) | MIME 타입 설정 (text/html, application/json 등) |
getWriter() | 텍스트 응답을 위한 출력 스트림 (PrintWriter) |
getOutputStream() | 바이트 스트림 응답용 (예: 이미지, 파일 등) |
예시 :
response.setContentType("text/html;charset=utf-8");
PrintWriter out = response.getWriter();
out.println("<h1>");
out.println("good");
out.println("</h1>");
out.flush();
text/html
: 응답 내용이 HTML이라는 의미charset=utf-8
: UTF-8 문자 인코딩을 사용하겠다는 뜻, 이걸 안 하면 한글 깨짐 가능성 있음PrintWriter
는 문자 기반 스트림 (바이너리 X), 이 스트림을 통해 HTML, 텍스트 등을 클라이언트로 전송함브라우저 화면에는 굵은 큰 글씨로 "good"이 표시됨
out.flush()
: 버퍼에 쌓여 있는 데이터를 강제로 클라이언트로 전송4. Content-Type, MIME 정리
Content-Type 이란 ?
클라이언트가 보내는 데이터 혹은 서버가 보내는 데이터의 형식을 명시하는 HTTP 헤더
주요 MIME 타입
Content-Type | 설명 |
text/html | HTML 응답 |
application/json | JSON 형식 응답/요청 |
application/x-www-form-urlencoded | 기본 form submit 시 사용되는 타입 (key=value&key2=value2 형태) |
multipart/form-data | 파일 업로드 등 바이너리 포함된 폼 전송 |
5. Body
Body는 언제 있는가 ?
- GET 요청은 보통 body가 없다.
- POST, PUT, PATCH 등에선 주로 body에 데이터를 담는다.
- body는 텍스트든 JSON이든 다 스트림 형태로 들어오므로
request.getReader()
로 읽어야 한다.
{
"username": "doythan",
"password": "1234"
}
6. 실습 코드 예제
@WebServlet("*.do") // *.do로 끝나는 모든 요청을 이 서블릿이 처리함
public class HelloServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
// GET 요청 시 호출됨
System.out.println("doGet called");
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
// POST 요청 시 호출됨
System.out.println("doPost called");
// 요청 본문을 BufferedReader로 읽음 (주로 JSON, form-data 읽을 때)
BufferedReader br = request.getReader();
String data;
// 본문을 한 줄씩 읽으며 출력
while ((data = br.readLine()) != null) {
System.out.println("read buffer data: " + data);
}
// 요청 URI 출력 (/example.do 등)
String uri = request.getRequestURI();
// 브라우저 종류나 디바이스 정보 (User-Agent 헤더)
String userAgent = request.getHeader("User-Agent");
// 요청의 Content-Type (예: application/json)
String contentType = request.getContentType();
// 요청 메서드(GET, POST 등)
String method = request.getMethod();
System.out.println("uri: " + uri);
System.out.println("userAgent: " + userAgent);
System.out.println("contentType: " + contentType);
System.out.printf("method: %s\n", method);
// 응답 헤더 설정: HTML 문서, UTF-8 인코딩
response.setContentType("text/html;charset=utf-8");
// 응답 출력 스트림 생성
PrintWriter out = response.getWriter();
out.println("<h1>");
out.println("good"); // 브라우저에 <h1>good</h1> 출력됨
out.println("</h1>");
out.flush(); // 버퍼 비우고 클라이언트에 전송
}
}
// BufferedReader br = request.getReader();
// String data;
//
// while ((data = br.readLine()) != null) {
// System.out.println("read buffer data: " + data);
// }
String username = request.getParameter("username");
System.out.println("username: " + username);
서블릿 요청은 1회용 스트림
request.getReader()
→ 요청 본문을 문자로 읽는 InputStream, 한 번 읽으면 내부 스트림이 소모됨 (더 이상 못 읽음)getParameter()
도 내부적으로 스트림을 읽어서 파싱함따라서 주석 해제 하면 username에는 null
7. 용어 정리
스트림
- 데이터의 흐름을 추상화한 것
- 파일, 네트워크, 키보드 입력 등에서 데이터를 "한 줄"처럼 흐르게 다룸
- 방향성 있음:
InputStream
(받기, 데이터 읽기) vsOutputStream
(보내기, 데이터 쓰기)
- 문자 스트림: 텍스트용 (
Writer
), 바이너리 스트림: 파일/이미지용 (OutputStream
)
바이너리 (Binary)
- 0과 1로 이루어진 데이터
- 이미지, 동영상, 압축파일 등은 바이너리 형태로 전송
- 텍스트도 결국 바이너리지만, 사람이 보기 쉽게 인코딩된 것일 뿐
flush()
- 스트림에 쌓인 데이터(버퍼)를 강제로 밀어내는 것
- 자바는 출력할 때 바로 안 보내고 버퍼에 잠깐 저장함
flush()
는 이걸 클라이언트나 파일로 즉시 전송
Share article