본문 바로가기

Spring

@SpringBootTest, @ContextConfiguration, Servlet Context, Servlet, Dispacher Servlet

 

 

  • Spring Boot가 아닌 순수 Spring에서는 @SpringbootTest 을 못쓰는가?
  • 순수 Spring에서의 테스트?
  • Application Context를 왜 만드는거야? Servlet Context랑 차이가 뭐야?
  • Servlet Context가 없다면?
  • Servlet?
  • @WebServlet과 스프링 @Controller 차이
  • Servlet 비효율적
  • 그래서 Dispacher Servlet이 생김

Spring Boot가 아닌 순수 Spring에서는 @SpringbootTest 을 못쓰는가?

그렇다

 

스프링 부트

  • Spring Boot에서 제공하는 어노테이션
  • Spring Boot 애플리케이션의 통합 테스트를 위해 사용
  • @SpringbootTest는 애플리케이션 컨텍스트를 로드 함
    • 테스트에서 사용되는 모든 빈을 설정한 다음 테스트를 실행
  • Spring Boot는 자동 설정(autoconfiguration) 기능을 제공
  • @SpringBootTest를 사용하면 애플리케이션 전체를 테스트하기에 편리

순수 스프링

  • @ContextConfiguration과 같은 어노테이션을 사용하여 테스트 환경을 설정
  • 필요한 설정 파일이나 설정 클래스를 직접 지정

 


순수 Spring에서의 테스트

Spring Boot가 아닌 순수 Spring 애플리케이션에서는 @SpringBootTest 대신 다른 어노테이션을 사용해야 합니다.

 

 

@ContextConfiguration:

  • 테스트에서 사용할 Application Context의 설정 파일, 클래스를 지정 사용
  • 테스트 클래스에 적용하여 테스트에 사용할 Application Context를 구성하는 데 사용
  • Spring 설정 파일(XML 또는 JavaConfig 클래스)을 지정하여 필요한 bean 로드
  • AppConfig에 적힌 거 다 불러오기
// Java Config를 사용하는 경우
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {AppConfig.class})  // 애
public class MyServiceTest {
    @Autowired
    private MyService myService;
    
    @Test
    public void testService() {
        // 테스트 코드
    }
}

// 여러 설정 파일 또는 클래스 사용
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { AppConfig.class, AnotherConfig.class })
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void testService() {
        // 테스트 코드
    }
}



// XML 설정 파일을 사용하는 경우
@RunWith(SpringRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void testService() {
        // 테스트 코드
    }
}

 

 

  • 설정 파일 지정:
    • XML 설정 파일이나 Java 기반의 설정 클래스를 통해 Application Context를 로드할 수 있습니다.
  • 다양한 컨텍스트 설정 가능:
    • 여러 설정 파일이나 클래스를 배열로 지정할 수 있습니다.
    • 이 경우, 테스트 시 필요한 여러 가지 설정을 조합할 수 있습니다.
  • 통합 테스트에서 애플리케이션 컨텍스트 제공:
    • 스프링 컨텍스트를 초기화하여 애플리케이션의 실제 환경과 유사한 컨텍스트를 제공합니다.
    • 이로 인해, 애플리케이션의 각 계층이 제대로 작동하는지 테스트할 수 있습니다.

 

 

@WebAppConfiguration:

  • 웹 애플리케이션 컨텍스트(WebApplicationContext)를 설정하기 위해 사용됩니다.
  • 이는 주로 웹 애플리케이션의 테스트에 사용됩니다.
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {WebConfig.class})
@WebAppConfiguration // 애
public class MyControllerTest {
    @Autowired
    private WebApplicationContext wac;
    
    @Test
    public void testController() {
        // 테스트 코드
    }
}

 

@Transactional:

  • 테스트에서 트랜잭션을 자동으로 롤백하기 위해 사용
  • 이 어노테이션을 사용하면 테스트 후에 데이터베이스 상태가 초기화됩니다.
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {AppConfig.class})
@Transactional // 애
public class MyRepositoryTest {
    @Autowired
    private MyRepository myRepository;
    
    @Test
    public void testRepository() {
        // 테스트 코드
    }
}

 

 


Application Context를 왜 만드는거야? Servlet Context랑 차이가 뭐야?

 

Application Context & Servlet Context 차이

  1. 목적과 사용 범위:
    • 애플리케이션 컨텍스트
      • 스프링 프레임워크의 핵심으로, 애플리케이션의 모든 객체(빈)를 관리하고 이들 간의 의존성을 주입
      • 이는 스프링 애플리케이션의 전반적인 구성 요소를 관리하는 역할을 합니다.
    • 서블릿 컨텍스트
      • 웹 애플리케이션에 대한 전역적인 정보를 제공
      • 서블릿들 간에 공통으로 사용되는 리소스나 데이터를 관리하는 역할
  2. 관리하는 객체:
    • 애플리케이션 컨텍스트
      •  스프링 빈(예: 서비스, 리포지토리, 컨트롤러 등)을 관리
    • 서블릿 컨텍스트
      •  서블릿, 필터, 리스너 등 서블릿 관련 객체와 웹 애플리케이션의 전역적인 속성을 관리
  3. 컨텍스트의 생성 시점:
    • 애플리케이션 컨텍스트
      • 스프링 애플리케이션이 시작될 때 생성
    • 서블릿 컨텍스트
      • 웹 애플리케이션이 서버에 배포되어 실행될 때 생성
  4. 범위:
    • 애플리케이션 컨텍스트
      • 스프링 애플리케이션 내부의 빈 관리에 집중
    • 서블릿 컨텍스트
      • 웹 애플리케이션의 전역적인 리소스와 환경 설정 다룸

 

Application Context

ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = context.getBean(MyService.class);
myService.doSomething();

정의

  • Spring 애플리케이션 컨텍스트
    •  스프링 프레임워크에서 애플리케이션의 구성 요소(빈, Bean)들을 관리하고 제공하는 핵심 컨테이너입니다.
    • 스프링 애플리케이션이 실행되는 동안 필요한 모든 객체를 생성하고 관리
    • 이러한 객체들 간의 의존성을 주입(DI, Dependency Injection)합니다.

기능

  • 스프링 부트가 시작될 때 application context가 로드되어 빈을 생성하고 관리합니다.
  • 이때 application.yml 파일의 설정이 적용됩니다.
# application.yml
# 스프링 부트 애플리케이션에서 사용하는 설정 파일
# 데이터베이스 연결 정보, 외부 API 키, 포트 번호 등 다양한 설정 값을 정의

server:
  port: 8080

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: secret
    
// spring
@SpringBootApplication
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

 

  • 빈 관리: 스프링 애플리케이션에서 사용되는 모든 빈을 생성하고 관리합니다.
@Configuration
public class AppConfig {
    @Bean
    public MyService myService() {
        return new MyServiceImpl();
    }
}

@Component
public class MyController {
    private final MyService myService;

    @Autowired
    public MyController(MyService myService) {
        this.myService = myService;
    }

    public void doSomething() {
        myService.performAction();
    }
}

 

 

  • 의존성 주입: 빈들 간의 의존성을 자동으로 주입합니다.
  • 애플리케이션 이벤트 관리: 이벤트 리스너를 통해 애플리케이션 이벤트를 처리할 수 있습니다.
  • 국제화(I18N): 애플리케이션의 국제화 메시지를 관리할 수 있습니다.
  • AOP 지원: 애스펙트 지향 프로그래밍(AOP) 기능을 제공합니다.

 

Servlet Context

ServletContext context = request.getServletContext();
String appPath = context.getRealPath("/");

정의

  • 자바 Web Application에서 웹 애플리케이션의 전역적인 정보를 제공하는 객체
  • Web Application 당 하나만 존재하며, 애플리케이션이 시작될 때 컨테이너(Tomcat, Jetty 등)에 의해 생성 됨

기능

  • 전역적인 설정 및 초기화:
    • web.xml 또는 애노테이션 기반 설정에서 정의된 초기화 파라미터를 관리합니다.
    • 이는 애플리케이션 전체에서 사용할 수 있는 전역적인 설정 정보입니다.
    • 데이터베이스 연결 정보나 파일 경로 같은 전역 설정을 서블릿 컨텍스트에 저장하고
    • 애플리케이션의 모든 서블릿이 이 정보를 참조할 수 있습니다.
전역 초기화 파라미터
web.xml에 정의된 파라미터를 통해 모든 서블릿이 공통적으로 사용할 수 있는 정보를 설정

<!-- web.xml -->
<context-param>
    <param-name>globalConfig</param-name>
    <param-value>/config/global.properties</param-value>
</context-param>

 

 

  • 서블릿 간 데이터 공유:
    • 서블릿 컨텍스트는 속성(attribute)을 저장
    • 다른 서블릿들이 이 속성에 접근할 수 있게 해줍니다.
    • 이를 통해 서블릿 간에 데이터를 쉽게 공유할 수 있습니다.
    • 예를 들어, 특정 데이터를 한 서블릿에서 설정하고, 다른 서블릿에서 이 데이터를 가져와 사용할 수 있습니다.
서블릿 간 데이터 공유
한 서블릿에서 설정한 속성(attribute)을 다른 서블릿이 사용

// 서블릿 1
ServletContext context = getServletContext();
context.setAttribute("sharedData", "someValue");

// 서블릿 2
String sharedData = (String) getServletContext().getAttribute("sharedData");

 

 

 

애플리케이션 리소스 관리:

  • 서블릿 컨텍스트는 웹 애플리케이션의 리소스(예: 파일, 이미지, HTML 파일 등)에 접근할 수 있는 경로를 제공
  • 이를 통해 애플리케이션 내의 정적 리소스를 관리할 수 있습니다.
  • 예를 들어, context.getRealPath("/index.html")을 사용하여 실제 파일 시스템 경로를 얻을 수 있습니다.
리소스 경로 접근
웹 애플리케이션의 특정 리소스에 접근할 때 사용

ServletContext context = request.getServletContext();
String filePath = context.getRealPath("/WEB-INF/config.properties");

 

 

  • 애플리케이션 정보 제공:
    • 서블릿 컨텍스트는 애플리케이션의 메타데이터, 서버 정보, 서블릿 API 버전 등 다양한 정보를 제공합니다.
    • 이는 애플리케이션이 실행되고 있는 환경에 대한 정보를 얻는 데 유용합니다.

 

  • 서블릿의 생명주기 관리:
    • 서블릿 컨텍스트는 웹 애플리케이션이 시작되거나 종료될 때 특정 작업을 수행하도록 할 수 있습니다. 이를 통해 리소스 초기화나 해제와 같은 작업을 자동으로 처리할 수 있습니다.

 


Servlet Context가 없다면?

서블릿 컨텍스트는 웹 애플리케이션의 전역적인 정보를 관리하고 서블릿 간의 협업을 가능하게 하는 중요한 역할을 합니다.

만약 서블릿 컨텍스트가 없다면 다음과 같은 문제가 발생할 수 있습니다:

  • 서블릿 간 데이터 공유 불가:
    • 서블릿 간에 데이터를 쉽게 공유할 방법이 없어집니다.
    • 각 서블릿이 독립적으로 동작하게 되며, 전역적인 정보를 공유하기가 어렵습니다.
  • 전역 설정 관리의 어려움:
    • 데이터베이스 연결 정보나 애플리케이션 설정과 같은 전역 설정을 관리하기가 어려워집니다.
    • 모든 서블릿에 동일한 설정을 전달해야 하며, 이는 중복 코드와 관리의 복잡성을 증가시킵니다.
  • 애플리케이션 리소스 접근의 제한:
    • 애플리케이션 내의 정적 리소스에 접근하는 데 어려움이 생깁니다.
    • 예를 들어, 파일의 실제 경로나 리소스의 경로를 동적으로 얻는 것이 어렵습니다.
  • 애플리케이션의 상태 관리 불가:
    • 웹 애플리케이션의 상태나 정보에 접근할 수 없어, 애플리케이션의 시작이나 종료 시 수행해야 할 작업을 관리하기 어렵습니다.
  • 애플리케이션의 복잡성 증가:
    • 모든 서블릿이 독립적으로 동작하면서, 애플리케이션의 복잡도가 증가하고 코드가 더 비효율적으로 될 수 있습니다.

Servlet?

서블릿의 생성과 소멸

 

 

Java 기반 웹 애플리케이션에서 클라이언트(주로 웹 브라우저)로부터의 요청을 처리하고,

그에 대한 응답을 생성하는 서버 사이드 프로그램입니다.

서블릿은 자바의 표준 기술로, 웹 애플리케이션 서버(Tomcat, Jetty 등)에서 실행되며, HTTP 요청을 처리하는 데 사용

 

Servlet 역할

  1. 클라이언트 요청 처리: 웹 브라우저나 기타 HTTP 클라이언트로부터 들어오는 요청을 처리합니다. 일반적으로 GET, POST 같은 HTTP 메서드를 통해 요청이 전달됩니다.
  2. 비즈니스 로직 수행: 요청에 따라 필요한 비즈니스 로직을 수행합니다. 예를 들어, 데이터베이스에 접근하여 데이터를 조회하거나 저장하는 작업을 수행할 수 있습니다.
  3. 응답 생성: 요청을 처리한 후, 클라이언트에게 HTML, JSON, XML 등의 형태로 응답을 반환합니다.

 

Servlet 동작 방식

  • 클라이언트 요청: 사용자가 웹 브라우저에서 특정 URL을 요청합니다.
  • 서버의 서블릿 매핑: 웹 애플리케이션 서버는 요청된 URL에 매핑된 서블릿을 찾습니다.

  • 서블릿의 요청 처리: 서블릿이 요청을 처리하고 필요한 작업을 수행합니다.

여러 요청이 들어오면 멀티스레드로 처리

  • 응답 반환: 서블릿이 결과를 생성하고, 이를 클라이언트에게 HTTP 응답으로 반환합니다.

 

Servlet 예시

아래는 간단한 서블릿 예제입니다. 이 서블릿은 /hello URL로 들어오는 요청을 처리하고, "Hello, World!"라는 응답을 반환합니다.

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/*
@WebServlet("/hello"): 이 어노테이션은 이 서블릿이 /hello URL에 매핑되도록 설정합니다.
클라이언트가 /hello URL을 요청하면 이 서블릿이 실행됩니다.
*/
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

/*
doGet 메서드: 이 메서드는 GET 요청을 처리하는 역할을 합니다. 
예를 들어, 사용자가 웹 브라우저에서 /hello URL에 접근하면, 이 메서드가 실행됩니다.
*/
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // 응답의 MIME 타입 설정
        response.setContentType("text/html");
        
        // 클라이언트에게 보낼 응답의 내용을 작성
        PrintWriter out = response.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello, World!</h1>");
        out.println("</body></html>");
/*
PrintWriter: response.getWriter()로 얻은 PrintWriter 객체를 사용하여 
클라이언트에게 보낼 HTML 응답을 작성합니다. 
이 예제에서는 "Hello, World!"라는 텍스트를 포함한 
간단한 HTML 페이지를 반환합니다.
*/
    }
}

 

 


@WebServlet과 스프링 @Controller 차이

 

@WebServlet과 @Controller는 모두 웹 요청을 처리하지만,

@WebServlet은 저수준에서 직접 HTTP 요청을 처리하는 데 사용

@Controller는 스프링 MVC의 고수준 추상화를 이용하여 더 구조화되고 유지보수가 용이한 방식으로 요청을 처리

  • 간단한 서블릿 예제: 직접 HTTP 요청을 처리하고 응답을 생성해야 할 때 사용.
  • 스프링 컨트롤러 예제: 복잡한 웹 애플리케이션에서 MVC 패턴을 사용해 요청과 비즈니스 로직을 분리하고 싶을 때 사용.

둘 중 어떤 것을 사용할지는 애플리케이션의 요구사항과 개발자의 선호에 따라 달라집니다.

 

 

서블릿 비효율적

요청마다 서블릿을 정의함

기능이 중복됨

요청을 수행할때마다 스레드를 생성함

계산한다, 만든다, 포장한다가 중복됨

 

그래서 Dispacher Servlet이 생김

 

하나의 서블릿이 요청을 다룸

 

아하 이래서...

 

 

 

@WebServlet (서블릿)

  • 동작 방식:
    • @WebServlet은 Java EE(또는 Jakarta EE) 표준에 속하는 서블릿 기술을 사용하는 애노테이션입니다.
    • 서블릿은 Java 기반 웹 애플리케이션의 핵심 구성 요소
    • HTTP 요청을 직접 처리하고, HTML, JSON, XML 등의 응답을 생성합니다.
  • 매핑:
    • @WebServlet 애노테이션은 특정 URL 패턴에 서블릿 클래스를 매핑합니다.
    • 예를 들어, @WebServlet("/hello")는 /hello URL로 들어오는 요청을 처리하도록 서블릿을 설정합니다.
  • 컨트롤 흐름:
    • 서블릿은 HTTP 요청을 받으면, doGet, doPost와 같은 메서드로 요청을 처리합니다.
    • 이때 요청 및 응답 객체를 사용해 HTTP 세부 사항을 직접 관리해야 합니다.

 

@Controller (스프링 MVC)

  • 동작 방식:
    • @Controller는 Spring Framework의 MVC 패턴에서 사용하는 애노테이션입니다.
    • 스프링 MVC는 서블릿을 기반으로 동작하지만,
    • 요청 처리의 복잡한 부분을 추상화하여 더 높은 수준의 구조화된 웹 애플리케이션 개발을 가능하게 합니다.
  • 매핑:
    • @RequestMapping이나 @GetMapping, @PostMapping 같은 애노테이션과 함께 사용
    • 이러한 애노테이션은 특정 URL 패턴과 HTTP 메서드에 컨트롤러 메서드를 매핑합니다.
  • 컨트롤 흐름:
    • 스프링 MVC는 클라이언트 요청을 디스패처 서블릿이 먼저 받아,
    • 적절한 컨트롤러로 요청을 전달합니다.
    • 컨트롤러는 비즈니스 로직을 수행하고,
    • ModelAndView 또는 데이터를 반환하여 뷰(템플릿 엔진을 사용한 HTML, JSON 등)를 생성

 

 

 

사진 출처: https://youtu.be/calGCwG_B4Y?si=DyCNoki2tJS_dHH-

 

'Spring' 카테고리의 다른 글

WebFlux  (0) 2024.08.29
Layered Architecture  (0) 2024.08.13
@EnableFeignClients, @FeignClient 연관성  (0) 2024.08.12
git ignore, commit history 삭제  (2) 2024.07.31
cannot find method 'value'  (0) 2024.07.31