ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [스프링 인 액션] Chapter 1 - 스프링 시작하기 :: 스프링 애플리케이션 작성하기
    개발서적읽기/Spring in Action 제 5판 2020. 7. 28. 13:35




    ■웹 요청 처리

    스프링은 스프링 MVC라고 하는 강력한 웹 프레임워크를 갖고 있다.


    스프링 MVC의 중심에는 컨트롤러가 있다.


    컨트롤러는 웹 요청과 응답을 처리하는 컴포넌트다.


    웹 브라우저를 상대하는 애플리케이션의 경우


    컨트롤러는 선택적으로 모델 데이터를 채워서 응답한다.


    그리고 브라우저에 반환되는 HTML을 생성하기 위해 해당 응답의 웹 요청을 뷰에 전달한다.


    package tacos;

    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;

    @Controller
    public class HomeController {
    @GetMapping("/")
    public String home() {
    return "home";
    }
    }

    @Controller는 컴포넌트 검색 시에 HomeController 클래스가 


    컴포넌트로 식별되게 하는 것이 주 목적이다.


    따라서 스프링의 컴포넌트 검색에서는 자동으로 HomeController 클래스를 찾은 후 


    스프링 애플리케이션 컨텍스트의 빈으로 HomeController의 인스턴스를 생성한다.


    @Component, @Service, @Repository를 포함한 몇 애노테이션들도 


    @Controller와 동일한 기능을 제공하므로 이런 애노테이션들 중 어느 것을 사용해도 된다.


    그러나 @Controller를 선택한 이유는 애플리케이션에서의 컴포넌트 역할을 


    더 잘 설명해 주기 때문이다.


    home 메서드엔 @GetMapping 애노테이션이 지정되어 있다.


    루트 경로인 /의 http get 요청이 수신되면 이 메서드가 해당 요청을 처리한다.


    "home" 값은 뷰의 논리적인 이름이다. 


    뷰 템플릿은 classpath에 지정되어 있는 Thymeleaf를 사용한다.


    Thymeleaf를 사용하기 때문에 템플릿 경로는 src/main/resources/templates/ 이고 


    파일 이름은 home.html 이다. 아래는 home.html 파일의 내부 코드이다.

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:th="http://www.thymeleaf.org" lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>Welcome</h1>
    <img th:src="@{/images/java.jpg}" alt="test"/>
    </body>
    </html>

    <img> 태그를 보자. 이 태그에서는 컨텍스트의 상대적인 경로에 위치하는 


    이미지를 참조하는 @{...} 표현식을 사용해서 Thymeleaf의 th:src 속성을 지정한다.


    이미지와 같이 정적인 콘텐츠는 src/main/resources/static 폴더에 위치해야 한다.


    이제는 방금 만든 뷰에 대한 테스트를 작성할 것이다.


    즉, 루트 경로인 /의 HTTP GET요청을 수행한 후 성공적인지, 


    그리고 뷰 이름이 home이고 'Welcome' 메시지가 포함된 결과가 기대한 대로 나오는지 


    테스트한다.

    package tacos;

    /*
    * @USER JungHyun
    * @DATE 2020-07-03
    * @DESCRIPTION
    */

    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
    import org.springframework.test.web.servlet.MockMvc;

    import static org.hamcrest.core.StringContains.containsString;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

    @WebMvcTest(HomeController.class)
    class HomeControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @Test
    void testHomePage() throws Exception{
    mockMvc.perform(get("/"))
    .andExpect(status().isOk())
    .andExpect(view().name("home"))
    .andExpect(content().string(containsString("Welcome")));
    }
    }

    HomeControllerTest는 @SpringBootTest 대신 @WebMvcTest 애노테이션을 사용한다.


    이 애노테이션은 스프링 부트에서 제공하는 특별한 테스트 애노테이션이다. 


    이 애노테이션은 테스트 코드가 스프링 MVC 애플리케이션의 형태로 


    테스트가 실행되도록 한다.


    즉, HomeController가 스프링 MVC에 등록되므로, 스프링 MVC에 웹 요청을 보내는


    형식으로 테스트가 실행되도록 한다.


    또한 @WebMvcTest는 스프링 MVC를 테스트하기 위해 


    실제 서버를 시작하는 대신 스프링 MVC의 모의 메커니즘을 사용한다.


    이 모의 테스트를 진행하기 위해 테스트 클래스는 MockMvc 객체를 주입받을 수 있다.




    ■스프링 부트 DevTools

    DevTools는 스프링 개발자에게 다음과 같은 개발 시점의 편리한 도구를 제공한다.

    1. java 코드나 속성 파일들이 변경될 때 자동으로 애플리케이션을 다시 시작시킨다.


    DevTools를 사용 중일 때, 애플리케이션은 JVM에서 


    두 개의 클래스 로더에 의해 로드된다. 


    그중 하나는 자바 코드, 속성 파일, 프로젝트 등 


    src/main/ 경로에 있는 모든 것을 로드한다. 


    이것은 자주 변경될 수 있는 것이다.


    나머지 클래스 로더는 자주 변경되지 않는 의존성 라이브러리와 함께 로드된다.


    변경이 감지되는 경우 DevTools는 우리 프로젝트 코드를 포함하는 클래스 로더만 


    다시 로드하고 스프링 애플리케이션 컨텍스트를 다시 시작시킨다.


    나머지 클래스 로더는 그대로 둔다. 


    따라서 애플리케이션이 시작하는데 걸리는 시간을 조금이나마 단축해 준다.


    하지만 DevTools의 단점은 애플리케이션이 자동으로 다시 시작될 때 


    의존성 변경이 적용될 수 없다는 것이다.


    의존성 라이브러리를 포함하는 클래스 로더는 자동으로 다시 로드되지 않기 때문이다.


    따라서 빌드 명세(pom.xml)에 의존성을 추가, 변경, 삭제할 때는 애플리케이션을 


    새로 시작해야만 그러한 변경의 효과가 나타날 수 있다.



    2. 템플릿 캐시를 자동으로 비활성화한다.


    Thymeleaf와 FreeMarker 같은 템플릿에서는 템플릿의 파싱(코드 분석) 결과를 


    캐시에 저장하고 사용하도록 구성된다.


    템플릿이 사용되는 모든 웹 요청마다 매번 다시 파싱되지 않게 하기 위해서다.

    이는 운영 시에는 효과적이지만 개발시에는 그렇지 않다.


    DevTools는 모든 템플릿 캐싱을 자동으로 비활성화한다.



    3. 브라우저로 전송되는 리소스가 변경될 때 자동으로 브라우저를 새로고침한다.

    DevTools는 애플리케이션이 구동될 때 동시에 LiveReload 서버를 실행하게 할 수 있다.


    LiveReload는 서버는 리소스의 변경이 생길 때 브라우저를 자동으로 새로고침 한다.


    LiveReload는 구글 크롬, 사파리, 파이어폭스, 브라우저의 플러그인을 지원한다.



    4. 만일 H2 데이터베이스가 사용 중이라면 자동으로 H2콘솔을 활성화한다.




    ■스프링 내부 동작


    위처럼 스프링은 프레임워크를 사용하는 데 필요한 코드 작성 부담이 


    상대적으로 적은 웹 프레임워크임을 알 수 있다.


    이 부담을 줄이기 위해 스프링이 내부적으로 어떻게 동작하고 있을까?


    스프링이 하는 일을 이해하기 위해 우선 빌드 명세를 살펴보자.


    빌드 명세를 정의한 pom.xml 파일에서 Web과 Thymeleaf 의존성을 선언했다.

    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    이 두 의존성은 다음 내용을 비롯해서 일부의 다른 의존성도 포함시킨다.


    - 스프링의 MVC 프레임워크


    - 내장된 톰캣


    - Thymeleaf와 Thymeleaf 레이아웃 dialect


    이때 스프링 부트의 자동-구성 라이브러리도 개입된다.


    애플리케이션이 시작될 때 스프링 부트 자동-구성에서 


    위의 위존성 라이브러리들을 감지하고 자동으로 다음 일을 수행한다.


    - 스프링 MVC를 활성화하기 위해 스프링 애플리케이션 컨텍스트에 


    관련된 빈들을 구성한다.


    - 내장된 톰캣 서버를 스프링 애플리케이션 컨텍스트에 구성한다.


    - Thymeleaf 템플릿을 사용하는 스프링 MVC 뷰를 나타내기 위해 


    Thymeleaf 뷰 리졸버 를 구성한다.


    자동-구성이 모든 작업을 수행하므로 


    우리는 애플리케이션 구현 코드를 작성하는 데 집중할 수 있다.

    댓글

Designed by Tistory.