이 글은 김영한 님의 Infrean 강의를 학습한 내용을 정리하여 작성합니다.
이제부터는 스프링 웹 개발 기초에 대해 알아본다.
웹 개발에는 크게 세 가지 방법이 존재한다.
- 정적 컨텐츠
- MVC와 템플릿 엔진
- API
정적 컨텐츠
정적 컨텐츠란 이전 우리가 간단한 예제로 Welcome Page를 만들어 본 것을 떠올리면 된다.
정적 웹 페이지(static web page), 플랫 페이지(flat page, 스테이셔너리 페이지(stationary page)는 저장된 그대로 사용자에게 전달되는 웹 페이지로서, [1] 이는 웹 애플리케이션에 의해 생성되는 동적 웹 페이지와 반대되는 용어이다. [2]
즉, 정적 웹 페이지는 모든 상황에서 모든 사용자에게 동일한 정보를 표시하며, 콘텐츠 타입이나 문서 언어의 협상(negotiate)을 위해 웹 서버의 현대적 기능에 종속된다.
출처: https://ko.wikipedia.org/wiki/%EC%A0%95%EC%A0%81_%EC%9B%B9_%ED%8E%98%EC%9D%B4%EC%A7%80
스프링 부트는 기본적으로 정적 콘텐츠 기능을 제공해준다.
간략히 살펴보면, 스프링 부트는 정적 컨텐츠를 /static 폴더로부터 찾아 제공한다고 나와있다.
실제로 /static 폴더 내부에 html 파일을 생성해보자.
보다시피, 정적 콘텐츠는 이미 우리가 생성해 둔 파일을 변화 없이 그대로 웹 브라우저에게 전달한다.
동작 방식은 간단하다.
- 웹 브라우저에서 localhost:8080/hello-static.html 입력
- 내장 톰켓 서버가 요청(request)을 받고 스프링 컨테이너에서 hello-static 관련 컨트롤러를 찾는다.
- hello-static 관련 컨트롤러가 없으므로 톰켓 서버는 resources 폴더 내 static 폴더에서 hello-static.html이라는 이름을 가진 파일을 찾는다.
- 찾은 파일의 내용 그대로 웹 브라우저에게 전달한다.
MVC와 템플릿 엔진
모델-뷰-컨트롤러(model–view–controller, MVC)는 소프트웨어 공학에서 사용되는 소프트웨어 디자인 패턴이다. 이 패턴을 성공적으로 사용하면, 사용자 인터페이스로부터 비즈니스 로직을 분리하여 애플리케이션의 시각적 요소나 그 이면에서 실행되는 비즈니스 로직을 서로 영향 없이 쉽게 고칠 수 있는 애플리케이션을 만들 수 있다. MVC에서 모델은 애플리케이션의 정보(데이터)를 나타내며, 뷰는 텍스트, 체크박스 항목 등과 같은 사용자 인터페이스 요소를 나타내고, 컨트롤러는 데이터와 비즈니스 로직 사이의 상호동작을 관리한다.
구성요소
모델-뷰-컨트롤러는 응용 프로그램을 세 가지의 구성요소로 나눈다. 각각의 구성요소들 사이에는 다음과 같은 관계가 있다. [1]
컨트롤러는 모델에 명령을 보냄으로써 모델의 상태를 변경할 수 있다. (예: 워드 프로세서에서 문서를 편집하는 것) 또, 컨트롤러가 관련된 뷰에 명령을 보냄으로써 모델의 표시 방법을 바꿀 수 있다. (문서를 스크롤하는 것)
모델은 모델의 상태에 변화가 있을 때 컨트롤러와 뷰에 이를 통보한다. 이와 같은 통보를 통해서 뷰는 최신의 결과를 보여줄 수 있고, 컨트롤러는 모델의 변화에 따른 적용 가능한 명령을 추가·제거·수정할 수 있다. 어떤 MVC 구현에서는 통보 대신 뷰나 컨트롤러가 직접 모델의 상태를 읽어 오기도 한다.
뷰는 사용자가 볼 결과물을 생성하기 위해 모델로부터 정보를 얻어 온다.
출처: https://ko.wikipedia.org/wiki/%EB%AA%A8%EB%8D%B8-%EB%B7%B0-%EC%BB%A8%ED%8A%B8%EB%A1%A4%EB%9F%AC
템플릿 엔진
템플릿 엔진이란 , 지정된 템플릿 양식과 데이터가 합쳐져 HTML 문서를 출력하는 소프트웨어
즉, 웹사이트 화면을 어떤 형태로 만들지 도와주는 양식이다.
이때 템플릿 엔진은 우리가 서버에서 프로그래밍을 통해 동적인 요소를 추가해 페이지를 만들어 낸다.
요즘에는 MVC와 템플릿 엔진을 통해 개발을 하는 추세다.
예제
뷰와 컨트롤러를 분리해 사용하는 것은 기본이다.
뷰는 화면 시각적인 요소와 관련된 일만 수행하고
컨트롤러는 서버와 비즈니스 로직과 관련된 일을 수행한다.
매개변수(parameter)를 입력받는 컨트롤러 예제를 살펴보자.
이때, addAttribute의 첫 번째 인자는 Key값을 의미하며 두 번째 인자는 Value값을 의미한다.
hello-template.html 파일에서 p 태그 내부에 "hello! empty" 문장이 나타내는 바는 다음과 같다.
thymeleaf 템플릿 엔진의 장점은 작성한 html 파일을 서버 없이 동작시켜도 결과를 확인할 수 있다는 것이다.
보다시피 서버 없이 동작하는 것을 확인할 수 있다.
즉, p 태그 내부에 작성한 "hello! empty"는 우리가 서버 없이 동작시켜 마크업 결과를 보기 위해 사용하는 것이다.
만약 서버가 동작한다면 p 태그의 속성으로 작성한 th 내용이 출력될 것이다.
생성한 코드를 동작시켜 보자.
실행시키면 분명히 위 이미지처럼 Error가 발생할 것이다.
이유는 다음과 같다.
IntelliJ 터미널에서 "Required String parameter 'name' is not present' 경고 문구를 확인할 수 있다.
그렇다.
컨트롤러에서 "name"을 입력받도록 했는데 우리는 "name"의 값을 입력해준 적이 없다.
문제를 해결하기 전 Parameter 정보에 대해 살펴보자.
(Windows를 사용하는 경우 단축키는 "^ + P")
required라는 옵션이 존재하는데 default가 true로 설정되어 있고
이 말은 "name"의 값을 기본적으로 넘겨받아야 됨을 의미한다.
값을 넘기는 방법은 다음과 같다.
이것은 HTTP GET 방식에서 parameter값을 넘기는 방법이다.
컨트롤러의 어노테이션(@GetMapping)의 내용으로 "hello-mvc"를 작성했으므로 url을 입력할 때 "hello-template"이 아닌 "hello-mvc"를 작성해야 함에 주의하자!!
동작 방식
- url을 통해 name의 값(=spring) 입력
- 컨트롤러에서 name의 값을 spring으로 변경한 후 model에 저장된다.
- 뷰 리졸버(viewResolver)가 hello-template 화면을 찾아간다.
- ${name}을 spring으로 변경해준다.
-> ${}은 model에서 Key에 해당하는 Value값을 찾아 치환해준다.
API
API(Application Programming Interface 애플리케이션 프로그래밍 인터페이스[*], 응용 프로그램 프로그래밍 인터페이스)는 컴퓨터나 컴퓨터 프로그램 사이의 연결이다. 일종의 소프트웨어 인터페이스이며 다른 종류의 소프트웨어에 서비스를 제공한다. [1] 이러한 연결이나 인터페이스를 빌드하거나 사용하는 방법을 기술하는 문서나 표준은 API 사양으로 부른다. 이 표준을 충족하는 컴퓨터 시스템은 API가 구현(implement)되었다거나 노출(expose)되었다고 말한다. API라는 용어는 사양이나 구현체를 의미할 수 있다.
컴퓨터와 인간을 연결시키는 사용자 인터페이스와 반대로, API는 컴퓨터나 소프트웨어를 서로 연결한다. 직접 사람(최종 사용자)에 의해 사용되도록 고안된 것이 아니며, 대신 소프트웨어에 이를 통합하고자 하는 컴퓨터 프로그래머가 사용하도록 고안되었다. API는 각기 다른 부분으로 구성되기도 하며 프로그래머가 사용할 수 있는 도구나 서비스의 역할을 한다. 이러한 부분들 중 하나를 사용하는 프로그램이나 프로그래머는 API의 해당 부분을 호출(call)한다고 말한다. API를 구성하는 호출들은 서브루틴, 메서드(method), 요청, 통신 엔드포인트라고도 부른다. API 사양은 이 호출들을 정의하며, 다시 말해 이들을 어떻게 사용하거나 구현하는지를 설명한다는 것을 의미한다.
API의 한 가지 목적은 시스템이 동작하는 방식에 관한 내부의 세세한 부분을 숨기는 것으로, 내부의 세세한 부분이 나중에 변경되더라도 프로그래머가 유용하게 사용할 수 있고 일정하게 관리할 수 있는 부분들만 노출시킨다. API는 특정 시스템용으로 커스텀하게 빌드될 수도 있고, 아니면 수많은 시스템 간 상호운용성을 허용하는, 공유가 되는 표준일 수도 있다.
API라는 용어는 웹 API를 의미하기도 하며, [2] 이는 인터넷에 의해 병합된 컴퓨터들 간 통신을 허용한다. 프로그래밍 언어, 소프트웨어 라이브러리, 컴퓨터 운영 체제, 컴퓨터 하드웨어를 위한 API도 존재한다. API는 1940년대에 기원하였으나 이 용어는 1960년대, 70년대 들어서야 모습을 드러냈다.
출처: https://ko.wikipedia.org/wiki/API
예제를 통해 API 방식에 대해 이해해본다.
예제 1. 문자열 반환
이전 예제들과 달리 @ResponseBody 어노테이션이 추가되었다.
@ResponseBody는 HTTP body 부분에 데이터를 직접 넣어주겠다는 것을 의미한다.
(HTTP에 대해서는 나중에 따로 다뤄보도록 한다.)
그래서 우리가 name의 값으로 "spring"을 입력해주면
return 값이 "hello spring"으로 변경될 것이다.
이전 예제들과의 차이점은 뷰가 존재하지 않고 해당 문자가 그대로 반환된다.
실행 결과는 다음과 같다.
이렇게만 보면 이전 예제들과 별 다를 게 없어 보인다.
하지만 다음과 같이 차이점은 분명히 존재한다.
위에서 말했다시피 return 한 문자열이 그대로 출력된 결과다.
html 코드를 모두 작성하고 return 하는 방식을 사용할 수 있으나 매우 비효율적이다.
예제 2. 데이터 반환
코드를 보면 알 수 있듯이 hello라는 객체를 생성하고 반환하는 예제다.
언뜻 보기에도 실행 결과가 이전 예제들과 다르다는 것을 확인할 수 있는데, 이것은 json 방식에 해당한다.
spring에서 객체를 반환하고 @ResponseBody 어노테이션이 존재하면, json으로 반환하는 것이 기본으로 세팅되어 있다.
단축키
IntelliJ는 위 코드에서 "^ + shift + Enter"를 클릭하면 자동으로 문장을 완성시켜준다.
참고
static class Hello{}는 Static 네스티드 클래스(static nested class)에 해당하는데
static 선언이 갖는 특성이 반영된 클래스다.
따라서, 자신을 감싸는 외부 클래스의 인스턴스와 상관없이 Static 네스티드 클래스의 인스턴스 생성이 가능하다.
참고
Windows에서 "^ + N"을 클릭하면 다음과 같은 창이 나타나는데
Getter and Setter를 선택하면 다음 코드가 자동으로 생성된다.
이것은 자바 빈 표준 방식에 해당하고, property 접근 방식이라 부르기도 한다.
이렇게 데이터를 반환하는 방식이 API를 사용하는 주된 이유다.
@ResponseBody 사용 원리
- @ResponseBody를 사용
- HTTP BODY에 문자 내용을 직접 반환
- viewResolver 대신 HttpMessageConverter가 동작
- 기본 문자처리: StringHttpMessageConverter
- 기본 객체 처리: MappingJackson2HttpMessageConverter
- byte 처리 등등 기타 여러 HttpMessageConverter가 기본으로 등록되어 있음
MappingJackson은 객체를 json으로 변경해주는 유명한 라이브러리다.
대표적으로 Jackson 라이브러리와 Google의 Gson 라이브러리가 존재한다.
(spring에서는 기본적으로 Jakcson 라이브러리를 가진다.)
참고: 클라이언트의 HTTP Accept 해더와 서버의 컨트롤러 반환 타입 정보 둘을 조합해
HttpMessageConverter가 선택된다.
'스프링 > 스프링 입문' 카테고리의 다른 글
스프링 빈과 의존관계 (0) | 2022.03.01 |
---|---|
회원 관리 예제 - 백엔드 개발 (0) | 2022.02.28 |
빌드하고 실행하기 (0) | 2022.02.27 |
View 환경설정 (0) | 2022.02.26 |
라이브러리 살펴보기 (0) | 2022.02.26 |