- 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 차이
- 목적과 사용 범위:
- 애플리케이션 컨텍스트
- 스프링 프레임워크의 핵심으로, 애플리케이션의 모든 객체(빈)를 관리하고 이들 간의 의존성을 주입
- 이는 스프링 애플리케이션의 전반적인 구성 요소를 관리하는 역할을 합니다.
- 서블릿 컨텍스트
- 웹 애플리케이션에 대한 전역적인 정보를 제공
- 서블릿들 간에 공통으로 사용되는 리소스나 데이터를 관리하는 역할
- 애플리케이션 컨텍스트
- 관리하는 객체:
- 애플리케이션 컨텍스트
- 스프링 빈(예: 서비스, 리포지토리, 컨트롤러 등)을 관리
- 서블릿 컨텍스트
- 서블릿, 필터, 리스너 등 서블릿 관련 객체와 웹 애플리케이션의 전역적인 속성을 관리
- 애플리케이션 컨텍스트
- 컨텍스트의 생성 시점:
- 애플리케이션 컨텍스트
- 스프링 애플리케이션이 시작될 때 생성
- 서블릿 컨텍스트
- 웹 애플리케이션이 서버에 배포되어 실행될 때 생성
- 애플리케이션 컨텍스트
- 범위:
- 애플리케이션 컨텍스트
- 스프링 애플리케이션 내부의 빈 관리에 집중
- 서블릿 컨텍스트
- 웹 애플리케이션의 전역적인 리소스와 환경 설정 다룸
- 애플리케이션 컨텍스트
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 역할
- 클라이언트 요청 처리: 웹 브라우저나 기타 HTTP 클라이언트로부터 들어오는 요청을 처리합니다. 일반적으로 GET, POST 같은 HTTP 메서드를 통해 요청이 전달됩니다.
- 비즈니스 로직 수행: 요청에 따라 필요한 비즈니스 로직을 수행합니다. 예를 들어, 데이터베이스에 접근하여 데이터를 조회하거나 저장하는 작업을 수행할 수 있습니다.
- 응답 생성: 요청을 처리한 후, 클라이언트에게 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-
'학습 기록 (Learning Logs) > 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 |