정보 보여주기#
- 스프링 웹 애플리케이션에서는 데이터를 가져오고 처리하는 것이 컨트롤러의 일이다.
- 브라우저에 보여주는 데이터를 HTML로 나타내는 것은 뷰가 하는 일이다.
도메인 설정하기#
- 도메인: 애플리케이션의 이해에 필요한 개념을 다루는 영역
class Ingredient(val id: String, val name: String, val type: Type) {
enum class Type {
WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE
}
}
data class Taco(val name: String? = null, val ingredients: List<String>? = null)
컨트롤러 클래스 생성하기#
- 컨트롤러: HTTP 요청을 처리하고, 브라우저에 보여줄 HTML을 뷰에 요청하거나, 또는 REST 형태의 응답 몸체에 직접 데이터를 추가한다.
@RequestMapping("/design")
@Controller
class DesignTacoController {
companion object {
val log = LoggerFactory.getLogger(DesignTacoController::class.java)
}
@GetMapping
fun showDesignForm(model: Model): String {
val ingredients = listOf(
Ingredient("FLTO", "Flour Tortilla", Ingredient.Type.WRAP),
Ingredient("COTO", "Corn Tortilla", Ingredient.Type.WRAP),
Ingredient("GRBF", "Ground Beef", Ingredient.Type.PROTEIN),
Ingredient("CARN", "Carnitas", Ingredient.Type.PROTEIN),
Ingredient("TMTO", "Diced Tomatoes", Ingredient.Type.VEGGIES),
Ingredient("LETC", "Lettuce", Ingredient.Type.VEGGIES),
Ingredient("CHED", "Cheddar", Ingredient.Type.CHEESE),
Ingredient("JACK", "Monterrey Jack", Ingredient.Type.CHEESE),
Ingredient("SLSA", "Salsa", Ingredient.Type.SAUCE),
Ingredient("SRCR", "Sour Cream", Ingredient.Type.SAUCE)
)
val types = Ingredient.Type.values()
for (type in types) {
model.addAttribute(
type.name.lowercase(),
filterByType(ingredients, type)
)
}
model.addAttribute("taco", Taco())
return "design"
}
private fun filterByType(ingredients: List<Ingredient>, type: Ingredient.Type): List<Ingredient> {
return ingredients.filter { it.type == type }
}
}
@Slf4j
: 컴파일 시점 시에 Lombok에 제공되며, 이 클래스에서 자동으로 SLF4J Logger를 생성한다.@Controller
: DesignTacoController
클래스가 컨트롤러로 식별되게 하며, 컴포넌트 검색을 해야 한다는 것을 나타낸다. 스프링이 해당 클래스를 찾은 후 스프링 애플리케이션 컨텍스트의 빈으로 인스턴스를 자동 생성한다.@RequestMapping
:- 클래스 수준으로 적용:해당 컨트롤러가 처리하는 요청의 종류를 나타낸다.
@Getmapping
: HTTP GET 요청이 수신될 때 그 요청을 처리하기 위해 메서드가 호출됨을 나타낸다.- 스프링 4.3 이전에는 이것 대신 메서드 수준의
@RequestMapping
애노테이션을 사용할 수 있었다.
@RequestMapping(method=RequestMethod.GET)
애노테이션 | 설명 |
---|
@RequestMapping | 다목적 요청을 처리한다. |
@GetMapping | HTTP GET 요청을 처리한다. |
@PostMapping | HTTP POST 요청을 처리한다. |
@PutMapping | HTTP PUT 요청을 처리한다. |
@DeleteMapping | HTTP DELETE 요청을 처리한다. |
@PatchMapping | HTTP PATCH 요청을 처리한다. |
Model
은 컨트롤러와 데이터를 보여주는 뷰 사이에서 데이터를 운반하는 객체다.Model
객체의 속성에 있는 데이터는 뷰가 알 수 있는 서블릿 요청 속성들도 복사된다.
- 메서드 마지막에 반환되는
String
값은 뷰의 논리적인 이름이다.
뷰 디자인하기#
- 스프링은 뷰를 정의하는 여러 가지 방법을 제공한다.
- JSP, Thymeleaft, FreeMaker, Mustache 등
- 뷰 라이브러리들은 어떤 웹 프로임워크와도 사용 가능하도록 설계되었다.
- 따라서 스프링의 추상화 모델을 알지 못하며, 컨트롤러가 데이터를 넣는 Model 대신 서블릿 요청 속성들을 사용한다.
- 뷰에게 요청을 전달하기 앞서 스프링은 Thymeleaft 와 이외의 뷰 템플릿이 사용하는 요청 속성에 데이터를 복사한다.
- Thymeleaf 템플릿은 요청 데이터를 나타내는 요소 속성을 추가로 갖는 HTML이다.
th:text
는 교체를 수행하는 Thymeleaf 네임스페이스 속성이다.${}
연산자는 요청 속성의 값을 사용하라는 것을 알려준다.th:each
: 컬렉션을 반복 처리하며, 해당 컬렉션의 각 요소를 HTML로 나타낸다.
- 템플릿 코드 경로:
/src/main/resources/templates
- 스프링 부트 애플리케이션의 정적 콘텐츠는 classpath의 루트 밑에 있는 /static 디렉터리에 위치한다.
폼 제출 처리하기#
- 뷰 이름에 “redirect:“가 앞에 붙으면 뒤 경로로 리다이렉션이 발생한다.
<form>
태그에 폼 액션을 지정하면, 해당 경로로 제출되도록 지정하고 있다.
폼 입력 유효성 검사하기#
- 스프링은 자바의 빈 유효성 검사(Bean Validation) API를 지원한다.
- 빈 유효성 검사 API를 사용하면 애플리케이션에 추가 코드를 작성하지 않고 유효성 검사 규칙을 쉽게 선언할 수 있다.
- 스프링 부트를 사용하면 유효성 검사 라이브러리를 쉽게 추가할 수 있다.
- 유효성 검사 API와 이 API를 구현한 하이버네이트 컴포넌트는 스프링 부트의 웹 스타터 의존성으로 자동 추가되기 때문이다.
- 스프링 MVC에서 유효성 검사 적용하는 방법
- 유효성을 검사할 클래스에 검사 규칙을 선언한다.
- 유효성 검사를 해야 하는 컨트롤러 메서드에 검사를 수행한다는 것을 지정한다.
- 검사 에러를 보여주도록 봄 퓨를 수정한다.
유효성 검사 규칙 선언하기#
@NotNull
: 속성의 값이 null이 아닌지 확인@Size
: 문자열 길이 확인@NotBlank
: 입력하지 않은 필드가 있는지 확인@CreditCardNumber
: Luhn 알고리즘 검사에 합격한 신용 카드 번호 유효성 검사@Pattern
: 정규 표현식 검사@Digits
: 숫지형식 검사. integer
필드는 자리 수 검사.
폼과 바인딩될 때 유효성 검사 수행하기#
- 유효성 검사를 하려면 컨트롤러의 메서드 인자에
@Valid
애노테이션을 추가해야 한다. @Valid
는 자바 빈 유효성 검사 API다.@Valid
애노테이션은 메서드 인자의 유효성 검사를 수행하라고 스프링 MVC에 알려준다.- 만일 어떤 검사 에러라도 있으면 에러의 상세 내역이
Errors
객체에 저장되어 메서드 인자로 전달된다.
유효성 검사 에러 보여주기#
- Thymeleaft에서는
fields
속성의 hasErrors()
메서드를 사용해서 필드에 에러가 있는지 검사한다.

뷰 컨트롤러로 작업하기#
- 뷰 컨트롤러: 모델 데이터나 사용자 입력을 처리하지 않는 간단한 컨트롤러
WebMvcContfigurer
: 스프링 MVC를 구성하는 메서드를 정의하고 있는 인터페이스addViewControllers()
: 하나 이상의 뷰 컨트롤러를 등록하기 위해 사용할 수 있는 ViewControllerRegistry
를 인자로 받는다.
@Configuration
class WebConfig: WebMvcConfigurer {
override fun addViewControllers(registry: ViewControllerRegistry) {
registry.addViewController("/").setViewName("home")
}
}
뷰 템플릿 라이브러리 선택하기#
- 서블릿 컨테이너는 자신이 JSP 명세를 구현하므로 스프링 부트의 스타터로 지정할 필요가 없다.
- 내장된 톰캣과 제티 컨테이너를 포함해서 자바 컨테이너는 /WEB-INF 밑에서 JSP 코드를 찾는다.
- JAR 파일로 생성한다면 이를 충족할 수 없다.
템플릿 캐싱#
- 기본적으로 템플릿은 최초 사용될 때 한 번만 파싱된다. 그리고 파싱된 결과는 향후 사용을 위해 캐시에 저장된다.
- 개발 시에 캐싱을 끄기위해 아래 속성값을
false
로 지정하면 된다.
템플릿 | 캐싱 속성 |
---|
FreeMarker | spring.freemarker.cache |
Groovy Templates | spring.groovy.template.cache |
Mustache | spring.mustache.cache |
Thymeleaf | spring.thymeleaf.cache |