💡 Controller VS WebServlet
✅ WebServlet
클라이언트 요청을 처리하고, 요청에 대한 결과를 다시 클라이언트에게 전송하는 역할을 하는 자바 프로그램
- @Controller와 @RequestMapping이 합쳐진 것이다.
- WebServlet은 @WebServlet 어노테이션을 통해 클래스 단위로만 url 지정이 가능하다.
- 컨트롤러의 옛날 스타일로, Request, Response 객체를 다루는 기능이 다소 자동화되어 있지 않다.
- HttpServlet을 상속받아, doGet 혹은 doPost 함수를 오버라이딩해서 사용해야 한다.
📌 GET 요청
@WebServlet("/hello-servlet-rest-get")
public class HelloServletRestGet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Hello hello = new Hello();
hello.setName("shin");
hello.setEmail("shin@naver.cm");
hello.setPassword("1234");
// 직렬화 : 자바 객체 -> json
// 객체를 데이터 스트림으로 만들어, 스트림에 객체를 출력
ObjectMapper objectMapper = new ObjectMapper();
String json_hello = objectMapper.writeValueAsString(hello);
// 응답 header
resp.setContentType("application/json");
resp.setCharacterEncoding("UTF-8");
// 응답 body
PrintWriter out = resp.getWriter();
out.print(json_hello);
//버퍼를 통해 조립이 이루어지므로, 버퍼를 비우는 과정.
out.flush();
}
}
- urlPatterns(/hello-servlet-rest-get)의 URL이 호출되면 서블릿 코드가 실행
- HTTP 요청/응답 정보를 쉽게 사용할 수 있는 HttpServletRequest와 HttpServletResponse 객체 생성
- request객체에서는 요청값을 쉽게 꺼내고,
- response객체에서는 응답값에 필요한 값만 세팅해주면 http스펙에 맞게 서블릿이 간편히 처리
📌 POST 요청
@WebServlet("/hello-servlet-rest-post")
public class HelloServletRestPost extends HttpServlet{
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// BufferedReader br = req.getReader();
// StringBuilder sb = new StringBuilder();
//
// // sb에 body 데이터 전부 가져오기
// String line = null;
// while((line = br.readLine()) != null) {
// sb.append(line);
// }
// 역직렬화 : json -> 자바 객체
// 스트림에서 String을 읽어 와 객체로 만듬
if(req.getContentType() == "application/json"){
ObjectMapper mapper = new ObjectMapper();
//Hello hello = mapper.readValue(sb.toString(), Hello.class);
Hello hello = mapper.readValue(req.getReader(), Hello.class);
System.out.println(hello);
}
// 응답 header
resp.setContentType("text/plain");
resp.setCharacterEncoding("UTF-8");
// 응답 body
PrintWriter out = resp.getWriter();
out.print("ok");
out.flush();
}
}
요청 값을 꺼내거나, 응답 값을 정해주려면 HttpServletRequest 객체와 HttpServletResponse 객체가 인자로 필요하다.
서블릿으로 구현하게 되면 request와 response처리를 위해 매번 위의 코드를 작성해주어야 하는데,
다른 메소드를 작성하는 경우에도 똑같은 코드들을 중복으로 작성해서 request와 response를 처리해야하는 불편함이 있다.
또한, 요청 정보에서 message body를 파싱하거나, 응답 header 및 body 정보를 조립하는 과정도 굉장히 번거롭다.
이에 서블릿 기술을 근간으로 두고, 내부적으로 서블릿 기능을 처리하면서 서블릿의 단점을 극복한 컨트롤러가 등장했다.
개발자는 단순히 @Controller 어노테이션을 사용함으로써, 복잡한 요청 및 응답 처리 과정을 스프링에 위임한다.
✅ Controller
- @Controller 어노테이션을 사용하며, 내부적으로 서블릿 기능을 사용하여 사용자 요청을 더 간편하게 처리한다.
- HTTP Request, Response 처리를 위해 매번 작성해줘야 했던 중복 코드들을 생략 가능하다.
- 클래스 단위(@RequestMapping) 뿐만아니라, 메서드 단위로(@GetMapping, @PostMapping)도 url 지정 가능하다.
- 현대에 많이 쓰이는 기술
📌 GET 요청
@Controller
@RequestMapping("hello")
public class HelloController {
@GetMapping("json")
@ResponseBody
public Hello helloJson() {
Hello hello = new Hello();
hello.setName("kamill");
hello.setEmail("ka@naver.com");
hello.setPassword("1234");
System.out.println(hello);
return hello;
}
}
- HTTP response를 @ResponseBody로 String 타입의 data를 응답 메시지로 처리
- 만약 json 객체를 리턴한다면 스프링이 알아서 json으로 변환해주는 과정, contentType을 설정하는 과정, print, flush 등의 여러 중복되는 과정들을 대신한다
📌 POST 요청
@Controller
@RequestMapping("hello")
public class HelloController {
@PostMapping("form-post-handle1")
@ResponseBody
public String formPostHandle1(@RequestParam(value = "name") String name,
@RequestParam(value = "email") String email,
@RequestParam(value = "password") String password) {
System.out.println("name = " + name);
System.out.println("email = " + email);
System.out.println("password = " + password);
return "정상처리";
}
}
- HTTP request를 @RequestParam이 처리
컨트롤러를 사용하면 HTTP Request, Response 처리를 위해
매번 작성해줘야 했던 중복 코드들을 생략 가능하다는 게 무슨 말일까?
✔️ Servlet
Servlet을 사용해서 로그인과 회원가입 기능을 만들면 아래와 같은 코드로 구현할 것이다.
이때, 각 기능마다 .java 파일이 있어야 하고, 파일 안에서 doGet, doPost, request, response 코드가 계속 중복된다.
@WebServlet(urlPatterns = "/user/login")
public class loginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// ...
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
// ...
}
}
@WebServlet(urlPatterns = "/user/signup")
public class UserSignUpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
// ...
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) {
// ...
}
}
✔️ Controller
반면, Controller를 이용해 로그인과 회원가입 기능을 만들면 아래와 같은 코드로 구현할 것이다.
하나의 java 파일 안에서 url로 각 기능들을 매핑이 가능해 코드 중복이 현저하게 줄어들고,
다양한 어노테이션들을 통해 내부적으로 자동화 처리된 기능들을 간편하게 가져다 쓸 수 있다!
@Controller
public class UserController {
@GetMapping("/user/login")
public String login() {
// ...
}
@GetMapping("/user/signup")
public String signup() {
// ...
}
@PostMapping("/user/signup")
public String registerUser(MemberDto memberDto) {
// ...
}
}
'Back-End 공부 > Spring' 카테고리의 다른 글
생성자 객체 생성 방식의 단점을 극복한 builder 패턴 (1) | 2024.01.23 |
---|---|
[Web] WebServer와 WAS 차이 쉽게 이해하기 (0) | 2024.01.20 |
스프링 에러메시지 공통소스화 (0) | 2024.01.18 |
스프링 RestFul - 기본 CRUD 만들기 프로젝트 (0) | 2024.01.18 |
스프링 HTML 화면없이 PostMan으로 테스트하기 (0) | 2024.01.18 |