Study

[스프링 인 액션] #1 스프링 애플리케이션 작성하기

voider 2021. 3. 12. 23:52

스프링이란?

스프링은 애플리케이션 컨텍스트라는 컨테이너를 제공한다. 이것은 애플리케이션 컴포넌트(빈)를 생성하고 관리한다. 컴포넌트 또는 빈은 스프링 애플리케이션 컨텍스트 내부에서 서로 연결되어 완전한 애플리케이션을 만든다. 벽돌, 모르타르, 목재, 못, 배관, 배선이 어우러져 집을 구성하는 것과 비슷하다.

빈의 상호 연결은 의존성 주입(Dependency Injection, DI)이라고 알려진 패턴을 기반으로 수행된다. 애플리케이션 컴포넌트에서 의존(사용)하는 다른 빈의 생성과 관리를 자체적으로 하는 대신 별도의 컨테이너가 한다. 이 컨테이너는 모든 컴포넌트를 생성하고 관리하고 그 컴포넌트를 필요로 하는 컴포넌트에게 주입(연결)한다.

애플리케이션 부트스트랩

Springboot는 JAR파일에서 애플리케이션을 실행할 수 있어야 하므로, 가장 먼저 시작되는 부트스트랩(구동) 클래스가 있어야 한다. 스프링 이니셜라이저로 생성한 프로젝트에는 이미 부트스트랩 클래스가 있다.

@SpringBootApplication
public class TacoCloudApplication {
    public static void main(String[] args) {
        SpringApplication.run(TacoCloudApplication.class, args);
    }
}

몇 줄 안 되는 코드여도 강력한 효과가 있다. @SpringBootApplication 애노테이션은 이 클래스가 스프링부트 애플리케이션임을 나타낸다.

@SpringBootApplication 은 세 개의 어노테이션을 결합한 것이다.

  • @SpringBootConfiguration
    현재 클래스(TacoCloudApplication)를 구성 클래스로 지정한다. 따라서 필요하다면 자바 기반 스프링 프레임워크 구성을 이 클래스에 추가할 수 있다. 이 애노테이션은 @Configuration 애노테이션의 특화된 형태다.
  • @EnableAutoConfiguration
    스프링부트 자동 구성을 활성화한다.
  • @ComponentScan
    컴포넌트 검색을 활성화한다. 스프링은 자동으로 컴포넌트들을 찾아서 애플리케이션 컨텍스트에 등록한다.

그리고 또 다른 중요한 부분은 JAR를 호출할 때 실행되는 메서드인 main() 메서드다. main() 메서드는 SpringApplication 클래스의 run() 메서드를 호출한다. run() 메서드로 전달하는 TacoCloudApplication.classargs 두 개의 인자는 구성 클래스와 명령행(command-line) 인자다.

SpringBootTest

스프링 이니셜라이저는 기본적인 테스트 클래스도 제공한다.

@SpringBootTest
class TacoCloudApplicationTests {
    @Test
    void contextLoads() {
    }
}

이 테스트는 실행 코드는 없지만 애플리케이션 컨텍스트가 정상 실행 되는지 확인할 수 있는 테스트다. 애플리케이션 컨텍스트의 생성을 막는 코드가 있다면 이 테스트는 실패한다.

@SpringBootTest 는 스프링부트 기능으로 테스트를 시작하라는 것을 JUnit에 알린다. main() 메서드의 SpringApplication.run() 호출에 부합하는 테스트 클래스를 나타낸다는 정도로 알고 있으면 된다.

웹 요청 처리하기

스프링은 MVC라는 웹 프레임워크를 가지고 있다. MVC의 중심에 컨트롤러가 있다. 컨트롤러는 웹 요청과 응답을 처리하는 컴포넌트다. 브라우저를 상대하는 애플리케이션의 경우 컨트롤러는 선택적으로 모델 데이터를 채워서 응답하며, 브라우저에 반환하는 HTML을 생성하기 위해 해당 응답의 웹 요청을 뷰에 전달한다.

간단한 컨트롤러와 뷰를 만들고 테스트 해보자.

HomeController.java

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

@Controller, @Service, @Repository 애노테이션은 해당 클래스가 애플리케이션 컨텍스트가 관리하는 컴포넌트라는 것을 명시하는 애노테이션이다. 사실상 @Component와 다르지 않지만, 컴포넌트의 역할을 좀 더 명확하게 설명하기 위한 애노테이션이라고 보면 된다.

home.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Taco Cloud</title>
</head>
<body>
    <h1>Welcom Taco!</h1>
    <img th:src="@{/images/taco.png}">
</body>
</html>

HomeControllerTest.java

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

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

위 테스트에서 @WebMvcTest는 스프링MVC 애플리케이션의 형태로 테스트가 실행되도록 한다. 또한 MVC를 테스트하기 위한 스프링 지원을 설정한다. 실제 서버를 시작하는 대신 MVC의 모의mocking 매커니즘을 사용해도 충분하므로 Mock테스트를 하기 위해 테스트 클래스에 MockMvc객체를 연결한다.(스프링 인 액션 23p)

책의 설명만으로 @SpringBootTest@WebMvcTest의 차이를 알기는 어려운 것 같음.

내장 WAS

테스트를 마쳤으면 직접 실행해서 확인해봐야 한다. 설명한 부트스트랩 클래스를 실행함으로써 애플리케이션을 실행할 수 있다. 스프링부트는 내장 WAS를 포함하고 있기 때문에 톰캣과 같은 애플리케이션 서버와 연결하지 않고 바로 실행할 수 있다.

스프링은 프레임워크의 요구를 만족시키기 위한 코드보다 애플리케이션의 요구를 충족하는 코드에 집중할 수 있도록 한다. 실제로 프로젝트를 생성하고 단 한 줄의 설정도 없이 몇 줄의 코드만 썼을 뿐인데 간단한 MVC를 구현할 수 있었다. 어떻게 이것이 가능할까? pom.xml의 빌드명세를 보면 spring-boot-starter-thymeleaf와 spring-boot-starter-web을 선언했다. 이 의존성들은 자신이 필요로 하는 다른 의존성을 추가시킨다.

  • 스프링 MVC프레임워크
  • 내장 톰캣
  • Thymeleaf와 Thymeleaf 레이아웃 dialect

스프링부트의 자동-구성 라이브러리도 개입되므로 애플리케이션이 시작될 때 스프링부트 자동-구성에서 그런 의존성 라이브러리를 감지하고 자동으로 이런 일을 실행한다.

  1. 스프링MVC 활성화기 위해 스프링 애플리케이션 컨텍스트에 관련된 빈들은 구성한다.
  2. 내장된 톰캣 서버를 스프링 애플리케이션 컨텍스트에 구성한다.
  3. Thyemleaf 템플릿을 사용하는 MVC뷰를 나타내기 위해 Thymeleaf View Resolver를 구성한다.

요약

  • 스프링은 웹 애플리케이션 생성, 데이터베이스 사용, 보안, 마이크로서비스 등에 개발자의 노력을 덜어준다.
  • 스프링부트는 의존성관리, 자동 구성, 런타임 시 애플리케이션 내부 작동 파악을 스프링에서 할 수 있게 한다.