View Resolution

2025. 2. 28. 02:06Spring Framework/Web on Servlet Stack

Spring MVC에서 뷰(View)란 사용자가 요청한 데이터를 렌더링하여 응답하는 역할을 합니다.
Spring MVC는 특정 뷰 기술(JSP, Thymeleaf, FreeMarker 등)에 종속되지 않고,
ViewResolver를 사용하여 논리적인 뷰 이름을 실제 뷰로 변환하는 방식을 채택하고 있습니다.

1. ViewResolver와 View 개념

Spring MVC는 View와 View Resolution을 분리하여,
컨트롤러가 특정 뷰 기술(JSP, FreeMarker 등)에 종속되지 않도록 설계되었습니다.

📌 ViewResolver 역할

  • 컨트롤러가 반환한 논리적인 뷰 이름(view name)을 실제 뷰 객체로 변환
  • 예를 들어, "home"이라는 뷰 이름이 "WEB-INF/views/home.jsp"로 매핑될 수 있음

📌 View 역할

  • 데이터를 적절한 형식(HTML, JSON, PDF 등)으로 렌더링하여 클라이언트에 응답
  • 예를 들어, JSP, Thymeleaf, JSON, PDF 등의 형태로 뷰를 생성할 수 있음

2. 주요 ViewResolver 구현체

Spring MVC는 여러 가지 ViewResolver 구현체를 제공하며,
각 구현체는 서로 다른 방식으로 뷰를 매핑하고 렌더링합니다.

📌 ViewResolver 구현체 종류

ViewResolver 설명
AbstractCachingViewResolver 뷰를 캐싱하여 성능을 향상 (FreeMarker 같은 템플릿 엔진과 함께 사용 가능)
UrlBasedViewResolver 논리적 뷰 이름을 URL 기반으로 직접 매핑
InternalResourceViewResolver JSP 및 서블릿 기반 뷰를 처리 (JSTL 포함 가능)
FreeMarkerViewResolver FreeMarker 템플릿을 사용한 뷰 해석
ContentNegotiatingViewResolver 요청의 Accept 헤더를 기반으로 적절한 뷰를 선택 (JSON, XML, HTML 등)
BeanNameViewResolver 뷰 이름을 빈(bean) 이름으로 해석

📌 ViewResolver는 여러 개를 체인으로 연결할 수도 있으며, 순서를 설정할 수 있음.
📌 특히 JSP를 사용할 경우, InternalResourceViewResolver는 항상 마지막에 배치해야 함.

3. ViewResolver 구현체 설명 및 예제

1. InternalResourceViewResolver (JSP + JSTL)

JSP를 뷰로 사용할 때 가장 많이 사용하는 뷰 리졸버입니다.

📌 설정 예제 (Java 기반)

@Bean
public InternalResourceViewResolver internalResourceViewResolver() {
    InternalResourceViewResolver resolver = new InternalResourceViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".jsp");
    return resolver;
}

📌 설명

  • 컨트롤러에서 "home"을 반환하면 → /WEB-INF/views/home.jsp로 변환
  • JSP 파일을 웹 루트가 아닌 WEB-INF 아래 두어 직접 접근을 막음

📌 컨트롤러 예제

@Controller
public class HomeController {

    @GetMapping("/home")
    public String home() {
        return "home"; // "WEB-INF/views/home.jsp"로 해석됨
    }
}

2. UrlBasedViewResolver (URL을 직접 매핑)

  • 논리적 뷰 이름을 URL과 직접 연결하는 뷰 리졸버
  • 별도의 뷰 매핑 없이 뷰 이름이 파일 경로와 일치할 경우 적합

📌 설정 예제

@Bean
public UrlBasedViewResolver urlBasedViewResolver() {
    UrlBasedViewResolver resolver = new UrlBasedViewResolver();
    resolver.setPrefix("/WEB-INF/views/");
    resolver.setSuffix(".html");
    return resolver;
}

"about"을 반환하면 → /WEB-INF/views/about.html로 변환됨

3. ContentNegotiatingViewResolver (컨텐츠 협상 기반 뷰 선택)

  • 요청의 Accept 헤더나 format 파라미터를 기반으로 뷰를 선택
  • JSON, XML, HTML 등 다양한 포맷을 자동 선택 가능

📌 설정 예제

@Bean
public ContentNegotiatingViewResolver contentNegotiatingViewResolver() {
    ContentNegotiatingViewResolver resolver = new ContentNegotiatingViewResolver();
    resolver.setDefaultViews(List.of(new MappingJackson2JsonView()));
    return resolver;
}

📌 사용 예제

GET /users           → HTML 응답 (기본)
GET /users?format=json  → JSON 응답
GET /users (Accept: application/json) → JSON 응답

4. BeanNameViewResolver (빈 이름으로 뷰를 찾음)

뷰 이름을 Spring 빈 이름과 연결하는 뷰 리졸버입니다.

📌 설정 예제

@Bean
public BeanNameViewResolver beanNameViewResolver() {
    return new BeanNameViewResolver();
}

@Bean(name = "myView")
public View myCustomView() {
    return new CustomView();
}

📌 컨트롤러 예제

@Controller
public class MyController {

    @GetMapping("/custom")
    public String customView() {
        return "myView"; // "myView"라는 빈을 찾아서 실행
    }
}

4. 뷰 리졸버 체인 설정

📌 뷰 리졸버를 여러 개 등록할 수 있으며, 순서를 지정할 수도 있습니다.

@Bean
public ViewResolverRegistry viewResolverRegistry() {
    ViewResolverRegistry registry = new ViewResolverRegistry();
    registry.viewResolver(contentNegotiatingViewResolver());
    registry.viewResolver(internalResourceViewResolver());
    return registry;
}

컨텐츠 협상을 먼저 하고, JSP 뷰는 그 이후에 적용

📌 JSP를 사용할 경우, InternalResourceViewResolver는 항상 마지막에 배치해야 함!

5. 리다이렉트와 포워드 처리

Spring MVC는 특수한 뷰 이름 접두사(redirect:forward:)를 사용하여 리다이렉트 및 포워드를 지원합니다.

1. redirect: (리다이렉트)

  • redirect:를 사용하면 새로운 URL로 이동
  • 302 Found 응답을 반환하고, 클라이언트가 새 URL로 이동

📌 예제

@GetMapping("/old-page")
public String redirect() {
    return "redirect:/new-page";
}

/old-page 요청 시 /new-page로 리다이렉트됨

2. forward: (포워드)

  • forward:를 사용하면 서블릿 내에서 요청을 전달
  • RequestDispatcher.forward()를 호출하여 클라이언트가 URL이 변경되었다는 사실을 모름

📌 예제

@GetMapping("/forward-example")
public String forward() {
    return "forward:/final-destination";
}

➡ 브라우저 주소는 그대로 유지되고 /final-destination으로 포워드됨

🚀 Summary

1️⃣ ViewResolver는 논리적 뷰 이름을 실제 뷰로 변환하는 역할을 함
2️⃣ 주요 ViewResolver

  • InternalResourceViewResolver → JSP 기반 뷰
  • UrlBasedViewResolver → URL 기반 뷰
  • ContentNegotiatingViewResolverAccept 헤더 기반 JSON, XML, HTML 뷰 선택
  • BeanNameViewResolver → 빈 이름을 뷰로 매핑
    3️⃣ 리다이렉트와 포워드
  • redirect: → 클라이언트가 새로운 URL로 이동 (302 Found)
  • forward: → 서버 내부에서 다른 리소스로 이동 (RequestDispatcher.forward())

📌 Spring MVC의 ViewResolution을 활용하면 다양한 뷰 기술을 유연하게 적용할 수 있습니다! 🚀

 

출처 : https://docs.spring.io/spring-framework/reference/web/webmvc/mvc-servlet/viewresolver.html

'Spring Framework > Web on Servlet Stack' 카테고리의 다른 글

Logging  (1) 2025.02.28
Multipart Resolver  (0) 2025.02.28
Exceptions  (0) 2025.02.28
Interception  (0) 2025.02.28
Path Matching  (0) 2025.02.27