Skip to content

Files

Latest commit

86c8c4d · Mar 22, 2022

History

History
445 lines (273 loc) · 15.1 KB

TIL220322.md

File metadata and controls

445 lines (273 loc) · 15.1 KB

Daily to do list

Java


Spring


CS


알고리즘


오늘의 회고

220322 Spring MVC

————————————————— 스프링 MVC 기본 기능

스프링 부트에서 Jar를 선택하는 이유는 JSP를 사용하지 않아서 Jar를 사용 Jar를 사용하면 항상 내장 서버(톰캣등)을 사용하고, webapp 경로도 사용하지 않는다. 내장 서버 사용에 최적화 되어 있는 기능. 최근에도 주로 이 방식 사용 War는 내장 서버도 사용가능 하지만, 주로 외부 서버 배포용

———————————————— 로깅

시스템 콘솔을 사용하면 안됨.. 별도의 로깅 라이브러리를 사용해서 로그 출력

  • 로깅 라이브러리 스프링에서 기본으로 제공 로그 라이브러리는 Logback, Log4J, Log4J2 등등 수 많은 라이브러리가 있는데 그것을 통합해서 인터페이스로 제공하는 것이 SLF4J Logback을 선택할고 SLF4J는 인터페이스

@RestController = @Controller클래스에서 return 하면 뷰의 이름을 찾는 뷰 리졸버가 실행되고 그러는데 @RestController로 하면 return 문자가 그대로 반환 (Rest = 그 RestAPI의 그 Rest) 즉, @RestController는 반환 값으로 뷰를 찾는 것이 아니라, http 메시지 바디에 바로 입력한다. 따라서 실행 결과로 ok 메시지를 받을 수 있다.

로그로 찍으면 여러 정보를 같이 담아주고  로그에 레벨을 담아줄 수 있다.

그리고 이 레벨을 가지고 운영서버에서는 info, 개발 서버는 debug 이런 식으로 레벨을 갖고 편하게 왔다갔다? 하기도 편하고 좋다.

  • 테스트 로그가 출력되는 포맷 확인 시간, 로그 레벨, 프로세스 ID, 쓰레드명, 클래스명, 로그 메시지 로그 레벨 설정으로 출력 결과 확인도 가능 로그 레벨 : Trace > Debug > Info > Warn > Error 기본이 Info레벨

 패키지뿐만 아니라 전체도 변경 가능!

****** Java 문법 차이로 메모리 낭비!  +연산을 사용하면 자바 로직 상 연산이 발생한다!!

  • 로그 사용시 장점 쓰레드 정보, 클래스 이름 같은 부가 정보 확인 가능 출력 모양 설정 가능 **** 로그 레벨에 따라 다르게 출력 가능 (애플리케이션에서 말고 설정만으로 조정 가능) 시스템 아웃 콘솔에만 출력하는 것이 아니라,파일, 네트워크로 남길 수 있고. 파일로 남길 때 용량에 따라 분할도 가능 성능도 일반 System.out보다 좋다 ( 내부 버퍼링, 멀티 쓰레드 등) 그래서 실무에서는 꼭 로그

———————————————— 요청 매핑

@RestController는 뷰를 찾는게 아니라 HTTP 메시지 바디로 바로 입력

 @RequestMapping에 배열 형태로 다중 설정도 가능

  • HTTP 메서드 메서드를 지정하지 않으면 메서드와 무관하게 호출 URI만 보고

  • 편리한 축약 애노테이션이 있다.  위에 것들에도 @RequestMapping 애노테이션이 포함되어 있다.

  • 경로 변수 사용  많이 사용 됨. 경로명에 있는 값을 @PathVariable로 데이터를 불러올 수 있음 URL 경로를 템플릿화 하는것, 매칭 되는 부분을 편리하게 조회할 수 있다.

  • 다중 매핑  값들을 여러개도 가능함.

  • 특정 파라미터 조건 매핑  잘 사용하진 않음, 특정 파라미터 정보가 있어야 함.

  • 특정 헤더로 추가 매핑  이렇게 헤더에 값이 있어야지만 실행

  • 미디어 타입 조건 매핑  이걸로 실행하면 텍스트, 사진 ,JSON 등에 따라 다르게 조건을 나눌 수 있다.

  • Accept 헤더 기반 미디어 타입  이번엔 반대로 클라이언트가 받아드릴 수 있는 타입으로 받을 수 있음.

——————— 요청 매핑 - API 예시

회원 관리를 HTTP API로 만든다 생각하고 매핑을 어떻게 하는지 (실제 데이터가 넘어가는 부분은 생략하고 URL 매핑만)

 

 @RequestMapping을 사용해서 동일한 URL 주소를 하나로 묶어 줌

—————————————————— HTTP 요청 -기본, 헤더 조회

애노테이션 기반의 스프링 컨트롤러는 다양한 파라미터리를 지원

 MultiValueMap은 Map과 유사한데, 하나의 키에 여러 값을 받을 수 있다.

—————————————————— HTTP 요청 파라미터 - @RequestParam

 @RestController도 되는데 그냥 @Controller에서는 이렇게 메서드에 @ResponseBody를 써도 문자로 전달 됨

 이렇게 생략을 더 해도 됨..

아래 V4를 보면 POST로 받았는데 requestParam은 queryString의 값을 받는 것으로 메시지 바디에 JSON으로 받은 값은 받지 못한다.

String, int Integer등의 단순 타입이면 @RequestParam도 생략이 가능하다.

  • 필수 파라미터  required를 선택할 수 있으며 true이면 무조건 값을 받아 와야 함.(아니면 오류)

객체형에는 NULL 가능 = Integer, 그냥 int는 불가능

  • 기본 값 설정  만약에 입력 값이 없으면 기본값으로 설정

  • 파라미터를 Map으로 조회  이렇게 Map은 key,value, MultiValueMap은 key=[value1,value2]… 이런식으로 들어옴

파라미터 값이 1개가 확실하면 Map 아니면 MultiMap 근데.. 멀티 쓸 일이 거의 없다..

————————————————— HTTP 요청 파라미터 - @ModelAttribute

 롬복의 Data 애노테이션을 쓰면 게터세터 다 지원

 이렇게 @ModelAttribute를 사용하면

  1. HelloData 객체를 생성한다.
  2. 요청 파라미터의 이름으로 HelloData 객체의 프로퍼티를 찾는다. 그리고 해당 프로퍼티의 setter를 호출해서 파라미터의 값을 입력(바인딩) 한다.
  3. 예) 파라미터 이름이 username이면 setUsername() 메서드를 찾아서 호출하면서 값을 입력한다. 객체에 게터세터가 있으면 그 값을 프로퍼티로 가지고 있는다..

참고) 바인딩 오류 >>> 숫자가 들어가야 하는데 문자가 오면, 타입이 안맞으면 Exception발생

 이렇게 @ModelAtribute 도 생략 가능…

스프링은! String, int, Integer 처럼 단순 타입은 @RequestParam 으로 자동 설정 나머지 = @ModelAttribute (argument resolver로 지정해둔 타입은 제외)

——————————————————— HTTP 요청 메시지 - 단순 텍스트

HTTP message body 에 데이터를 직접 담아서 요청 HTTP API에서 주로 사용, JSON XML, TEXT 데이터 형식은 주로 JSON POST, PUT, PATCH

요청 파라미터와 다르게 HTTP 메시지 바디를 통해 데이터가 직접 넘어오는 경우는 @RequestParam, @ModelAttribute를 사용할 수 없다. (물론 HTML Form 형식으로 전달되는 경우는 요청 파라미터로 인정된다!)

 InputStream(Reader), OutputStream(Writer)를 사용하여 HTTP 요청 메시지 바디의 내용을 직접 조회하거나 HTTP 응답 메시지의 바디에 직접 결과 출력을 할 수 있다!

  • HttpEntity: HTTP header, body를 간단하게 조회할 수 이다. 요청 파라미터를 조회하는 기능과는 관계 없음 (@RequestParam, @ModelAttribute)

  • HttpEntity는 응답에도 사용 가능 메시지 바디 직접 반환 헤더 정보 포함 가능 view 조회 x

HttpEntity를 상속받은 다음 객체들도 RequestEntity, ResponseEntity도 사용할 수 있다 몇가지 기능을 더 제공 해줌

 이렇게 ResponseBody, RequestBody를 사용해서 받을수 있다. (실무에서 가장 많이 사용 ㅎㅎ,..)

참고) 헤더 정보가 필요하면, @RequestHeader, ㅎ

***강조 중요 : 이렇게 메시지 바디를 직접 조회하는 기능은 요청 파라미터(쿼리스트링)를 조회하는 @RequestParam, @ModelAttribute와는 전혀 관계가 없다!!

그리고 HttpMessageConverter 가 동작함.

요청 파라미터 조회 : @RequestParam, @ModelAttribute HTTP 메시지 바디를 직접 조회하는 기능 : @RequestBody

@ResponseBody를 사용하며 view를 거치지 않고 바로 메시지 바디에 담아서 전달

—————————————————— HTTP 요청 메시지 - JSON

 서블릿에서 했던 것처럼

 이렇게 Request,Response Body를 사용해서 할수도 있음

 이렇게 HelloData를 직접 넣을수도 있음.

@RequestBody에 단순 타입이 아닌 객체를 지정할 수 있다!

HttpEntity, @RequestBody를 사용하면 HTTP 메시지 컨버터가 HTTP 메시지 바디의 내용을 우리가 원하는 문자나 객체로 변환 해준다. 문자, JSON등 객체로 변환해준다..

@RequestBody는 생략할 수 없음 생략하면 @ModelAttribute가 되어버림. 

HTTP 요청 시, Content-type이 application/json인지 꼭 확인해야 한다. 그래야 JSON을 처리할 수 있는 HTTP 메시지 컨버터가 실행된다.

 물론 HttpEntity를 사용해도 된다.

 이렇게 메시지 응답으로도 가능하다 들어올 땐 JSON 에서 메시지 컨버터로 객체로 되었다가 나갈떄는 객체에서 메시지 컨버터를 거쳐서 다시 JSON으로 바꿔준다.

 나갈 때는 Accept에 맞춰서 나감 들어올떄는 Content-type에 맞춰서 들어옴

——————————— HTTP 응답 - 정적 리소스, 뷰 템플릿

 응답은 크게 3종류이다! (요청도 3종류 ..)

  • 정적 리소스 /static, /public /resources /META_INF/resources 여기에 정적 리소스를 제공한다.

  • 뷰 템플릿 뷰 템플릿을 거쳐서 HTML이 생성되고, 뷰가 응답을 만들어서 전달을 한다.(뷰리졸버) 일반적으로 HTML을 동적으로 생성하는 용도로 사용, 다른 것들도 가능.

기본 뷰 템플릿 경로 = templates

 이렇게 가능

—————————————————— HTTP 응답 - HTTP API, 메시지 바디에 직접 입력

참고 : HTML이나 뷰 템플릿을 사용해도 HTTP 응답 메시지 바디에 HTML 데이터가 담겨서 전달 된다.

아래 버전은 객체를 보내기 때문에 상태 코드를 못정해서 애노테이션으로 붙일 수 있다. 하지만 애노테이션으로 붙이면 동적으로 바꿀 수 없기에 ReponseEntity를 사용해야 한다.

메서드마다 @ReponseBody를 붙이기 귀찮으면 클래스에 @ResponseBody에도 가능

———————————————— HTTP 메시지 컨버터

뷰 템플릿으로 HTML을 생성해서 응답하는게 아니라 HTTP API처럼 JSON 데이터를 HTTP 메시지 바디에서 직접 읽거나 쓰는 경우 HTTP 메시지 컨버터를 사용하면 편리

@ResponseBody 를 사용하면 HTTP의 Body에 문자 내용을 직접 반환 viewResolver 대신에 HttpMessageConverter가 동작

기본 문자 처리 : StringHttpMessageConverter 기본 객체 처리 : MappingJackson2HttpMessageConverter byte처리 등등 여러 HttpMessageConverter가 기본으로 등록되어 있음

참고 : 응답의 경우 클라이언트의 HTTP Accept헤더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해서 컨버터가 선택

  • 스프링 MVC는 다음의 경우 HTTP 메시지 컨버터를 적용 HTTP 요청 : @RequestBody, HttpEntity(RequestEntity) HTTP 응답 : @ResponseBody, HttpEntity(ResponseEntity)

  • HTTP 메시지 컨버터 인터페이스 인터페이스이다 다양한 컨버터가 있으니…

HTTP 메시지 컨버터는 HTTP 요청, 응답 둘 다 사용된다. 컨버터가 양방향이다.

canRead(), canWrite() : 메시지 컨버터가 해당 클래스, 미디어 타입을 지원하는지 체크 read(), write() : 메시지 컨버터를 통해서 메시지를 읽고 쓰는 기능

바이트 > String > JSON 순서

요청을 처리할 때 : Content/Type 응답을 처리할 때 : Accept

  • HTTP 요청 데이터 읽기 HTTP 요청이 오고, 컨트롤러에서 @RequestBody, HttpEntity 사용 하면 Byte? String? 객체 or HashMap? 물어봄> canRead() 그래서 대상 클래스 타입이 맞으면 HTTP 요청의 Content-TYpe 미디어 타입을 지원하는지확인 맞으면 read()를 호출해서 객체 생성하고 반환.

  • HTTP 응답 데이터 생성 컨트롤러에서 @ResponseBody, HttpEntity 로 값이 반환된다. 메시지 컨버터가 메시지를 쓸 수 있는지 확인하기 위해 canWrite()를 호출 대상 클래스 타입을 지원하는가? (Byte? String? 객체?) HTTP 요청의 Accept 미디어 타입을 지원하는가?(더 자세히는 @RequestMapping의 produces) 조건 만족하면 write()를 호출해서 HTTP 응답 메시지 바디에 데이터 생성.

 이런식으로 되는거고 ?는 안되는 경우..

——————————————— 요청 매핑 헨들러 어뎁터 구조

 여기서 메시지 컨버터가 동작

  • ArgumentResolver 리졸버는 뭔가 처리해주는 것 ㅎ(뷰 리졸버는 뷰를 찾아주고 ㅎ)

애노테이션 기반의 컨트롤러는 매우 다양하게 파라미터를 사용할 수 있다. HttpSErvletRequest, Model, @RequestParam, @modelAttribute… @RequestBody.. 등등

이렇게 파라미터를 유연하게 처리할 수 있는 이유가 ArgumentResolver!!

애노테이션 기반 컨트롤러를 처리하는 RequestMappingHandlerAdaptor가 ArgumentResolver를 호출해서 컨트롤러(핸들러)가 필요로 하는 다양한 파라미터의 값을 생성 그리고 이렇게 파라미터의 값이 모두 준비되면 컨트롤러를 호출하면서 값을 넘겨준다.

스프링은 30개가 넘는 ArgumentReolver를 제공..

정확한 명칭은 HandlerMethodArgumentResolver

  • 동작 방식 ArgumentResolver의 supportsParameter()를 호출해서 해당 파라미터를 지원하는지 체크, 지원하면 resolverArgument()를 호출해서 실제 객체를 생성! 이 객체를 컨트롤러 호출 시 넘김

  • ReturnValueHandler ArgumentResolver랑 비슷한데 이것은 응답을 반환해주는 타입을 맞춰주는 것! 컨트롤러의 반환 값을 변환 하는 것!!

컨트롤러에서 String으로 뷰 이름을 반환해도, 동작하는 이유

스프링은 10여개가 넘는 것을 지원

  • HTTP 메시지 컨버터 위치  Argument Resolver가 사용한다. ReturnValueHandler가 사용한다. HTTP 메시지 컨버터를 사용하는 @RequestBody 도 컨트롤러가 필요로 하는 파라미터의 값에 사용된다. @ResponseBody의 경우도 컨트롤러의 반환 값을 이용한다.

*요청의 경우 ArgumentResolver 들이 HTTP 메시지 컨버터를 사용해서 필요한 객체를 생성하는 것이다.

*응답의 경우 ReturnValueHandler가 있고 여기에서 HTTP 메시지 컨버터를 호출해서 응답 결과를 만든다.

*확장 : 스프링은 다음 모두를 인터페이스로 제공한다 (즉, 얼마든지 확장할 수 있다!) HandlerMethodArgumentResolver HandlerMethodReturnValueHandler HttpMessageConverter

스프링이 필요한 대부분의 기능을 제공하기 떄문에 실제 확장할 일은 많지 않다. 기능 확장은 WebMvcConfigurer를 상속 받아서 스프링 빈으로 등록하면 된다. 실제 자주 사용하지는 않으니 실제 기능 확장이 필요할 때 WebMvcConfigurer를 검색