Controller 와 HTTP Request 메시지

SaGo_MunGcci·2022년 7월 28일
0

스프링

목록 보기
4/31

Definition Access

  • 스프링은 기본적으로 서버를 통합 개발해주는 프레임워크이다.
  • 클라이언트에서 요청을 하면 그에 대한 응답을 정확히 해주어야 한다.
  • 그러나 Rest 규칙에 따라 Restful한 api로써 통신이 이루어져야 한다.
  • 따라서 Rest하게 리소스,행동,표현으로써 클라이언트가 규격에 맞게 요청을 하면 서버도 마찬가지로 규칙에 따라 응답을 해주어야 한다.
  • Spring의 아키택처 패턴인 mvc패턴에 따라 컨트롤러에서 주로 request메시지를 처리하게 된다.
  • 컨트롤러는 클라이언트가 요청하는 표현(Json)에 따라서 그 요청을 처리해 주어야 하는데 spring에서 처리하는 @(어노테이션)이 있다.


Mechanism

참고 : https://elfinlas.github.io/2018/02/18/spring-parameter/

  1. http://15.164.169.213/shcool/grade/2
    and
  2. http://15.164.169.213/shcool/class?name=apple&page=2

이런 형식의 Url 창을 한번쯤은 본적이 있을것이다.

  • 사실 이것이 rest한 방식이라는 것을 그리고 그것을 전세계 웹개발자들과 사용자들이 웹을 사용할때 약속한 방식(아키텍처)라는 것을 안지는 얼마 되지 않았다. 왜냐? 나는 약속한적이 없고 그냥 이렇게 쓰니까 원래 이렇게 쓰는 줄 알았다.

  • 여튼 rest와 restful한 api의 차이점을 알고 싶으면 아래의 참고링크를 걸어두겠다.

참고 : https://velog.io/@sago_mungcci/Rest-RESTful-API%EB%9E%80

1.@PathVariable

  • 1번에 있는 주소에서 /shcool/grade/2와 같은 형식일때 사용한다
@GetMapping("/shcool/grade/{id}")
    // @pathVariable로 해당 URL의 id를 받아옴.
    public ResponseEntity<BasicResponse> readPostOne(@PathVariable Long id) {

        BasicResponse basicResponse = new BasicResponse();
        
        .....
  • @PathVariable의 경우 url에서 각 구분자에 들어오는 값을 처리해야 할 때 사용한다.

2.@RequestParam

  • 2번에 있는 주소에서 ?name=apple&page=2와 같은 형식일때 사용한다.
  • "?"앞은 서버컴퓨터의 주소이고 "?" 뒤는 이다음부터는 클라이언트가 요청하는 특정 데이터를 말한다. 이름은 apple이고 page는 2페이지에 있는 것을 요청하는 것을 말한다.
@GetMapping("/shcool/class")
    // @pathVariable로 해당 URL의 id를 받아옴.
    public ResponseEntity<BasicResponse> readPostOne(@RequestParam("name") int page) {

        BasicResponse basicResponse = new BasicResponse();
        
        .....
  • @RequestParam 어노테이션의 괄호 안의 경우 전달인자 이름(실제 값을 표시)입니다.
  • 원래는 @RequestParam String name, int page 이런식으로 적는 걸로 알았는데 처음 알았다.
@PostMapping("/shcool/class")
	public ResponseEntity<BasicResponse>  readPostOne(@RequestParam String name, int page) {
		System.out.println(">>> " + name);
		System.out.println(">>> " + page);
        
		return "result";
	}
    
    
  • 보다시피 url의 데이터를 받을 때 name,page를 변수로 받을 수있다.

3.@RequestBody

참고 : https://ocblog.tistory.com/49?category=395154

@PostMapping("/shcool/class")
	public ResponseEntity<BasicResponse>  readPostOne(@RequestBody String name, int page) {
		System.out.println(">>> " + name);
		System.out.println(">>> " + page);
        
		return "result";
	}
    
 //출력 결과
//통신 성공
//>>> name=apple&page=2
    
  • http://15.164.169.213/shcool/class?name=apple&page=2
  • 이 URL을 위의 컨트롤러에서 받아서 출력해보자.
  • 우리가 입력한 'apple' 이라는 이름과 'page'라는 번호가 잘 전달이 되었지만 단지 'name=apple&page=2' 이라는 String 으로 전달되어 전달된 데이터를 사용하기에는 불편함이 있다.
  • 그러나 리소스의 행위로 클라이언트가 요청하는 것이 아니라 JSON으로 리소스의 행위에 JSON으로 표현하여 요청하면 어떨까?

이런 형태의 Json이 있다고 가정하자.

  • { "name":"jun",
    "age":"13" }

바로위에 있는 코드에 @RequestBody가 아닌 @RequestParam으로 바꾼다면 다음과 같은 에러가 발생한다.

  • MissingServletRequestParameterException: Required String parameter 'name' is not present

  • name 이라는 파라미터가 없다고 한다.

  • 그 이유는 기본적으로 @RequestParam 은 url 상에서 데이터를 찾기 때문이다.

  • 우리가 위에서 <form'> 태그를 이용하여 데이터를 입력하고 제출 버튼을 누르면 입력한 데이터들이 url을 통해서 전달된다.

  • 예를 들면 'http://localhost:8080/grade?name=apple&page=2' 이런 식이다.

  • 반면에 Json형식으로 데이터를 전달할때는, url은 http://localhost:8080/grade 변함이 없고 body에 데이터를 포함하여 전송하기 때문에 @RequestParam 으로는 받을 수 없는 것이다.

  • 다시 @RequestParam을 @RequestBody로 바꾸면
@PostMapping("/shcool/class")
	public ResponseEntity<BasicResponse>  readPostOne(@RequestBody String name, int page) {
		System.out.println(">>> " + name);
		System.out.println(">>> " + page);
        
		return "result";
	}
    
/출력 결과
//통신 성공
//>>> {"name":"apple","page":"2"}    
    
  • <form'> 태그로 데이터를 전달하고 @RequestBody 로 받았을 때와 차이가 없어 보인다.

하지만 여기에는 큰 차이가 있다.

1)자동 객체 생성

만약 다음과 같이 name과 page 를 필요로 하는 Person 클래스가 있고 getter 가 구현되어 있다면

public class Person {
    private String name;
    private int page;

    public Person() {

    }

    public Person(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public int getPage() {
        return page;
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", page=" + page +
                '}';
    }
}
  • 다음과 같은 기능이 가능하다.
@PostMapping("/shcool/class")
	public ResponseEntity<BasicResponse>  readPostOne(@RequestBody Person person) {
		System.out.println(">>> " + name);
		System.out.println(">>> " + page);
        
		return "result";
	}
    
/출력 결과
//통신 성공
//>>> {"name":"apple","page":"2"} 
  • 신기하게도 Person 객체를 자동으로 생성해 주었다.

  • @RequestBody 가 아닌 @RequestParam 을 이용한다면 불가능하다. 한번 시도해보자.

4.@ModelAttribute

출처 : https://dahliachoi.tistory.com/44

1) Model

  • Model은 객체이다.
  • view의 이름과 view를 렌더링할 때 필요하다.
  • map으로 되어있기 때문에 controller에서 view에 필요한 데이터를 key, value로 넣어준다.
  • Servlet에서 request.setAttribute()와 비슷한 역할을 한다.
  • model객체에 담을 때는 model.addAttribute("key", value)를 사용하면 된다.

2) @ModelAttribute

  • 요청 파라미터를 받아서 필요한 객체를 만들고 그 객체에 값을 넣어주어야 한다.

  • 보통 @RequestParam을 사용해서 값을 받고, set을 사용해서 값을 넣어주곤 하지만 이 과정을 자동화시켜주는 것이 @ModelAttribute이다.

  • @ModelAttribute를 사용하지 않을 때 (model도 같이 사용해보기)
public void item(@RequestParam String name,
                 @RequestParam int price,
                 Model model){
    Item item = new Item();
    item.setName(name);
    item.setPrice(price);
    model.addAttribute("item", item);
}
  • 이렇게 @RequestParam으로 일일이 받아서 set을 해줘야 값이 저장된다. 하지만 @ModelAttribute를 사용하면 간단해진다.
  • modelAttribute 사용
public void modelAttributeEx(@ModelAttribute Item item, Model model){
	model.addAttribute("item", item);
}
  • 이렇게 간결하게 사용 가능하다.

  • @ModelAttribute가 실행되는 원리를 설명하자면 요청 파라미터의 이름으로 Item 객체의 프로퍼티를 찾는다.

  • 해당 프로퍼티의 setter를 호출해서 파라미터 값을 입력한다.

  • 하지만 저기에서 model.addAttribute도 생략 가능하다. @ModelAttribute를 사용함으로써 model에도 자동적으로 객체가 추가 되기 때문이다.

  • @ModelAttribute 어노테이션도 생략가능하다.

  • public void ModelAttributeEx(Item item, Model model){}



Retrospection

  • 과제를 하다보니까 습관적으로 쓰게 됬는데 이렇게 정리라도 해놓으니까 이해도 되면서 정리가 되는 느낌이다. 그런데 시간이 너무 많이 걸린다?????
  • 왜 진작 이렇게 정리할 생각을 하지 못했을까???
  • 마지막으로 내가 공부했던 Controller 와 HTTP Request 메시지 @어노테이션 공부했던 표를 올린다.

출처 : 항해99 스프링 심화 1주차 강의자료



profile
이리저리 생각만 많은 사고뭉치입니다.

0개의 댓글