"인프런의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의를 듣고 작성한 글 입니다."
정적 컨텐츠를 제외하고 웹을 구현하는 방법?
MVC 패턴을 통해 html 파일을 템플릿 엔진의 랜더링을 거쳐 웹 브라우저에 뿌려주느냐, 아니면 API 를 통해 데이터를 직접 전달해주느냐, 총 2가지로 보면 된다.
아래와 같이 코딩해보자.
- helloController.java
@GetMapping("hello-string")
@ResponseBody // html 태그에 있는 body 가 아니다. - http 에서 header 와 body 가 있는데 여기서 body 부에 데이터를 직접 널어주겠다는 뜻
public String helloString(@RequestParam("name") String name){
return "hello " + name;
// 템플릿엔진 과의 차이점? - 뷰 같은게 없다 -> 데이터가 그대로 웹 브라우저로 내려간다.
}
* @ResponseBody 를 사용하면 뷰 리졸버(viewResolver) 를 사용하지 않는다.
* 대신 HTTP 의 BODY 에 문자 내용을 직접 반환 해준다.(HTML 의 body 태그를 말하는 것이 아님)
위와 같이 메소드를 작성해준 후 서버를 재실행 해준 다음 URL 에 localhost:8080/hello-string?name=spring!! 를 입력하여 접속하면 화면이 정상적으로 출력되는 것을 확인 할 수 있다.
여기서 템플릿 엔진과 현재 방식이 명백하게 다른점이 나타난다.
MVC 패턴을 이용함으로써 템플릿 엔진을 거치게 될 경우, 리턴 문에 문자열로 적어둔 뷰 파일을 찾아서 해당 파일을 랜더링하여 화면에 뿌려주는 반면, @ResponseBody 어노테이션을 사용할 경우 따로 뷰 파일을 찾을 필요 없이 리턴문에 적혀있는 문자열 데이터 자체가 화면으로 뿌려지게 된다.
여기서 더 자세히 차이를 확인해보려면 템플릿 엔진으로 화면을 랜더링 했을 경우 화면의 페이지 소스 보기를 했을때 파일에 작성된 html 태그들과 내용이 출력되는 반면, @ResponseBody 를 이용했을 경우 html 태그 없이 리턴으로 뿌려진 문자열 데이터 자체만 페이지 소스로 나타나는 것을 확인할 수 있다.
그런데 만약 위와 같은 문자열이 아니라 진짜 사용해야 하는 데이터를 뿌려줘야 할 경우 어떻게 해야할까?
아래와 같이 소스 코드를 작성해보자.
- helloController.java
@GetMapping("hello-api")
@ResponseBody
public Hello helloApi(@RequestParam("name") String name){
Hello hello = new Hello();
hello.setName(name);
return hello; // 문자열이 아닌 객체 데이터를 넘겨준다.
}
// api 를 통해 데이터를 전달해주는 경우를 학습하기 위해 내부 클래스(객체) 작성
static class Hello{
private String name;
// getter, setter 메소드 작성
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
위와 같이 코드를 작성하고 서버를 재실행 시켜준 후 localhost:8080/hello-api?name=spring!! 으로 URL 접속을 해보면 여태까지와는 다른 화면이 출력되는 것을 확인할 수 있다.
이는 hello 객체 안에 들어있는 데이터 필드와 그 값을 화면상에 출력 시켜주는 것으로 형식을 자세히 보면 JSON 형태라는 것을 알 수 있다.
(스프링의 경우 객체를 반환하는 동시에 @ResponseBody 어노테이션이 붙어있다면 브라우저 측에 리턴으로 전달되는 데이터의 형태는 JSON 이 기본으로 되어있다.)
@RespoonseBody 동작원리 설명
1. localhost:8080/helllo-api 접속 요청
2. 스프링이 톰캣 서버에서 해당 URL 이 매핑되어 있는 메소드를 컨트롤러에서 찾음
3. 찾은 메소드에 @RespoonseBody 가 붙어있는 것을 확인
4. HTTP 응답에 데이터를 그대로 넘겨야 한다고 판단.
5. 여기서 문자열이 아닌 객체 데이터를 넘겨줘야 할 경우 기본적으로 JSON 타입으로 변환해서 HTTP 응답에 반환해줌
6. HttpMessageConverter 가 동작 - JsonConverter 와 StringConverter 가 존재함
7. 넘어오는 데이터가 문자열일 경우엔 StringConverter 가 동작하여 HTTP Body 에 문자 내용을 직접 반환하지만, 객체인 경우엔 JsonConverter 가 동작함 -> 이를 통해 객체 데이터가 넘어오면 해당하는 데이터를 JSON 타입으로 바꿔준다.
8. 화면에 해당 데이터를 전달해줌
* 더 자세히?
기본 문자처리시 StringHttpMessageConverter 가 동작하고 기본 객체처리시 MappingJackson2HttpMessageConverter 가 동작한다.
- 여기서 Json 이 아니라 왜 Jackson 일까?
실무에서 객체를 json 으로 바꿔주는 대표적인 라이브러리로 Jackson, GSON(구글에서 만든 라이브러리) 가 있는데, 스프링은 기본적으로 Jackson 라이브러리를 탑재하도록 되어 있다.