"인프런의 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 강의를 듣고 작성한 글 입니다."
* 웹을 개발하는데는 크게 3가지 방법이 있다.
1. 정적 컨텐츠 : 서버에서 별 다른 처리 없이 파일 자체를 웹 브라우저에 내려주는 것
2. MVC 와 템플릿 엔진 : 요즘 가장 많이 하는 방식으로, html 파일을 그냥 주는게 아니라 서버 측에서 프로그래밍을 통해 html 에 동적인 기능을 부여해 줄 수 있는것이 템플릿 엔진의 역할 -> 이를 수행하기 위한 Controller, Model, View 와 같은 3가지 구성요소를 MVC 라고 한다.
* 정적 컨텐츠 와의 차이점
정적 컨텐츠의 경우 파일을 그대로 전달해주는 것이지만 MVC 와 템플릿 엔진은 서버에서의 변형을 통해 html 에 동적인 기능을 부여하여 웹 브라우저에 내려주는 방식이라는 것이다.
3. API : JSON 과 같은 데이터 구조를 통해 필요한 데이터를 클라이언트 측에 전달해주는 방식
정적 컨텐츠 - 스프링 부트는 정적 컨텐츠 기능을 자동으로 제공해준다.
스프링 부트 정적 컨텐츠 관련 내용 링크 : https://docs.spring.io/spring-boot/docs/2.3.1.RELEASE/reference/html/spring-bootfeatures.html#boot-features-spring-mvc-static-content
웹 프로젝트에서 static 폴더에 hello-static.html 파일을 만들어 놓고 해당 파일을 웹 브라우저에 띄워보자.
- hello-static.html
<!DOCTYPE HTML>
<html>
<head>
<title>static content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
정적 컨텐츠 입니다.
</body>
</html>
접속 URL : http://localhost:8080/hello-static.html
위의 경로로 웹 브라우저를 통해 접속해보면 해당하는 파일의 내용이 잘 출력되는 것을 확인할 수 있다.
다만 정적인 컨텐츠이기 때문에 별다른 동적인 기능을 수행하지는 않는다.
말 그대로 파일의 내용 그 자체를 출력해주기만 하는 것이다.
* 정적 컨텐츠 동작 원리
1. 웹 브라우저에서 http://localhost:8080/hello-static.html 경로 접속
2. 내장 톰캣 서버에서 요청을 받고 해당 내용을 스프링으로 넘겨준다.
3. 스프링으로 요청이 넘어오면 Controller 쪽에서 hello-static 으로 경로가 매핑된 메소드가 있는지 먼저 찾아본다.
(컨트롤러가 정적 컨텐츠 보다 경로 탐색 우선순위를 먼저 가진다.)
4. Controller 에 URL 이 매핑된 메소드가 존재하지 않을 경우 내부에 있는 static/hello-static.html 파일을 찾는다.
5. 파일이 존재할 경우 웹 브라우저로 반환해준다.
MVC와 템플릿 엔진
개발을 공부하는데 있어서 관심사를 분리해야 한다는 말이 있듯이 웹 개발을 할 때에는
View 에서는 화면을 그리고 출력해주는 것에 모든 역량을 집중해 줘야 하고, Controller 와 Model 과 관련된 부분은 비즈니스 로직이나 다른 내부적인 처리를 해주는데 집중해야 한다.
서로 다른 분야간 선택과 집중을 위해 원래 하나였던 View - Controller 가 쪼개진 것이다.
(옛날엔 뷰 파일 하나에 (jsp) 비즈니스 로직에서부터 데이터베이스 접근까지 전부 다 있었다.)
다음과 같이 코딩해보자.
- helloController.java
// hello-mvc 경로 매핑된 메소드 생성(파라미터 값으로 name 을 받아야 한다.)
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
뷰 파일도 하나 생성해보자.
- hello-template.html
<html xmlns:th="http://www.thymeleaf.org">
<body>
<p th:text="'hello ' + ${name}">hello! empty</p>
</body>
</html>
여기서 컨트롤러 측 파라미터에 데이터를 넘겨주는 값 없이 localhost:8080/hello-mvc 와 같이 경로에 접속하게 되면 에러가 발생하게 된다.
그렇다면 발생한 에러에 대한 로그를 살펴보자.
MissingServletRequestParameterException: Required request parameter 'name' for method parameter type String is not present
위의 로그를 살펴보면 request parameter 로 name 변수가 필요하다는 것을 알 수 있다.
이제 컨트롤러에서 코드를 아래와 같이 변경해보자.
- helloController.java
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam(value = "name", required = false) String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
여기서 @RequestParam 어노테이션의 괄호 내부에 required = false 가 추가된 것을 볼 수 있는데, 이와 같이 설정을 해두면 request parameter 로 필요한 변수 값이 설정되어 있지 않아도 에러 없이 화면이 잘 출력되는 것을 확인할 수 있다.
(localhost:8080/hello-mvc 와 같은 경로로 name 변수 없이 접속해도 에러 없이 접속이 잘 된다.)
원래 required 속성은 기본값(default) 으로 true 가 설정되어 있는데, 이를 false 로 바꿔줌으로써 @RequestParam 을 통해 컨트롤러로 넘어와야 하는 변수가 존재하지 않아도 에러가 발생하는 것을 막아주는 것이다.
그렇다면 이번엔 다시 required = false 와 같은 설정 없이 @RequestParam 어노테이션에 들어있는 request parameter 변수에 데이터 값을 제대로 적재하여 화면이 에러없이 잘 출력될 수 있도록 해보자.
-helloController.java
// hello-mvc 경로 매핑된 메소드 생성(파라미터 값으로 name 을 받아야 한다.)
@GetMapping("hello-mvc")
public String helloMvc(@RequestParam("name") String name, Model model){
model.addAttribute("name", name);
return "hello-template";
}
접속 URL : localhost:8080/hello-mvc?name=spring!!!
위와 같은 경로로 접속 했을 경우 화면이 에러없이 잘 출력되는 것을 확인해 볼 수 있다.
여기서 name 변수에 들어간 spring!!! 값 또한 thymeleaf 템플릿 엔진의 기능으로 인해 그 값이 화면에 잘 출력된다.
* MVC 와 템플릿엔진 동작원리
1. 위에서 작성한 URL 과 같이 name 변수에 값이 적재되어 컨트롤러로 접속 요청이 넘어간다.
2. hello-mvc 로 경로가 매핑된 메소드를 컨트롤러 내부에서 찾은 후, 해당 메소드가 요구하는 name 변수가 URL 에 존재하는지 확인한다.
3. URL 에 name 변수가 존재한다면 해당 변수의 값을 메소드에 @RequestParam 어노테이션을 통해 선언해둔 변수에 적재해준 후 메소드의 기능을 동작시킨다. (model 에 name 변수의 값이 담기게 된다.)
4. 메소드의 동작을 수행한 이후 뷰 리졸버(viewResolver) 를 통해 다시 return 에 적혀있는 문자열 값을 이름으로 하는 파일을 찾아서 thymeleaf 템플릿 엔진이 처리를 해줄 수 있게끔 넘겨준다.
5. 템플릿 엔진이 랜더링을 통해 변환이(동적인 기능이 수행되고 있으므로 thymeleaf 를 통해 파일의 내용을 변환해 주어야 한다.) 된 후 해당 파일을 웹 브라우저 상에 출력 시켜준다.
'Spring basic' 카테고리의 다른 글
스프링 입문 : 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 비즈니스 요구사항 정리 및 회원 도메인과 레포지토리 만들기 (0) | 2021.11.03 |
---|---|
스프링 입문 : 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - API (0) | 2021.10.23 |
스프링 입문 : 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - View 환경설정 및 빌드하고 실행하기 (0) | 2021.10.10 |
스프링 입문 : 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술 - 프로젝트 환경설정 및 라이브러리 살펴보기 (0) | 2021.10.09 |
스프링에 대한 기본적인 학습을 다시 시작하는 데에 앞서... (0) | 2021.10.06 |