코드 그라데이션

request 스코프 예제 만들기 본문

Spring/핵심 원리 구현

request 스코프 예제 만들기

완벽한 장면 2024. 2. 17. 13:02

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
Comments