Guide_Building an Application with Spring Boot

Dev.Hammy·2023년 12월 18일
0

Spring Guides

목록 보기
22/46

이 가이드에서는 Spring Boot가 애플리케이션 개발을 가속화하는 데 어떻게 도움이 되는지에 대한 샘플을 제공합니다. Spring 시작하기 가이드를 더 많이 읽으면 Spring Boot에 대한 더 많은 사용 사례를 볼 수 있습니다. 이 가이드는 Spring Boot를 빠르게 맛보기 위한 것입니다. 자신만의 Spring Boot 기반 프로젝트를 생성하려면 Spring Initializr를 방문하여 프로젝트 세부 정보를 입력하고 옵션을 선택한 후 번들 프로젝트를 zip 파일로 다운로드하세요.

What You Will Build

Spring Boot를 사용하여 간단한 웹 애플리케이션을 구축하고 여기에 몇 가지 유용한 서비스를 추가합니다.

Spring Boot로 무엇을 할 수 있는지 알아보세요

Spring Boot는 애플리케이션을 구축하는 빠른 방법을 제공합니다. classpath와 구성한(configured) Bean을 살펴보고 누락된 항목에 대해 합리적인 가정을 하고 해당 항목을 추가합니다. Spring Boot를 사용하면 인프라에 대한 부담을 덜고 비즈니스 기능에 더 집중할 수 있습니다.

다음 예제에서는 Spring Boot가 수행할 수 있는 작업을 보여줍니다.

  • Spring MVC가 classpath에 있습니까? 거의 항상 필요한 몇 가지 특정 Bean이 있으며 Spring Boot는 이를 자동으로 추가합니다. Spring MVC 애플리케이션에는 서블릿 컨테이너도 필요하므로 Spring Boot는 내장된 Tomcat을 자동으로 구성합니다.

  • Jetty가 classpath에 있나요? 그렇다면 아마도 Tomcat이 아니라 내장된 Jetty를 원할 것입니다. Spring Boot가 이를 처리합니다.

  • Thymeleaf가 classpath에 있나요? 그렇다면 항상 애플리케이션 컨텍스트에 추가해야 하는 몇 가지 빈이 있습니다. Spring Boot가 이를 추가합니다.

이는 Spring Boot가 제공하는 자동 구성의 몇 가지 예입니다. 동시에 Spring Boot는 방해가 되지 않습니다. 예를 들어 Thymeleaf가 경로에 있으면 Spring Boot는 자동으로 SpringTemplateEngine을 애플리케이션 컨텍스트에 추가합니다. 그러나 자신만의 설정으로 SpringTemplateEngine을 정의하면 Spring Boot는 이를 추가하지 않습니다. 이렇게 하면 약간의 노력으로도 제어할 수 있습니다.

Spring Boot는 코드를 생성하거나 파일을 편집하지 않습니다. 대신, 애플리케이션을 시작하면 Spring Boot가 beans과 settings을 동적으로 연결하고 이를 애플리케이션 컨텍스트에 적용합니다.

Create a Simple Web Application

이제 다음 목록(src/main/java/guides/springboot/HelloController.java)에 표시된 대로 간단한 웹 애플리케이션을 위한 웹 컨트롤러를 생성할 수 있습니다.

package guides.springboot;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String index() {
        return "Greetings from Spring Boot!";
    }
    
}

클래스는 @RestController로 표시됩니다. 이는 Spring MVC에서 웹 요청을 처리하는 데 사용할 준비가 되었음을 의미합니다. @GetMapping/index() 메소드에 매핑합니다. 브라우저에서 호출하거나 명령줄에서 컬을 사용하여 메서드를 호출하면 순수 텍스트가 반환됩니다. 이는 @RestController가 뷰가 아닌 데이터를 반환하는 웹 요청을 발생시키는 두 개의 주석인 @Controller@ResponseBody를 결합하기 때문입니다.

애플리케이션 클래스 생성

Spring Initializr는 간단한 애플리케이션 클래스를 생성합니다. 그러나 이 경우에는 너무 단순하다. 다음 목록(src/main/java/guides/springboot/Application.java)과 일치하도록 애플리케이션 클래스를 수정해야 합니다.

package guides.springboot;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;

import java.util.Arrays;

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);

    }

    @Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
            System.out.println("Let's inspect the beans provided by Spring Boot:");
            
            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                System.out.println(beanName);
            }
            
        };
    }
}

ApplicationContextCommandLineRunner는 스프링 프레임워크에서 다른 용도로 사용되는 것들입니다.

  1. ApplicationContext:

    • ApplicationContext는 스프링 컨테이너의 핵심 인터페이스입니다.
    • 스프링 애플리케이션의 빈들을 관리하고, 빈들 간의 의존성을 주입해주는 역할을 합니다.
    • 애플리케이션의 설정 정보를 로드하고, 빈들을 생성하고 관리하는데 사용됩니다.
    • 스프링 애플리케이션 컨텍스트는 XML 기반 또는 자바 기반의 설정을 통해 생성됩니다.
  2. CommandLineRunner:

    • CommandLineRunner는 스프링 부트에서 제공하는 인터페이스로, 애플리케이션이 실행될 때 특정한 작업을 수행할 수 있도록 하는 역할을 합니다.
    • CommandLineRunner를 구현한 빈을 등록하면, 스프링 부트 애플리케이션이 실행될 때 해당 빈의 run 메서드가 실행됩니다.
    • 주로 애플리케이션을 초기화하거나 특정한 데이터를 로드하는 등의 작업을 수행하는 데 활용됩니다.

ApplicationContext는 스프링의 핵심 컨테이너로써 빈들을 생성하고 관리하는데 사용되는 반면에, CommandLineRunner는 스프링 부트에서 제공하는 인터페이스로 애플리케이션이 실행될 때 특정한 작업을 수행하는데 활용됩니다.

코드에서 정의된 args는 실제로 CommandLineRunnerrun 메서드에서 전달되는 명령행 인수(arguments)가 아닙니다.

@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
    return args -> {
        // 여기서의 args는 커맨드 라인 실행 시에 전달되는 명령행 인수가 아닌, 빈을 정의하는 메서드 내에서 사용되는 매개변수입니다.
        // 실제 애플리케이션 실행 시 전달되는 명령행 인수(arguments)와는 직접적인 관련이 없습니다.
        // 이 부분에서 args는 빈을 정의하는 메서드에서 사용할 수 있는 임의의 이름으로 정의된 매개변수입니다.
    };
}

CommandLineRunner를 반환하는 commandLineRunner 빈 메서드 내에서 사용된 args는 단지 람다 표현식에서 사용하는 매개변수 이름으로 정의된 것일 뿐이며, 이는 실제 애플리케이션 실행 시 전달되는 명령행 인수(arguments)와는 직접적인 관련이 없습니다.

즉, args -> { ... }에서의 args는 단순히 해당 메서드 내에서 사용되는 매개변수 이름일 뿐이며, 커맨드 라인에서 전달되는 실제 명령행 인수와는 무관합니다.

Run the Application

org.springframework.boot.autoconfigure 빈을 명확하게 볼 수 있습니다. tomcatEmbeddedServletContainerFactory도 있습니다.


ApplicationContext가 빈을 생성하고 초기화하는 과정에서, 빈들이 독립적으로 초기화되므로 빈들 간의 호출 순서를 보장할 수 없습니다.

따라서 코드에서 보여주는 것처럼 빈의 이름이나 ID에 따라 정렬되어 출력될 수 있습니다. 하지만 스프링에서는 빈들 간의 의존성을 고려하여 빈을 초기화하는 경우가 많기 때문에, 특정한 의존성이 있는 경우에는 해당 의존성에 따라 호출 순서가 조금 다를 수도 있습니다.

빈들 간의 순서를 보장하려면 @DependsOn 어노테이션을 사용하거나, Ordered 인터페이스를 구현하거나, @Order 어노테이션을 활용하여 순서를 지정할 수 있습니다. 하지만 이러한 방식은 빈들 간의 직접적인 의존성이 있는 경우에만 해당되며, 전체적인 빈들의 호출 순서를 완벽하게 보장하지는 않습니다.


이제 다음 명령(출력과 함께 표시됨)을 실행하여 별도의 터미널 창에서 컬을 사용하여 서비스를 실행합니다.

$ curl http://localhost:8080

Greetings from Spring Boot!

Add Unit Tests

추가한 엔드포인트에 대한 테스트를 추가하고 싶을 것이며 Spring Test는 이를 위한 몇 가지 메커니즘을 제공합니다.

Gradle을 사용하는 경우 build.gradle 파일에 다음 종속성을 추가하세요.

testImplementation('org.springframework.boot:spring-boot-starter-test')

이제 다음 목록(src/test/java/guides/springboot/HelloControllerTest.java)에 표시된 대로 엔드포인트를 통해 서블릿 요청 및 응답을 모의하는 간단한 단위 테스트를 작성합니다.

package guides.springboot;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import static org.hamcrest.Matchers.equalTo;

import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@SpringBootTest
@AutoConfigureMockMvc
class ApplicationTests {
    
    @Autowired
    private MockMvc mvc;

    @Test
    public void getHello() throws Exception {
        mvc.perform(MockMvcRequestBuilders.get("/").accept(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk())
                .andExpect(MockMvcResultMatchers.content().string(equalTo("Greetings from Spring Boot!")));
    }
}

MockMvc는 Spring Test에서 제공되며 편리한 빌더 클래스 세트를 통해 DispatcherServlet에 HTTP 요청을 보내고 결과에 대한 어설션을 만들 수 있습니다.


DispatcherServlet은 스프링 MVC 프레임워크의 핵심이 되는 컨트롤러 중 하나입니다. 웹 요청을 받고, 처리하는데 사용됩니다. 웹 애플리케이션의 특정 URL 패턴과 매핑된 컨트롤러를 찾아서 해당 요청을 처리하고 그 결과를 반환합니다.

일반적으로 DispatcherServlet은 웹 애플리케이션의 web.xml 또는 Java Config 설정에서 설정됩니다. 클라이언트로부터 들어오는 모든 요청은 이 서블릿으로 전달되며, 이 서블릿은 적절한 핸들러(Controller)를 찾아서 요청을 전달하고 응답을 생성합니다.

DispatcherServlet의 주요 역할은 다음과 같습니다:

  1. URL 매핑 및 요청 전달: 클라이언트의 HTTP 요청을 받고, 해당 요청을 처리할 적절한 컨트롤러(핸들러)에게 전달합니다. 이때 URL 패턴과 매핑된 컨트롤러를 찾아서 요청을 라우팅합니다.

  2. 뷰(View) 선택: 핸들러(Controller)가 요청을 처리하고 나면, DispatcherServlet은 해당 요청에 대한 응답으로 사용할 뷰를 선택합니다. 일반적으로 뷰는 JSP, Thymeleaf, Freemarker 등과 같은 템플릿 엔진을 통해 생성됩니다.

  3. 모델 데이터 전달: 뷰에 전달할 모델 데이터를 설정합니다. 컨트롤러가 반환한 데이터는 뷰에 전달되어 웹 페이지를 구성하는 데 사용됩니다.

  4. 핸들러 어댑터(HandlerAdapter) 호출: DispatcherServlet은 핸들러 어댑터를 사용하여 실제 요청을 처리할 핸들러(Controller)를 실행하고, 요청을 처리한 결과를 반환합니다.

이러한 과정을 거쳐 DispatcherServlet은 웹 요청을 처리하고 적절한 응답을 생성하여 클라이언트에게 반환합니다. 이는 스프링 MVC에서 웹 애플리케이션의 요청-응답 주기를 관리하고, MVC 아키텍처에서의 역할을 담당합니다.


결과에 대한 어설션을 만든다는 것은 테스트에서 기대한 결과를 확인하기 위해 원하는 조건을 설정하고 확인하는 과정을 말합니다.

MockMvc를 사용하면 실제 HTTP 요청을 보내지 않고도 가상의 환경에서 Spring MVC 컨트롤러를 실행하고, 그 결과를 검증할 수 있습니다. 테스트 시에 예상한 동작을 확인하고 검증하기 위해 다양한 어설션(assertion) 메서드들을 사용할 수 있습니다.

예를 들어, 다음과 같은 어설션을 만들 수 있습니다:

  • HTTP 상태 코드 검증: 예상하는 HTTP 상태 코드(200, 404, 500 등)를 확인하여 요청이 제대로 처리되었는지 확인합니다.
  • 응답 본문 내용 확인: JSON, XML, HTML 등의 응답 본문을 검증하여 특정 필드나 값이 예상과 일치하는지 확인합니다.
  • 모델 속성 확인: 모델에 설정된 속성 값을 검증하여 컨트롤러가 올바른 데이터를 모델에 담았는지 확인합니다.
  • 리다이렉션 확인: 리다이렉션된 URL이 예상한 대로인지 확인합니다.
  • 뷰 이름 확인: 반환된 뷰의 이름이 예상한 뷰 이름과 일치하는지 확인합니다.

이런 어설션들을 사용하여 특정 URL에 요청을 보내고, 그 결과를 검증하여 응답이 예상대로 잘 동작하는지 확인할 수 있습니다. 이를 통해 애플리케이션의 특정 부분이 예상한 대로 작동하는지 확인할 수 있게 됩니다.


MockMvc 인스턴스를 주입하기 위해 @AutoConfigureMockMvc@SpringBootTest를 사용하는 것에 주목하세요. @SpringBootTest를 사용하면 전체 애플리케이션 컨텍스트가 생성되도록 요청합니다. 대안은 @WebMvcTest를 사용하여 컨텍스트의 웹 레이어만 생성하도록 Spring Boot에 요청하는 것입니다. 두 경우 모두 Spring Boot는 자동으로 애플리케이션의 기본 애플리케이션 클래스를 찾으려고 시도하지만 다른 것을 빌드하려는 경우 이를 재정의하거나 범위를 좁힐 수 있습니다.

HTTP 요청 주기를 모의하는 것 외에도 Spring Boot를 사용하여 간단한 전체 스택 통합 테스트를 작성할 수도 있습니다. 예를 들어, 이전에 표시된 모의 테스트 대신(또는 이와 마찬가지로) 다음 테스트를 생성할 수 있습니다(src/test/java/guides/springboot/HelloControllerIT.java에서).

package com.example.springboot;

import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.ResponseEntity;

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class HelloControllerIT {

	@Autowired
	private TestRestTemplate template;

    @Test
    public void getHello() throws Exception {
        ResponseEntity<String> response = template.getForEntity("/", String.class);
        assertThat(response.getBody()).isEqualTo("Greetings from Spring Boot!");
    }
}

webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT로 인해 임베디드 서버는 임의의 포트에서 시작되며 실제 포트는 TestRestTemplate의 기본 URL에 자동으로 구성됩니다.


RestTemplateTestRestTemplate은 Spring에서 제공하는 HTTP 통신을 위한 두 가지 서로 다른 클라이언트입니다.

  1. RestTemplate:

    • RestTemplate은 기본적으로 실제 HTTP 요청을 보내는 데 사용됩니다.
    • 주로 실제 애플리케이션 코드에서 사용되며, 외부 API 호출이나 서버 간 통신 등의 용도로 활용됩니다.
    • 예를 들어, 외부 API에 GET, POST, PUT, DELETE 등의 HTTP 메서드를 사용하여 요청을 보내고, 해당 요청에 대한 응답을 받아올 수 있습니다.
  2. TestRestTemplate:

    • TestRestTemplate은 테스트를 위한 목적으로 제공됩니다.
    • 실제 HTTP 요청을 보내는 대신, 내부적으로 Servlet 컨테이너에 연결하여 테스트용 HTTP 요청을 처리합니다.
    • 테스트 시에는 실제 서버가 아닌 내장 서버를 실행하고 이 서버에 요청을 보내어 테스트하는 데 사용됩니다.
    • 따라서 TestRestTemplate을 사용하면 실제로 HTTP 통신을 수행하지만, 내장된 서버 환경에서 테스트가 이루어집니다.

위의 코드에서 HelloControllerIT 클래스는 Spring Boot 테스트를 수행하고 있는 것으로 보입니다. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)를 사용하여 내장 서버를 랜덤 포트로 실행하고, TestRestTemplate을 사용하여 해당 서버에 HTTP 요청을 보내고 응답을 검증하고 있습니다. 이러한 접근 방식은 통합 테스트를 수행할 때, 내장 서버를 활용하여 테스트하고 그 결과를 검증하는 데 사용됩니다.


내장 서버와 별도로 구성된 외부 서버를 사용하는 것 사이에는 몇 가지 차이가 있습니다.

  1. 테스트 환경의 격리:

    • 내장 서버: 내장 서버를 사용하면 애플리케이션을 테스트할 때 외부 서버에 종속되지 않고 격리된 환경에서 테스트할 수 있습니다. 테스트 케이스를 실행할 때마다 내장 서버가 자체적으로 구동되어 테스트가 이루어집니다.
    • 외부 서버: 외부 서버를 사용할 경우 해당 서버가 구동 중이어야 하며, 테스트가 이루어지는 환경이 외부 서버에 종속됩니다. 테스트 환경을 완전히 격리하기 어려울 수 있습니다.
  2. 테스트 속도와 안정성:

    • 내장 서버: 내장 서버는 테스트 시에 빠르게 구동되며, 테스트의 반복적인 실행에 용이합니다. 또한 네트워크 지연이나 외부 서버의 부하 등으로 인한 영향을 최소화하여 안정적인 테스트를 수행할 수 있습니다.
    • 외부 서버: 외부 서버를 사용하는 경우 네트워크 지연이나 외부 서버의 상태 등이 영향을 줄 수 있어 테스트의 안정성이나 속도에 영향을 줄 수 있습니다.
  3. 테스트 설정의 용이성:

    • 내장 서버: 내장 서버는 주로 테스트 환경을 위해 사전 구성된 설정을 사용하므로 테스트용으로 적합한 구성을 갖추고 있습니다.
    • 외부 서버: 외부 서버를 사용할 경우 외부 서버의 구성이나 설정을 테스트 환경에 맞게 조정해야 할 수 있으며, 이로 인해 테스트 설정이 복잡해질 수 있습니다.

내장 서버를 사용하는 것은 테스트를 더욱 효과적으로 수행하고 속도를 높일 수 있는 방법 중 하나이며, 특히 통합 테스트 시에 유용합니다. 외부 서버를 사용하는 경우 테스트 환경의 완전한 격리가 어려울 수 있지만, 실제 프로덕션 환경과 더 유사한 상황에서 테스트를 수행할 수 있습니다.


네, 일반적으로 localhost:8080을 사용하는 경우에는 내장 서버를 활용하는 것입니다. localhost는 현재 컴퓨터의 자기 자신을 가리키는 호스트명이며, 8080은 일반적으로 내장 웹 서버가 기본적으로 사용하는 포트 번호 중 하나입니다.

내장 서버가 실행 중인 경우, 보통 localhost:8080이나 다른 호스트와 포트를 통해 서비스를 제공하며, 이는 외부에서 접속할 수 있는 서버가 아니라 내부에서만 동작하는 서버입니다. 이러한 내장 서버는 특정한 프레임워크나 언어에 내장되어 있거나 해당 프로젝트가 별도의 웹 서버 없이 독립적으로 실행되는 경우에 사용됩니다.

보통은 개발 및 테스트 목적으로 내장 서버가 사용되며, 실제 프로덕션 환경에서는 Apache, Nginx, Tomcat과 같은 별도의 웹 서버가 사용될 수 있습니다.


별도의 웹 서버를 활용하는 경우에는 해당 웹 서버의 호스트와 포트 번호 또는 도메인 주소를 사용합니다. 일반적으로 실제 프로덕션 환경에서는 웹 서버를 통해 클라이언트가 서비스에 접근하게 됩니다. 이 때 사용되는 주소는 서버의 IP 주소나 도메인 주소에 해당하는 주소입니다.

예를 들어:

  • IP 주소 사용: 웹 서버의 실제 IP 주소를 사용하여 접근할 수 있습니다. 예를 들어, http://192.168.0.1과 같이 웹 서버의 IP 주소를 입력하여 접근할 수 있습니다.

  • 도메인 주소 사용: 웹 서버에 연결된 도메인 주소를 사용하여 접근할 수 있습니다. 예를 들어, http://www.example.com과 같이 도메인 이름을 입력하여 웹 서버에 접근할 수 있습니다.

웹 서버를 활용하는 경우 실제 주소는 서버가 호스팅되는 위치와 관련이 있으며, 해당 위치에 따라 IP 주소나 도메인 주소가 다를 수 있습니다. 이러한 주소를 통해 클라이언트는 별도의 웹 서버에 접속하여 해당 서버에서 호스팅되는 웹 애플리케이션에 접근하게 됩니다.


이 두 코드 모두 HelloController에 대한 테스트를 수행하고 있어서 비슷한 기능을 하고 있습니다. 그러나 두 가지 중요한 차이가 있습니다.

  1. 테스트 방식:

    • HelloControllerTest는 Spring MVC의 MockMvc를 사용하여 컨트롤러를 테스트합니다. 이는 실제로 애플리케이션을 시작하지 않고, 내부적으로 MockMvc를 사용하여 컨트롤러의 동작을 시뮬레이트합니다.
    • HelloControllerIT는 내장 서버를 사용하여 컨트롤러를 테스트합니다. TestRestTemplate을 사용하여 애플리케이션의 실제 인스턴스를 시작하고, 실제 HTTP 요청을 보내고 결과를 받아옵니다.
  2. 테스트 환경:

    • HelloControllerTest@SpringBootTest를 사용하지만, 별도의 내장 서버를 실행하지 않습니다. 대신 MockMvc를 사용하여 서버를 시작하지 않고 컨트롤러를 단위 테스트합니다.
    • HelloControllerIT@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)를 사용하여 내장 서버를 랜덤 포트로 실행하고, 실제 HTTP 요청을 보내며 테스트를 합니다.

첫 번째 테스트인 HelloControllerTest는 컨트롤러의 동작을 시뮬레이트하여 단위 테스트하는 데 사용되며, 내부적으로 서버를 시작하지 않습니다. 두 번째 테스트인 HelloControllerIT는 실제 내장 서버를 사용하여 통합 테스트를 수행합니다.

이 두 가지 접근 방식은 각각 단위 테스트와 통합 테스트의 목적과 환경에 따라 선택됩니다. 단위 테스트에서는 컨트롤러의 동작을 격리된 환경에서 테스트하고, 통합 테스트에서는 실제 서버 환경에서 요청과 응답을 테스트합니다.

--

@MockBean은 스프링 테스트에서 사용되며, 테스트 시에 스프링 애플리케이션 컨텍스트에 가짜(Mock) 빈을 등록할 때 사용됩니다. 이는 실제 빈을 대체하여 특정 테스트 시나리오를 시뮬레이션하거나 테스트하고자 하는 대상에 대한 의존성을 대체하는 데 사용됩니다.

보통 다음과 같은 상황에서 @MockBean을 사용합니다:

  1. 테스트 환경 설정: 실제 구현이 아직 없는 경우에, 해당 빈을 대체하여 테스트 환경을 구축할 때 사용됩니다. 예를 들어, 외부 서비스 호출을 대체하기 위해 가짜 객체를 주입하는 등의 경우에 활용될 수 있습니다.

  2. 테스트 케이스의 의도된 동작 시뮬레이션: 특정 시나리오를 테스트하고자 할 때 사용됩니다. 예를 들어, 에러 조건, 특정 응답, 또는 예외적인 상황을 시뮬레이션할 때 해당 빈을 Mock으로 대체하여 의도된 동작을 시험할 수 있습니다.

예를 들어, 외부 서비스 호출을 하는 클래스가 있고, 이를 테스트하고 싶지만 실제 서비스는 테스트 중에 호출되면 안 되는 경우가 있습니다. 이 때 @MockBean을 사용하여 실제 서비스 대신 가짜(Mock) 객체를 주입하여 해당 호출을 시뮬레이션하고 응답을 조작하여 테스트를 수행할 수 있습니다.


MockMvc@MockBean은 스프링 테스트에서 다른 역할을 수행하는 것입니다.

  1. MockMvc:

    • MockMvc는 스프링 MVC 컨트롤러의 테스트를 지원하는 클래스입니다.
    • HTTP 요청 및 응답을 시뮬레이션하여 컨트롤러의 동작을 테스트할 수 있습니다.
    • 내장 서버를 시작하지 않고 컨트롤러를 테스트할 때 사용됩니다.
    • 주로 컨트롤러의 동작 및 응답을 검증하고 테스트하는 데 사용됩니다.
  2. @MockBean:

    • @MockBean은 테스트 시에 스프링 애플리케이션 컨텍스트에 가짜(Mock) 빈을 등록할 때 사용됩니다.
    • 실제 빈을 대체하여 의도된 동작을 시뮬레이션하거나 특정 테스트 시나리오를 테스트할 때 사용됩니다.
    • 주로 서비스나 컴포넌트 등의 빈을 테스트할 때 해당 빈이 의존하는 빈을 대체하고자 할 때 사용됩니다.

간단히 말하면, MockMvc는 컨트롤러의 동작과 HTTP 요청 및 응답을 테스트하는 데 사용되고, @MockBean은 테스트 시에 스프링 컨텍스트에 등록된 빈을 가짜(Mock)로 대체하여 특정 시나리오를 테스트하는 데 사용됩니다. 두 가지는 서로 다른 목적을 가지고 있으며, 테스트 시에 필요한 상황에 따라 각각 선택하여 사용됩니다.

프로덕션 등급 서비스 추가

귀하의 비즈니스를 위한 웹 사이트를 구축하는 경우 일부 관리 서비스를 추가해야 할 수도 있습니다. Spring Boot는 actuator 모듈을 통해 이러한 여러 서비스(예: 상태(health), 감사(audit), Bean 등)를 제공합니다.

Gradle을 사용하는 경우 build.gradle 파일에 다음 종속성을 추가하세요.

implementation 'org.springframework.boot:spring-boot-starter-actuator'

터미널에 아래 명령을 입력하여 실행합니다.

./gradlew bootRun

새로운 RESTful 엔드포인트 세트가 애플리케이션에 추가된 것을 볼 수 있습니다. Spring Boot에서 제공하는 관리 서비스입니다. 다음 목록은 일반적인 출력을 보여줍니다.

액추에이터는 다음을 노출합니다.

  • actuator/health
  • actuator

/actuator/shutdown 엔드포인트도 있지만 기본적으로 JMX를 통해서만 표시됩니다. 이를 HTTP 끝점으로 활성화하려면 application.properties 파일에 Management.endpoint.shutdown.enabled=true를 추가하고 Management.endpoints.web.exposure.include=health,info,shutdown을 사용하여 노출합니다. 그러나 공개적으로 사용 가능한 애플리케이션에 대해서는 종료 엔드포인트를 활성화하면 안 됩니다.


종료(Shutdown) 엔드포인트는 애플리케이션을 종료시키는 기능을 제공합니다. 이 기능은 보안상 중요하며, 애플리케이션에 민감한 영향을 미칠 수 있습니다. 그래서 보통 공개적으로 사용 가능한 애플리케이션에서는 종료 엔드포인트를 활성화하지 않습니다.

만약 종료 엔드포인트가 공개적으로 노출되어 있다면, 외부에서 이 엔드포인트를 호출하여 애플리케이션을 종료시킬 수 있습니다. 이것은 악의적인 공격자들에 의해 애플리케이션을 해치는 데 이용될 수 있습니다. 때문에 보안상의 이유로 일반적으로 공개적으로 접근 가능한 애플리케이션에서는 종료 엔드포인트를 활성화하지 않습니다.

따라서, 기본적으로 보안을 위해 공개적으로 사용 가능한 애플리케이션에서는 종료 엔드포인트를 활성화하지 않는 것이 일반적인 Best Practice입니다. 만약 애플리케이션이 내부 네트워크나 보안이 강화된 환경에서만 사용되거나 관리자가 제어하는 환경에서만 사용된다면 종료 엔드포인트를 활성화하는 것이 덜 위험할 수 있습니다.


다음 명령을 실행하여 애플리케이션의 상태를 확인할 수 있습니다.

$ curl http://localhost:8080/actuator/health
{"status":"UP"}

또한, curl을 통해 종료를 호출하여 application.properties에 필요한 line(이전 참고에 표시됨)을 추가하지 않았을 때 어떤 일이 발생하는지 확인할 수도 있습니다.

$ curl -X POST http://localhost:8080/actuator/shutdown
{"timestamp":1401820343710,"error":"Not Found","status":404,"message":"","path":"/actuator/shutdown"}

활성화하지 않았기 때문에 요청한 엔드포인트를 사용할 수 없습니다(엔드포인트가 존재하지 않기 때문).

각 REST 엔드포인트에 대한 자세한 내용과 application.properties 파일(src/main/resources)을 사용하여 설정을 조정하는 방법은 엔드포인트에 대한 설명서를 참조하세요.

0개의 댓글