인프런 커뮤니티 질문&답변

sdyj178님의 프로필 이미지
sdyj178

작성한 질문수

토비의 스프링 부트 - 이해와 원리

@Configuration과 proxyBeanMethods

자동 구성 정보 분리가 안됩니다.

작성

·

3.2K

·

수정됨

0

안녕하세요 자동 구성 정보 분리쪽 강의를 따라 구현하던 도중 문제가 발생하여 질문을 남깁니다.

 

return new String[]{
        "tobyspring.config.autoconfig.TomcatWebServerConfig",
        "tobyspring.config.autoconfig.DispatcherServletConfig"
};

직접 경로를 작성해주는 경우에는 문제 없이 동작합니다.

Iterable<String> candidates = ImportCandidates.load(MyAutoConfiguration.class, classLoader);
return StreamSupport.stream(candidates.spliterator(), false).toArray(String[]::new);

클래스 로더를 이용해서 외부에서 파일 경로를 불러오는 방법을 사용하면 아래와 같은 문제가 발생합니다.

오후 11:26:47: Executing ':HellobootApplication.main()'...

> Task :compileJava
> Task :processResources UP-TO-DATE
> Task :classes

> Task :HellobootApplication.main() FAILED

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.7.8)

2023-02-27 23:26:49.370  INFO 3532 --- [           main] t.helloboot.HellobootApplication         : Starting HellobootApplication using Java 17.0.6 on yj_notebook with PID 3532 (C:\git\TID\helloboot\build\classes\java\main started by deter in C:\git\TID\helloboot)
2023-02-27 23:26:49.374  INFO 3532 --- [           main] t.helloboot.HellobootApplication         : No active profile set, falling back to 1 default profile: "default"
2023-02-27 23:26:49.641  WARN 3532 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.context.ApplicationContextException: Unable to start web server; nested exception is org.springframework.boot.web.context.MissingWebServerFactoryBeanException: No qualifying bean of type 'org.springframework.boot.web.servlet.server.ServletWebServerFactory' available: Unable to start AnnotationConfigServletWebServerApplicationContext due to missing ServletWebServerFactory bean
2023-02-27 23:26:49.667 ERROR 3532 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Web application could not be started as there was no org.springframework.boot.web.servlet.server.ServletWebServerFactory bean defined in the context.

Action:

Check your application's dependencies for a supported servlet web server.
Check the configured web application type.


Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.6/userguide/command_line_interface.html#sec:command_line_warnings
3 actionable tasks: 2 executed, 1 up-to-date

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':HellobootApplication.main()'.
> Process 'command 'C:/Users/deter/.jdks/azul-17.0.6/bin/java.exe'' finished with non-zero exit value 1

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 2s
오후 11:26:49: Execution finished ':HellobootApplication.main()'.

제가 생각하기로는 클래스 로더를 통해서 구성 정보를 불러와야 하는데 못 불러오고 있는 것 같습니다.

package tobyspring.config.autoconfig;

import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import tobyspring.config.MyAutoConfiguration;

@MyAutoConfiguration
public class TomcatWebServerConfig {

    @Bean
    public ServletWebServerFactory servletWebServerFactory() {
        return new TomcatServletWebServerFactory();
    }

}

 

이 문제를 해결하기 위해서

  • java 버전 11, 17

  • gradle 버전 7.6, 8.0

  • Build and run 을 Geadle, IntelliJ

  • 파일 경로 수정 등

로 변경하는 방법들을 시도해봤지만 해결하지 못했습니다.

 

현재 제 개발 환경은 아래와 같습니다.

  • IntelliJ버전은 2022.2.3 Community버전

  • spring boot 2.7.8

  • gradle 7.6

어디서 문제가 발생하는지 감을 잡을 수 없어서 문의드립니다.

 

 

 

답변 1

0

토비님의 프로필 이미지
토비
지식공유자

IntelliJ Community 버전을 사용하는 건 예제 동작하는 것에 영향을 주지 않습니다.

외부 파일에 구성정보를 가져오는 단계에서 주의할 점은 파일의 위치와 파일명이 바르게 설정되어있는지 확인하셔야 합니다. 애노테이션 이름과 일치하는 파일이 존재하지 않아도 에러가 나지 않습니다. 그냥 무시되죠. 이 경우에 톰캣 관련 빈이 생성되지 않으니 서블릿 컨테이너를 띄우지 못할 것이고요.

Github에 올려둔 예제를 받아서 비교하면서 파일명과 위치, 애노테이션 이름을 다시 확인해보세요.

아무리해도 안 되면 github에 작업 중인 예제를 공유하시고 알려주시면 제가 확인해보겠습니다.

 

sdyj178님의 프로필 이미지
sdyj178
질문자

문제를 찾았습니다.

META-INF.spring 폴더를 생성할 때, 똑같이 META-INF.spring으로 입력했는데

실제 탐색기에서 찾아보니까 META-INF/spring이 아니라 META-INF.spring이라는 이름으로 만들어졌습니다.

다시 한번 test.test라는 이름으로 생성해 봤는데 resources하위에서는. 을 포함한 test.test폴더명으로 생성되고, java하위에서는. 을 구분해서 test/test 구조로 생성됩니다.

답변해 주셔서 감사합니다.

감사합니다. 상상하지도 못한 이유였는데 저도 도움받았습니다.

JetBrains 제품군이 다그런건지 잘 모르겠지만, 패키지 표현방식에 있어 고정된 방식이 있는듯 합니다. 많이쓰는 VSCode 를 예로들면, 패키지 구분에 dot '.' 대신 slash '/' 구분을 기본으로 합니다. JetBrains 의 IntelliJ 는 지금에서야 다양한 멀티 언어의 IDE 이지만, 추측하기로는 태생이 Java 기반 Kotlin 에 특화된 배경이 있어 계층구조폴더의 압축된 표현을 패키지처럼 dot 표기방식을 기본으로 사용하는 듯 합니다. 저도 이 때문에 불만족스런 부분이 Java 패키지를 제외한, 계층적 폴더는 '/' 구분을 했으면 좋겠다는 아쉬움이 있습니다.

IntelliJ 기준
계층폴더구조 표현방식에서 오는 혼동을 대처하는 2가지 방법

  1. 자신이 생성하는 것이 폴더 인지, 패키지인지 인지한 이후 생성 오더를 내림.
    즉, 일반폴더에서 계층구조 폴더생성을 위해 패키지 작성하듯 dot '.' 을 남발하면,
    aaa.bbb.cc 와 같은 폴더 1개 가 생성됨

  2. 아래 토글옵션 Uncheck : 패키지 표현 꺼짐(단점: 모든 패키지 표현이 계층표현으로 바뀜)

Compact Middle Packages - Uncheck

image

ps. 혹시, 패키지가 아닌 폴더 계층구조 표현을 dot 이 아니라, slash 로 바꾸는 옵션을 알고 계시다면 아래에 남겨주세요.

sdyj178님의 프로필 이미지
sdyj178

작성한 질문수

질문하기