Spring) Component Scan 단계별 실습하기(feat. Postman)

TigerFriend·2023년 10월 7일
0

웹 개발

목록 보기
4/7
post-thumbnail

⚙️ 개발환경 : Java 11, JDK 11, SpringBoot 2.6.17, Mustache, IntelliJ, Postman

⚙️ 필요 배경 지식 : Dispather-servlet(디스패처 서블릿), Annotation, Component Scan, MVC패턴

⚙️ 배울 내용 키워드 : @Controller, @RequestMapping, @ResponseBody

⚙️ 개요 : Component Scan을 사용하여 Http메소드 실행하기.


1. Component Scan

Component Scan시, 스프링의 디스패처 서블릿은 @Component어노테이션이 붙은 클래스를 찾아 메모리에 올려준다. (@Component가 붙어있는 메타 어노테이션은 @Service, @Repository, @Controller 등이 있다.)

이를 확인해보자.

** 주의할점은 Component Scan은 사용자가 직접 만든 도메인 패키지 내부만 스캔하기 때문에 basic_controller 내부에 Controller패키지를 만들어야 한다.

@Controller //컴퍼넌트 스캔(디스패처 서블릿이 찾아준다.)
public class HttpMethodController {
    public HttpMethodController() {
        System.out.println("컴퍼넌트 스캔됨");
    }

성공적으로 해당 클래스가 스프링에 의해 생성됨을 확인할 수 있다. 이제 @GetMapping으로 디스패처 서블릿에게 Method레벨의 어노테이션을 등록한다.

이때 @Controller가 붙은 클래스내부 메소드에서 return은 기본적으로 View를 찾는다. 그렇기 때문에 데이터값(메세지 등)을 return 하고 싶다면 @ResponseBody 어노테이션을 메소드 앞에 붙이면 된다.


2. @GetMapping

Http 메소드를 통해 데이터를 읽고 써보자. 먼저 Get이다.

@Controller //컴퍼넌트 스캔(디스패처 서블릿이 찾아준다.)
public class HttpMethodController {
    public HttpMethodController() {
        System.out.println("컴퍼넌트 스캔됨");
    }
    
    @GetMapping("/req/get")
    public void methodGet(){
        System.out.println("methodGet() 호출됨");
    }
}

현재 localhost:9000을 쓰고 있기 때문에 "localhost:9000/req/get"을 입력하면 로그에 "methodGet() 호출됨"이 남게 된다.


3. Bufferd Write 직접 접근하기

디스패처 서블릿은 클라이언트로부터 요구사항을 전달받아 저장하는 request객체와 응답을 보내기 위한 response객체를 가지고 있다.

여기에 직접 접근하여 해당 값을 사용할 수 있는데, 매개변수에서 각각을 입력함으로써 메서드 내에서 다룰 수 있다.

// 디스패처 서블릿이 들고 있는 request와 response를 전달받고 싶을 때
    @GetMapping("/req/get/v2")
    public void methodGetV2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        System.out.println("methodGetV2() 호출됨");

        PrintWriter pw = response.getWriter(); //BW버퍼에 직접 입력함.
        pw.println("<h1>Get</h1>"); //Content-Type은 text/html, Status Code는 200(정상작동완료)
    }

웹페이지->f12를 통해 확인할 수 있는 개발자 창에서 Request Method : GET과 Status Code : 200을 확인할 수 있다.


4. RequestDispatcher

만약 메소드의 return값이 void가 아닌 String값이라면 어떨까?
-> 스프링은 기본적으로 RequestMapping 객체의 return을 Viewname으로 인식한다. 즉, templates폴더(default)에서 "hello.mustache"파일을 찾아서 클라이언트에 전달한다.

@Controller
public class HttpMethodController {

	@GetMapping("/req/get/v3")
	public String methodGetV3() {
    	return "hello"; //templates안에 hello.mustache를 찾으러 간다. // 그리고 ViewResolver가 발동됨.
	}
    
}

웹페이지 정보를 확인해보면, v3이름의 요청의 상태코드는 200인 것을 확인할 수 있다. requestdispatcher를 사용하면 클라이언트(외부)의 한번의 요청으로 처리할 수 있다. 이를 다음 Redirection과 비교해보자.


5. sendRedirect

public class HttpMethodController {

	@ResponseBody //나는 return시 ViewResolver말고 문자 그대로 표시하고 싶다!
    @GetMapping("/req/get/v4")
    public String methodGetV4() {
        return "<h1>Get</h1>"; //return시 MessageConverter가 발동함.
    }
    
  	@GetMapping("/req/get/v5")
  	public void methodGetV5(HttpServletResponse response) throws IOException {
      	response.sendRedirect("/req/get/v4"); 
  	}
}

redirect로 전달하면 아래와 같이 302상태로 클라이언트에 보내고 다시 v4를 받아오는 것을 알 수 있다.

이유가 무엇일까??

stateless서버는 request를 저장하지 않기 때문에 httpHeader에 hello.mustache 정보를 전달한 후 hello.mustache를 view에 전달하는 과정을 거친다.

이 과정에서 총 2번의 외부 요청이 있게 되기 때문에 v5와 v4의 request가 표시된것이다.

반면, return string으로 view파일을 찾아서 화면에 표시하는 방식은 디스패처 서블릿이 requestdispatcher로 내부에서 바로 view로 전달했기 때문에 한번의 request기록이 남게 된다.

📌 sendRedirect vs requestDispatcher

: 리소스 관점에서 redirect는 request가 두번 만들어지기 때문에 requestdispatcher가 효율적이다.
: sendRedirect방식은 client가 바로 hello.mustache를 요청할 수 있기 때문에 외부에서 바로 접근할 수 있는 위험이 있다. (접근 통제가 안됨)


💾 Postman으로 HTTP 메서드 실행

RestAPI 규칙을 만족하는 Restful API를 만들기 위해선 Http메서드로 자료를 CRUD(Create-Read-Update-Delete) 할수 있어야 한다.

웹서버에서는 Http메서드 중 Get만 확인할 수 있다.
그래서 Postman를 통해 http메서드 호출을 확인해 보았다.

public class HttpMethodController {
    @GetMapping("/req/get")
    public void methodGet(){
        return "<h1>Get</h1>";
    }
    @ResponseBody
    @PostMapping("/req/post")
    public String methodPost(){
        return "<h1>Post</h1>";
    }
    @ResponseBody
    @PutMapping("/req/put")
    public String methodPut(){
        return "<h1>put</h1>";
    }
    @ResponseBody
    @DeleteMapping("/req/delete")
    public String methodDelete(){
        return "<h1>delete</h1>";
    }
}

그 중 Post를 예시로 보면 url을 통해 request를 보내면 "Post"를 확인할 수 있다.


정리

  1. Component Scan을 이용하여 등록한 객체는 FrontControll의 역할을 하는 스프링의 디스패처 서블릿이 생성한다.
  2. 객체를 등록한다는 것은 객체에게 생성 및 관리를 맡기는 것이고, 개발자가 생성하는 것이 아니라 프레임워크가 생성한다고 해서 이를 IoC(Inversion of Control)-제어의 역전이라 한다.
  3. 이후 필요할 때, 사용자가 생성(new)하지 않고 스프링이 생성한 객체를 사용한다. 이를 DI(Dependency Injection) - 의존성 주입이라 한다.
  4. 이렇게 스프링 프레임워크가 생명주기를 관리하는 객체를 "Bean"객체라고 한다.
profile
TigerFriends

0개의 댓글