코드 그라데이션
request 스코프 예제 만들기 본문
build.gradle
plugins {
id 'java'
id 'org.springframework.boot' version '2.7.16'
id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}
group = 'inflearn'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '11'
}
//lombok 설정 추가 시작
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter'
implementation 'org.junit.jupiter:junit-jupiter:5.8.1'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
//lombok 라이브러리 추가 시작
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'
testCompileOnly 'org.projectlombok:lombok'
testAnnotationProcessor 'org.projectlombok:lombok'
//lombok 라이브러리 추가 끝
implementation 'javax.inject:javax.inject:1'
//web 라이브러리 추가
implementation 'org.springframework.boot:spring-boot-starter-web'
}
tasks.named('test') {
useJUnitPlatform()
}
이제 SpringCoreApplication 을 돌려보면
"C:\Program Files\Java\jdk-11.0.16.1\bin\java.exe" -XX:TieredStopAtLevel=1 -noverify -Dspring.output.ansi.enabled=always -Dcom.sun.management.jmxremote -Dspring.jmx.enabled=true -Dspring.liveBeansView.mbeanDomain -Dspring.application.admin.enabled=true "-Dmanagement.endpoints.jmx.exposure.include=*" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2023.2.1\lib\idea_rt.jar=50345:C:\Program Files\JetBrains\IntelliJ IDEA 2023.2.1\bin" -Dfile.encoding=UTF-8 -classpath C:\Inflearn_Spring\spring_core\out\production\classes;C:\Inflearn_Spring\spring_core\out\production\resources;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.projectlombok\lombok\1.18.30\f195ee86e6c896ea47a1d39defbe20eb59cd149d\lombok-1.18.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-web\2.7.16\f6e4e226b0c9c1cf36c17c04262c702c6a0bad99\spring-boot-starter-web-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter\2.7.16\f80dbc197a703fbeb1a932a9a57a20d318ea475\spring-boot-starter-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter\5.8.1\73a218cf02d36d4e87bb9697fdbe0780e92b6bd3\junit-jupiter-5.8.1.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\javax.inject\javax.inject\1\6975da39a7040257bd51d21a231b76c915872d38\javax.inject-1.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-json\2.7.16\c9eb703f57c75b92139f1e34092de4c34111f3fc\spring-boot-starter-json-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-tomcat\2.7.16\a1a152bf27d592d98edcb1e9b9d57d881ed155d\spring-boot-starter-tomcat-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-webmvc\5.3.30\67ad9ebc6189c91942a52328f58d824cd3171fd9\spring-webmvc-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-web\5.3.30\e1a1fd179650d4ccbf95d3f475bf1050a1a84484\spring-web-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-autoconfigure\2.7.16\9aed25d721bada6273d7bb4bbd8b4280bd24a33f\spring-boot-autoconfigure-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot\2.7.16\f4b3155ce7becb10a98dec761f227b5f727286f\spring-boot-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework.boot\spring-boot-starter-logging\2.7.16\cf9f9502fc815038cb317a8bf188418b45e971aa\spring-boot-starter-logging-2.7.16.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\jakarta.annotation\jakarta.annotation-api\1.3.5\59eb84ee0d616332ff44aba065f3888cf002cd2d\jakarta.annotation-api-1.3.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-core\5.3.30\cd2b09bf9bdb45c3cf2b771317b6dd0d6b2f6a25\spring-core-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.yaml\snakeyaml\1.30\8fde7fe2586328ac3c68db92045e1c8759125000\snakeyaml-1.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-params\5.8.2\ddeafe92fc263f895bfb73ffeca7fd56e23c2cce\junit-jupiter-params-5.8.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-api\5.8.2\4c21029217adf07e4c0d0c5e192b6bf610c94bdc\junit-jupiter-api-5.8.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jsr310\2.13.5\8ba3b868e81d7fc6ead686bd2353859b111d9eaf\jackson-datatype-jsr310-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.module\jackson-module-parameter-names\2.13.5\a401a99e7a45450fd3ef76e82ba39005fd1a8c22\jackson-module-parameter-names-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.datatype\jackson-datatype-jdk8\2.13.5\1278f38160812811c56eb77f67213662ed1c7a2e\jackson-datatype-jdk8-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-databind\2.13.5\aa95e46dbc32454f3983221d420e78ef19ddf844\jackson-databind-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-websocket\9.0.80\d5846742e4cadd827e495dac086ecbbfca2a41da\tomcat-embed-websocket-9.0.80.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-core\9.0.80\55bd200b34d917428bc37165fb9a6d20a58357d5\tomcat-embed-core-9.0.80.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apache.tomcat.embed\tomcat-embed-el\9.0.80\b23cc2ee59f2357b3926188de2efc0cde6f35aaa\tomcat-embed-el-9.0.80.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-context\5.3.30\f57f929a5e4e3ccfc2efb8fc053245e82cc5c983\spring-context-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-aop\5.3.30\1727f2f562fdbdf15c7ae3ed0ff506c20555edfb\spring-aop-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-beans\5.3.30\cb67c4d7a42fbbac5a0991fb3b774f0f0e5c9834\spring-beans-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-expression\5.3.30\c9165dd27c851fd9b8e4b4547c22261ca83388c0\spring-expression-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-classic\1.2.12\d4dee19148dccb177a0736eb2027bd195341da78\logback-classic-1.2.12.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-to-slf4j\2.17.2\17dd0fae2747d9a28c67bc9534108823d2376b46\log4j-to-slf4j-2.17.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.slf4j\jul-to-slf4j\1.7.36\ed46d81cef9c412a88caef405b58f93a678ff2ca\jul-to-slf4j-1.7.36.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.springframework\spring-jcl\5.3.30\6851e13bd5e29ddbb5833e7c45322636a8606ac2\spring-jcl-5.3.30.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apiguardian\apiguardian-api\1.1.2\a231e0d844d2721b0fa1b238006d15c6ded6842a\apiguardian-api-1.1.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.platform\junit-platform-commons\1.8.2\32c8b8617c1342376fd5af2053da6410d8866861\junit-platform-commons-1.8.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.opentest4j\opentest4j\1.2.0\28c11eb91f9b6d8e200631d46e20a7f407f2a046\opentest4j-1.2.0.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-annotations\2.13.5\136f77ab424f302c9e27230b4482e8000e142edf\jackson-annotations-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\com.fasterxml.jackson.core\jackson-core\2.13.5\d07c97d3de9ea658caf1ff1809fd9de930a286a\jackson-core-2.13.5.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\ch.qos.logback\logback-core\1.2.12\1d8e51a698b138065d73baefb4f94531faa323cb\logback-core-1.2.12.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.slf4j\slf4j-api\1.7.36\6c62681a2f655b49963a5983b8b0950a6120ae14\slf4j-api-1.7.36.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.apache.logging.log4j\log4j-api\2.17.2\f42d6afa111b4dec5d2aea0fe2197240749a4ea6\log4j-api-2.17.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.jupiter\junit-jupiter-engine\5.8.2\c598b4328d2f397194d11df3b1648d68d7d990e3\junit-jupiter-engine-5.8.2.jar;C:\Users\eui44\.gradle\caches\modules-2\files-2.1\org.junit.platform\junit-platform-engine\1.8.2\b737de09f19864bd136805c84df7999a142fec29\junit-platform-engine-1.8.2.jar inflearn.spring_core.SpringCoreApplication
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.7.16)
2023-10-12 16:24:01.790 INFO 1584 --- [ main] i.spring_core.SpringCoreApplication : Starting SpringCoreApplication using Java 11.0.16.1 on EUIJOON with PID 1584 (C:\Inflearn_Spring\spring_core\out\production\classes started by eui44 in C:\Inflearn_Spring\spring_core)
2023-10-12 16:24:01.793 INFO 1584 --- [ main] i.spring_core.SpringCoreApplication : No active profile set, falling back to 1 default profile: "default"
2023-10-12 16:24:02.541 INFO 1584 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http)
2023-10-12 16:24:02.549 INFO 1584 --- [ main] o.apache.catalina.core.StandardService : Starting service [Tomcat]
2023-10-12 16:24:02.550 INFO 1584 --- [ main] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.80]
2023-10-12 16:24:02.648 INFO 1584 --- [ main] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext
2023-10-12 16:24:02.648 INFO 1584 --- [ main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 814 ms
call AppConfig.memberRepository
call AppConfig.memberService
call AppConfig.orderService
2023-10-12 16:24:02.931 INFO 1584 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2023-10-12 16:24:02.941 INFO 1584 --- [ main] i.spring_core.SpringCoreApplication : Started SpringCoreApplication in 1.539 seconds (JVM running for 2.99)
드디어 서버가 돌아간다.
참고
: spring-boot-starter-web 라이브러리를 추가하면
스프링 부트는 내장 톰켓 서버를 활용해서 웹 서버와 스프링을 함께 실행시킨다.
참고
: 스프링 부트는 웹 라이브러리가 없으면 우리가 지금까지 학습한 AnnotationConfigApplicationContext 을 기반으로
애플리케이션을 구동한다. 웹 라이브러리가 추가되면 웹과 관련된 추가 설정과 환경들이 필요하므로
AnnotationConfigServletWebServerApplicationContext 를 기반으로 애플리케이션을 구동한다.
cf. 기본 8080 포트에서 포트번호 변경하는 방법
main/resources/application.properties
server.port=9090
request 스코프 예제 개발
- 동시에 여러 HTTP 요청이 오면 정확히 어떤 요청이 남긴 로그인지 구분하기 어렵다.
- 이럴때 사용하기 딱 좋은것이 바로 request 스코프이다.
UUID가 같으면 같은 고객에게서 왔음을 확인할 수 있음.
실습 시작
common 패키지 생성 후
MyLogger
package inflearn.spring_core.common;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.UUID;
// 스프링 빈으로 등록되는 클래스를 나타내는 어노테이션
@Component
// 스프링 빈의 스코프를 "request"로 지정
@Scope(value = "request")
public class MyLogger {
private String uuid; // UUID를 저장하는 변수
private String requestURL; // HTTP 요청의 URL을 저장하는 변수
// 외부에서 HTTP 요청의 URL을 설정하는 메서드
public void setRequestURL(String requestURL) {
this.requestURL = requestURL;
}
// 로그 메시지를 출력하는 메서드
public void log(String message) {
System.out.println("[" + uuid + "]" + "[" + requestURL + "] " +
message);
}
// 빈 초기화 시 UUID를 생성하고 초기화 메시지를 출력하는 메서드
@PostConstruct
public void init() {
uuid = UUID.randomUUID().toString(); // UUID 생성
System.out.println("[" + uuid + "] request scope bean create:" + this);
}
// 빈 소멸 시 소멸 메시지를 출력하는 메서드
@PreDestroy
public void close() {
System.out.println("[" + uuid + "] request scope bean close:" + this);
}
}
컨트롤러 클래스 작성
LogDemoController
package inflearn.spring_core.web;
import inflearn.spring_core.common.MyLogger;
import inflearn.spring_core.logdemo.LogDemoService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
@Controller
@RequiredArgsConstructor
public class LogDemoController {
private final LogDemoService logDemoService;
private final MyLogger myLogger;
@RequestMapping("log-demo")
@ResponseBody
public String logDemo(HttpServletRequest request) {
String requestURL = request.getRequestURL().toString(); //고객이 어떤 URL로 보냈는지를 추출
myLogger.setRequestURL(requestURL); // URL 세팅 완료
myLogger.log("controller test");
logDemoService.logic("testId");
return "OK";
}
}
참고
: requestURL을 MyLogger에 저장하는 부분은
컨트롤러 보다는 공통 처리가 가능한 스프링 인터셉터나 서블릿 필터 같은 곳을 활용하는 것이 좋다.
여기서는 예제를 단순화 하기 위해서 사용.
스프링 웹에 익숙하다면 인터셉터를 사용해서 구현해보자.
LogDemoService 생성
package inflearn.spring_core.logdemo;
import inflearn.spring_core.common.MyLogger;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class LogDemoService {
private final MyLogger myLogger;
public void logic(String id) {
myLogger.log("service id = " + id);
}
}
실행하면 (SpringCoreApplication)
기댓값
[d06b992f...] request scope bean create
[d06b992f...][http://localhost:8080/log-demo] controller test
[d06b992f...][http://localhost:8080/log-demo] service id = testId
[d06b992f...] request scope bean close
요런 모양.
하지만... 오류가 발생한다.
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'logDemoService' defined in file [C:\Inflearn_Spring\spring_core\out\production\classes\inflearn\spring_core\logdemo\LogDemoService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'myLogger': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:801) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:224) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1372) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1222) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:582) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:921) ~[spring-context-5.3.30.jar:5.3.30]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:583) ~[spring-context-5.3.30.jar:5.3.30]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.16.jar:2.7.16]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:731) ~[spring-boot-2.7.16.jar:2.7.16]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:408) ~[spring-boot-2.7.16.jar:2.7.16]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:307) ~[spring-boot-2.7.16.jar:2.7.16]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1303) ~[spring-boot-2.7.16.jar:2.7.16]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1292) ~[spring-boot-2.7.16.jar:2.7.16]
at inflearn.spring_core.SpringCoreApplication.main(SpringCoreApplication.java:10) ~[classes/:na]
Caused by: org.springframework.beans.factory.support.ScopeNotActiveException: Error creating bean with name 'myLogger': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:383) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:276) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1391) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:911) ~[spring-beans-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:788) ~[spring-beans-5.3.30.jar:5.3.30]
... 19 common frames omitted
Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request.
at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.3.30.jar:5.3.30]
at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:42) ~[spring-web-5.3.30.jar:5.3.30]
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:371) ~[spring-beans-5.3.30.jar:5.3.30]
... 25 common frames omitted
Process finished with exit code 1
원인
스프링 애플리케이션을 실행하는 시점에 싱글톤 빈은 생성해서 주입이 가능하지만,
request 스코프 빈은 아직 생성되지 않는다.
이 빈은 실제 고객의 요청이 와야 생성할 수 있다!
다음 포스팅에서 오류를 해결해 나가자.
728x90
'Spring > 핵심 원리 구현' 카테고리의 다른 글
스코프와 프록시 (0) | 2024.02.18 |
---|---|
스코프와 Provider (0) | 2024.02.18 |
웹 스코프 (0) | 2024.02.16 |
프로토타입 스코프 - 싱글톤 빈과 함께 사용시 Provider로 문제 해결 (0) | 2024.02.15 |
프로토타입 스코프 - 싱글톤 빈과 함께 사용 시 문제점 (0) | 2024.02.15 |
Comments