이제 스프링 부트에 대해서 꾸준히 공부해보며 정리한다.
Spring Boot Configuration
앞에서 해봤던 스프링 부트 어플리케이션 설정을 살펴보자. (pom.xml이 나올지 build.gradle이 나올지 내마음)
1 |
|
spring-boot-starter-web
, spring-boot-maven-plugin
등은 아예 버전조차 정의되지 않고 있다. 스프링 부트가 제공하는 의존성 관리 기능 때문이다. 설정에서 <parent>
로 정의된 spring-boot-starter-parent
의 시작 부분을 살펴보면
1 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
또 <parent>
로 spring-boot-dependencies가 정의된 것을 알 수 있다.
이 spring-boot-dependencies의 정의를 보면 <parent>
가 없다.
즉 이 spring-boot-dependencies가 가장 최상위라고 할 수 있다.
중간에 내용을 살펴보면 버전이 정의 되어있음을 알 수 있다.
또 프로퍼티 밑을 보면 <dependencyManagament>
로 해서 각 의존성들이 버전까지 정의 되어 있음을 알 수 있다.
자세히 살펴보면 여기에 사용된 의존성들이 위에 <properties>
에서 정의된 버전 정보를 사용하고 있음을 알 수 있다
즉 스프링 부트에서 관리하고 있는 것들은 버전명시를 안해도 자동으로 버전까지 정의되어서 충돌 걱정을 할 필요가 없다. 이로 인해서 얻을 수 있는 장점은 무엇이 있을까?
- 관리해야할 의존성이 줄어든다.
- 개발 외적의 일이 그만큼 줄어든다는 뜻.
- 뜬금없는 ModelMapper
- 가급적 도메인 활용이 좋겠지만 DTO 사용을 해야할 경우 값 복사 어떻게?
- 보통 일일히 필드 매칭
- modelmapper는 간단하게 이를 커버 가능
- http://modelmapper.org/getting-started/
자동 설정의 이해
위의 예제에서 살펴봤듯이 @SpringBootApplication
한방이면
설정이 완료되었다. how?
1 | //@SpringbootApplication |
@SpringBootConfiguration
은 사실상 Configuration이다.
그리고 스프링 부트의 빈 등록은 두단계라고 할 수 있는데@ComponentScan
을 통해 검색된 빈등록과, @EnableAutoConfiguration
을 통해 검색된 빈의 추가적인 등록이다.
@ComponentScan
은 스프링의 기본 내용이라 패스…
그래도 한번 다시 되집고 가자면@Component
라는 어노테이션이 붙은 클래스들을 빈으로 등록해준다.
@Service, @Controller, @RestController, @Repository
도 @Component에 기반한다.
@ComponentScan
어노테이션이 쓰이는 곳은 아마 @Configuration
이나 @SpringBootConfiguration
이 붙은 컨피규레이션 자바 클래스일텐데
이때 자기 자신도 빈으로 등록한다.
중요한점은 @CompoentScan
은 그 하위로 스캔하기 때문에
상위 패키지나 다른 패키지는 스캔이 안됨을 주의하자
@EnableAutoConfiguration
을 주석처리하면 에러가
발생하는데 ServletWebServerFactory
빈을 찾지 못해서 ServletWebServerApplicationContext
를 시작할 수 없다고 나온다. 즉 저 찾지 못한 ServletWebServerFactory
빈등을 자동으로 등록시켜 주는게 @EnableAutoConfiguration
의 역할이다.
만약 web 형태로 만들지 않는다면 실행을 해볼 수 있다.
밑의 소스 처럼, Application을 static이 아닌 new로 인스턴스 할당한후 .setApplicationType
에 MyApplication.NONE
으로 세팅하고 run해주면 console에서 Spring Boot가 실행 되는 모습을 볼 수 있다.
1 |
|
@EnableAutoConfiguration
은 Spring의 메타파일을 읽어들인다.@EnableAutoConfiguration
의 풀패키지명은org.springframework.boot.autoconfigure.EnableAutoConfiguration
로spring-boot-autoconfigure-<version>.RELEASE.jar
파일을 참조 한다. 해당 jar파일의 META-INF
를 보면 spring.factories
라는 파일이 존재한다.
(이 spring.factories
는 Spring Boot 한정이 아닌 일반적인 Spring Framework에 포함되어 있는 것이다)
spring.factories
를 열어보면 다음과 같이 키가 설정되어 있고
그 키에는 여러개의 컨피규레이션들이 지정되어 있다.
하위에 보면 키 이름이 EnableAutoConfiguration이 있고 하위에 정말 수많은 Configuration 클래스의 이름이 들어 있다. 열어보면 @Configuration
이 붙어 있는 스프링 Configuration 클래스임을 알 수 있다.
@EnableAutoConfiguration
을 사용하면 이 키값의 모든 컨피규레이션을 참조하여 빈을 등록하는 것이다.
그러면 @EnableAutoConfiguration
을 하면 이 수많은 클래스에서 설정한 더 수많은 빈들을 모조리 등록하는 것일까?
결론부터 말하면 No.
일단 EnableAutoConfiguration의 컨피규레이션중 하나를 열어보자.
1 |
|
@Configuration
이 설정되어 있는 WebMvcAutoConfiguration
설정 클래스의 첫 부분이다.
살펴보면 @ConditionalOn
으로 시작하는 어노테이션이 엄청 붙어 있는 것들을 볼 수 있다. @EnableAutoConfiguration
에 설정된 수많은 Configuration
클래스에는 이런식으로 다시 수많은 @ConditionalOn~
어노테이션이 붙어 있으며 여기에 설정된 condition에 따라서 빈이 등록되고 혹은 등록이 되지 않기도 한다.
Configuration 클래스위에 붙어 있는 @ConditionalOn~
어노테이션은
현재 설정 클래스 자체를 사용할지 안할지를 결정하며,
하위 @Bean
에 붙어있는 @ConditionalOn~
어노테이션은
해당 빈을 등록할지 안할지 결정한다.
예를들어서 위 클래스에 설정되어있는
1 |
의 경우
1 | package kr.rkaehdaos; |
위의 예처럼 타입이 Servlet 일때 이 설정 클래스를 사용하라라는 뜻이다.
이런식의 설정이 컨피규레이션 클래스마다 많은 룰로 정의되어 있어서
전부 다 빈으로 등록되는 것은 아니고 필요한 빈들 위주로
등록이 된다는 점을 알아두자.
자동 설정(AutoConfiguration) 이해
자동 설정(AutoConfiguration)의 이해를 위해
커스텀한 자동 설정을 직접 정의하여 프로젝트에서 사용해 보자
Spring Boot 의 모듈 프로젝트는 보통 2가지 프로젝트로 나눈다.
- XXX-Spring-Boot-AutoConfigure 모듈 : 자동설정
- XXX-Spring-Boot-Starter 모듈 : 필요한 의존성 정의
자동 설정은 위 2가지중 AutoConfigure에 넣는것이 일반적이다.
내용이 작을 경우 굳이 분리하지 않고 XXX-Spring-Boot-Starter만 만들고 AutoConfigure 부분도 안에 그냥 써준다.
starter는 pom파일이 핵심이라 보통 소스코드가 없는 경우가 많다.
내용이 작은 경우 Starter하나만 만들고 Auto부분도 다 넣어버리면 된다.
일반적으로 실제 개발에서
현재 만드는 이 프로젝트는 자동설정의 타겟이 되는 타겟 프로젝트이며
이 프로젝트에서 만드는 클래스들(여기선 Person하나)은
실제적으로 다른 프로젝트에서 참조하는 라이브러리가 될 것이다.
구현 방법
1. 의존성 추가
1 |
|
맨처음 포스트에서 봤던 <parent>
의 상속을 쓰지 않고spring-boot-dependencies
를 이용하던 방법을 이용하여 의존성을 설정 하였다.
의존성 추가후 다음 스텝으로 넘어가기전에
자동설정을 지정할 타겟 클래스를 만들어본다. Person을 예로 들어보자
1 | package me.rkaehdaos; |
이름과 나이를 멤버로 갖는 Person 클래스에 Getter/Setter와 toString까지만 만든 상태다.
2. @Configuration
파일 작성
1 | package me.rkaehdaos; |
Person타입의 Bean을 리턴하는 설정 파일을 만들었다.
3. src/main/resource/META-INF에 spring.factories 파일 만들기
src/main/resource/META-INF에 spring.factories 파일을 생성한다.
IDE 사용중이면 resource까진 있을테니 밑에 META-INF 폴더 생성후 파일을 만든다.
이 파일은 스프링 부트 전용이 아닌 스프링 프레임워크에 원래 사용되는 파일이다.
이펙티브 자바의 service Provider참조
4. spring.factories 안에 자동 설정 파일 추가
아까 만들었던 설정파일을 명시적으로 지정한다.
1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ |
이러면 앞에서 봤던것처럼 스프링의 EnableAutoConfiguration이 켜져있으면
알아서 위에 추가한 자동설정 파일을 읽게 된다.
5. mvn install
maven install plugin은 install phase에서 동작하는 플러그인으로
local repository에 artifact를 추가하는데 사용된다.
maven deploy plugin은 deploy phase에서 동작하는 플러그인으로
remote repository에 artifact를 올리는 역할
mvn install 하면 build 플러그인후 install 플러그인이 실행된다.
이러면 위의 프로젝트가 jar로 묶인후 나의 로컬 repo(기본적으로 개발자 pc)
에 올라가게 되며 이제 다른 프로젝트에서
이 프로젝트를 참조하여 사용할 수 있게 된다.
맨위에서 만들었던 Application1에서 사용해보자.
Application1의 의존성관리에 방금 만든 프로젝트를 추가해보자
방금만든 프로젝트(person포함한)의 pom.xml을 열어보면
맨위에 나온 artifactId와 groupId가 있는데 이것을 사용할
프로젝트(Application1)의 pom.xml의 의존성 관리에 추가한다.
1 | <!--의존성부분만 보면--> |
이렇게 하면 왼쪽의 External Lib(IDE에 따라서 maven Lib)에 내가 만든 프로젝트가
참조 됨을 알 수 있다.
Application1의 메인 메소드에 application타입을 WebApplicationType.NONE
로 설정해서 로딩이 좀더 빠르게 해보자.
1 | package me.rkaehdaos; |
타겟(Person)의 확인을 위해 ApplicationRunner 구현 클래스를 하나 만든다.
1 | package me.rkaehdaos; |
이제 실행해보면 Application1의 스프링부트가 실행되면서
ApplicationRunner에 의해 Person에 대해 println하게 된다.
보면 타겟프로젝트 자동설정에서 세팅한 대로
빈에 값이 들어가 있는 것을 볼 수 있다.
빈 설정 오버라이딩 문제
사실 여기에 문제가 있는데 다음과 같이 새빈을 등록시킨다고 가정하자.
1 | package me.rkaehdaos; |
이렇게 코드를 만드는 개발자는 빈설정이 오버라이딩 되서
새로운 설정에 따른 빈이 생성됨을 기대할 것이다.
허나 결과는 앞과 동일하게 자동생성에 만든대로 빈이 나온다.
즉 새로 작성한 빈 코드가 무시가 된다. 왜그럴까?
맨 위의 자동설정의 이해에서..@SpringbootApplication
은 다음의 페이즈의 묶음이라고 하였다.
@SpringBootConfiguration
//사실상 컨피규레이션@ComponentScan
//빈 리딩 1step@EnableAutoConfiguration
//빈 리딩 2step
위에서 보이듯이 @ComponentScan
가 먼저 이뤄지기 떄문이다.
이 빈리딩 1step에서 내가 Application1에 생성한 Bean이 만들어진 후
그다음의 2step에서 자동설정의 빈이 불러와서 1step에서 만들었던 빈을
덮어씌운것이다. 즉 개발자의 의도와 정 반대로
내가 만든 빈 설정이 라이브러리의 자동설정의 빈설정이 덮어 씌웠다.
이것을 어떻게 해결할 수 있을까?
이것은 자동 설정쪽에 하나만 추가 해주면 된다.
1 | package me.rkaehdaos; |
@ConditionalOnMissingBean
위에서 스프링 부트의 설정 클래스를 열었을때 붙어있는 수많은 @Conditional~
어노테이션을 기억하는가? 그중에서 @ConditionalOnMissingBean
를 @Bean
에 붙었다.
이는 빈 설정에 적용이 되며 해당 빈이 없을때에만 이 설정이 작동이 된다.
위처럼 선택하고 다시 mvn install
하면 이제 정상적으로 새로 만든 빈 설정이 적용된다.
1step에서 생성된 새로 설정된 빈이 2step에서 저 어노테이션을 만나고
그시점에서 해당 타입의 빈이 이미 1step에서 생성되었으므로 넘어가게 되는 것이다.
자 이제 빈 설정 오버라이딩 문제가 해결되었다.
그런데 꼭 빈 설정을 오버라이딩 해야하는 것일까?
빈 재정의 간소화
현재 코드에서는 @Bean
이 붙은 Person 빈을 리턴하는 메소드를 똑같이 붙여넣었다.
그런데 이러면 중복코드가 된다. 예제처럼 짧지 않고 빈생성 메소드가 엄청 길다면?
그리고 그런 메소드가 수십개가 된다면?? 전부 복사해서 붙여야할까?
만약 자동설정의 설정대로 빈 설정후 setter만 실행해서 내가 원하는 값을 set할 수
있다면?
만약에 프로퍼티파일에 우리가 원하는 값을 세팅해놓고 자동설정에서 프로퍼티를 참조해서
우리가 원하는 값을 찾으면 그값으로 세팅하고 빈을 등록 할 수 있게 된다면?
프로퍼티파일 생성
스프링 부트는 application.properties 파일을 이용해서 설정을 제공한다.
스프링 부트가 제공하는 프로퍼티를 설정 하는 파일이지만 커스텀한 프로퍼티도
설정이 가능하다.
1 | Person.name = Ahn_Properties |
properties keyvalue auto complete
위의 프로퍼티에는 새로운 빈 설정 값만 프로퍼티로 들어가 있다.
이 커스텀 프로퍼티를 사용하는 방법들이 다수 존재하는데
설정 프로퍼티 클래스를 사용하면 관련 설정을 한 클래스에서 관리할 수 있어서 편하다.
설정 프로퍼티 클래스 생성(ConfigurationProperties class)
먼저 설정 프로퍼티로 사용할 클래스를 생성한다.
1 | package me.rkaehdaos; |
설정 프로퍼티로 사용할 PersonProperties 클래스를 생성하였다.
클래스에 @ConfigurationProperties
를 붙인 후application.properties
에서 사용할 접두어(prefix)를 정한다.
설정 프로퍼티 클래스에는 파일 속의 프로퍼티 값을 전달받을 Setter와
프로퍼티 참조시 사용할 getter가 필요하다.
application.properties의 프로퍼티는 다음과 같이 매칭된다.
application.properties 프로퍼티 이름 = prefix + “.” + setter 프로퍼티 이름
위처럼 하면 인텔리 J에서 에러가 나며 다음 문서로 연결된다.
Spring Boot Configuration Annotation Processor not found in classpath
해석 그대로 해당 스프링 부트 어노테이션 프로세서를 못찾았으니
의존성에 추가해달라는 이야기
1 | <dependency> |
적용하면 에러가 사라진다.
@ConfigurationProperties
를 적용한 클래스를 만들었다면,
다음 할 일은 빈으로 등록하는 것이다.
스프링 빈으로 등록하는 방법은 두 가지가 있다.
- 설정 프로퍼티 클래스에
@Configuration 적용하기
(또는 설정 프로퍼티 클래스를@Bean
으로 등록하기) @EnableConfigurationProperties
을 이용해서 지정하기
1번의 방법은 설정 프로퍼티 클래스를 빈으로 등록하는 방법이다.@Configuration
이 붙어있으면 콤포넌트 스캔시 빈으로 등록된다.
스프링부트는 해당 빈에 @ConfigurationProperties
가 적용되어 있다면
프로퍼티값을 할당해 준다.
여기는 자동설정 공부이므로 2번 방법으로 한다.
@EnableConfigurationProperties
을 설정 클래스에 추가,
설정 클래스(여기서는 PersonConfiguration)에 @EnableConfigurationProperties
를 추가한다.
어노테이션의 값에는 @ConfigurationProperties를 적용한 클래스를 지정한
설정 프로퍼티 클래스(여기선 PersonProperties)를 지정하면 된다.
이 경우 @EnableConfigurationProperties
는 해당 클래스를 빈으로 등록하고
프로퍼티 값을 할당한다.
1 | package me.rkaehdaos; |
클라이언트 프로젝트에서 refresh후 사용해보자
위의 설정이 모두 끝난 상태라면
인텔리J엔터프라이즈 버전인 경우 properties도 자동완성이 가능하다.
인텔리J에서 프로퍼티 인코딩을 UTF-8로 해도 한글이 깨지는 경우
File Encoding에서 밑에 보면 properties 따로 체크 하는 부분이 나온다.
여기서 Transparent native-to-ascii conversion을 체크하면 한글이
올바로 표시된다.
\0A등의 문자표로 저장이 되더라도 보여지기는 한글이나 아스키로 보여지게
하는 옵션이다.
내장 웹 서버의 이해
스프링 부트는 서버가 아니다.
스프링 부트 실행시 자동으로 뜨는 서버를 보고 서버인 줄 착각하면 안된다.
스프링 부트는 서버가 아니다.
코드상에서 톰캣실행시 다음의 7단계가 필요하다.
- 톰캣 객체 생성
- 포트 설정
- 톰캣에 컨텍스트 추가
- 서블릿 만들기
- 톰캣에 서블릿 추가
- 컨텍스트에 서블릿 맵핑
- 톰캣 실행 및 대기
이해를 위해 위의 단계를 수동으로 했다고 생각하자.
1 | package me.rkaehdaos.springbootstudyembeddedtomcat; |
위 코드를 실행하고 브라우저에서 /hello로 접근하면 서블릿 응답을 볼 수 있다.
이 모든 과정을 보다 상세히 또 유연하고 설정하고 실행해주는게
바로 스프링 부트의 자동 설정이다.
역시 org.springframework.boot.autoconfigure
안의 spring.factories
를
보면 설정파일 키값중 org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration
키가 존재한다. 해당 설정 클래스를 살펴보면 서블릿 웹서버 생성을 설정하는 것을 확인 할 수 있다. 살펴보면 TomcatServletWebServerFactory
를 참조하는 것을 확인할 수 있는데 이부분을 보면 앞에서 만들었던 비슷하게 톰캣을 생성한후 커스터마이징을 하는 것을 알 수 있다.
그러면 서블릿등록 부분은 어디 있을까?
일반적으로 많이 쓰이는 웹 MVC 구조를 위해선
첫단에 DispatcherServlet이 필요하다.(프론트 컨트롤러 패턴)
역시 spring.factories
의 org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration
키값을 찾아가면 설정 클래스를 확인할 수 있다. 클래스 내용을 보면 해당 클래스에서 dispatcher 서블릿을 만들고 클래스에 등록하는 부분이 설정 되어 있음을 확인할 수 있다.
이처럼 컨테이너 생성과 서블릿 등록이 분리되어 있기 떄문에
컨테이너 생성과 서블릿등록이 서로 의존되지 않고 각자 설정이 가능하다.
컨테이너와 포트
1) 다른 컨테이너로 변경
스프링부트의 기본 컨테이너는 톰캣임을 의존성에서 확인할 수 있다.
이는 앞에서 살펴보았던 자동 설정에 의해서 (ConditionalOnClass)
톰캣용 자동 파일이 읽어지게 되는 것이다.
참조 레퍼런스 : https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-web-servers.html
pom.xml에 설정했던 spring-boot-starter-web
은 spring-boot-starter-tomcat
를 포함하기 때문에 톰캣을 포함하게 된다. 이 톰캣을 exclude하고 spring-boot-starter-jetty
나 spring-boot-starter-undertow
를 대신 사용할 수 있다.
1 | <dependency> |
2) web server 사용하지 않기
위에서 해봤던 것처럼 SpringApplication에서
1 | application.setWebApplicationType(WebApplicationType.NONE); |
해서 웹서버를 사용하지 않기도 했다.
하지만 이렇게 코드에 써놓을 필요없이 프로퍼티만으로도 가능하다.
1 | spring.main.web-application-type=none |
3) port 변경
standalone 어플리케이션에서 메인 HTTP port는 8080이 기본이다. 바꿀떄는
1 | server.port=7070 |
0을 지정하면 random port로 서버를 올릴때마다 포트가 바뀐다.
4) 런타임시 포트 알아내는 법
프로그램 코드내에서 포트 정보가 필요한 경우 만약 랜덤포트나 특정 주입등으로
포트가 결정 되는 경우에 어떻게 얻어야할까?
가장 쉬운 방법은 콘솔에 찍힌 로그를 확인하는 것이다.
하지만 위 참조에서 보듯이 가장 최선의 방법(Best way)은 ApplicationListener<ServletWebServerInitializedEvent>
타입의 빈을 등록 후
가져오는 것이다.
ApplicationListener 인터페이스를 통해 이벤트를 수신할 수 있는 데 수신한 이벤트는 ServletWebServerInitializedEvent
다. 이 이벤트는 스프링 부트에서 ApplicationContext
가 갱신되고 WebServer
가 ready되었을 때 publish된다.
1 | package me.rkaehdaos; |
내장 웹서버에서 HTTPS와 HTTP2 사용하기
HTTPS 설정하기
키스토어 만들기
1 | keytool -genkey \ |
1 | server.ssl.key-store: keystore.p12 |
스프링 부트는 기본적으로 하나의 커넥터만 등록이 되는데
그 커넥터에 SSL이 적용되게 된다.
이제 http로 하면 400에러 뜨고 https로만 접속이 된다.
https접속하면 인증서 신뢰에 관한 에러가 뜨게 된다.
지금 사용한 인증서는 브라우저가 가지고 있는 CA의 pub키가
아니기 때문에 당연히 뜨는 것이다.
무시하고 들어가는것을 선택하면 이제 만들어놓은 사이트에 접속이 된다.
참조: curl 사용법 (https://www.lesstif.com/pages/viewpage.action?pageId=14745703)
1 | curl -I http://localhost:8080 |
하나인 커넥터가 https가 되었기 떄문에 http를 사용 할 수 없어서
http 시 400 에러가 뜨고 https로 접속하면 인증서 신뢰에 대한 오류 가 뜬다.
이를 무시하기 위해 k옵션을 붙이면 정상적으로 200이 뜬다.
현재 http2가 아니므로 htt2옵션을 보내도 헤더가 HTTP/1.1인 것을 알 수 있다.
만약 http와 https를 동시에 사용하려면?
커넥터를 하나 만들어서 추가하면 된다.
1 | package me.rkaehdaos.springbootsslhttp2test; |
위처럼 8080 포트를 사용하는 커넥터를 추가한다.
원래 https를 사용하는 기본 커넥터는 8443으로 바꾼다.
1 | server.port=8443 |
이렇게 하면 http(8080),https(8443) 둘다 사용이 가능하다.
http2 사용하기
https://developers.google.com/web/fundamentals/performance/http2/?hl=ko
https://www.popit.kr/%EB%82%98%EB%A7%8C-%EB%AA%A8%EB%A5%B4%EA%B3%A0-%EC%9E%88%EB%8D%98-http2/
(HTTP/2를 사용하려면 SSL은 적용이 되어있어야 함을 명심하자.)
스프링 부트 어플리케이션에서 server.http2.enabled
설정으로
HTTP/2 사용을 가능하게 할 수 있다. 어떤 컨테이너를 사용하느냐에 따라서
이후 제약사양이 달라진다.
- 제약사양
- Undertow: 아무런 추가 설정이 필요 없다.
- tomcat: 조올라복잡하다..쓰지말자..
다만 링크 밑에 보면 알듯이 tomcat 9.0.x와 JDK9이상을 사용하는 경우에는 설정없이 가능하다.
()그러니 이경우가 아니면 톰캣에서 HTTP/2를 사용하는 것은 지양하자.)
1 | <properties> |
인텔리 J에서 platform jdk만 9로 바꿔주면 되는 것이 아니라
modules의 dependency도 9버전으로 올려줘야함을 명심하자.
독립 실행 가능한 JAR
스프링 부트 보다는 maven 플러그인에 더 가까운 내용이다.
간단한 스프링 예제 만든후 mvn package
를 하면 target 안에 jar파일이 생기는데
이를 java -jar <jar파일이름>.jar
를 하는 것만으로도 스프링 부트 어플리케이션의
실행이 가능하다. 크기는 아마 16메가정도로 기억된다.
그럼 안의 내용은 어떻게 되는가? 내가 만든 클래스는 다 포함이 되어 있겠지만
나머지 그 수많은 의존성파일들도 다 jar에 lib로 포함이 되어있다.
그래서 과거에는 “uber”jar를 사용하였다.
uber jar라는 것은 의존성 및 어플리케이션을
jar파일 하나로 압축하는 방법이다.
이렇게 되면 무슨 라이브러리를 쓰는 것인지 뭐가 어디에서 오는 것인지 알 수가 없다.
특히 내용이 다른데 이름이 같은 파일의 경우에는 처리가 어렵다.
이런 까닭은 바로
자바에는 jar를 읽을 수 있는 표준 방법이 없기 때문이다.
스프링 부트는 내장 Jar로 Jar 파일안에 Jar를 묶어놓고
어플리케이션 클래스와 라이브러리 위치를 분리한다.
그리고 그걸 읽을 수 있는 기능을 추가하였다.
만들어진 jar를 보면org.springframework.boot.loader
가 있는 부분이 바로 그것이다.org.springframework.boot.loader.jar.JarFile
을 사용해 내장 JAR를 로딩한다.org.springframework.boot.loader.Launcher
를 사용해서 실행한다.
위의 경우에는 Jar파일이라 JarLaunch를 사용해서 실행하게 된다. 실제로 jar파일의
MANIFEST.MF 파일을 보면 메인 클래스에org.springframework.boot.loader.JarLauncher
로 되어 있음을 볼 수 있다.
1 | Manifest-Version: 1.0 |
JarLauncher는 Start-Class로 정의된 내가 만든 클래스를 타겟으로 실행을 하게 된다.
이 독립적으로 실행가능한 어플리케이션을 만드는 것도 스프링 부트의 특징이다.
원리 정리
- 의존성 관리
- 스프링 부트 스타터 덕분에 의존성 내용이 엄청 줄었다.
정말 조금만 적어도 알아서 다 가져온다.
- 스프링 부트 스타터 덕분에 의존성 내용이 엄청 줄었다.
- 자동 설정
@EnableAutoConfiguration
로 자동 설정을 읽어오는 부분 기억하자.- 자동설정을 이용해서 개발자가 재정의하거나 설정해야할 부분을 최대한 줄여보자.
- 내장 웹 서버
- 이것도 스프링 부트의 goal의 하나인 독립 실행 가능한 어플리케이션에 이바지
- 톰캣,제티,언더토우, 얼마든지 커스터마이징 할 수 있음을 기억하자.
- 독립적 실행 가능한 Jar
- 이것도 독립 실행 가능한 어플리케이션에 이바지한다.
- 위에서 봤다시피 라이브러리와 어플리케이션을 구분해서 완전한 관리가 가능하다.
Related POST
- [Spring Boot] 13. Spring REST Client
- [Spring Boot] 12. Spring Security
- [Spring Boot] 11. Spring Data
- [Spring Boot] 10. 스프링 웹 MVC-2: Spring HATOAS, CORS
- [Spring Boot] 9. 스프링 웹 MVC-1:
- [Spring Boot] 8. Spring-Boot-Devtools
- [Spring Boot] 7. 테스트(Testing)
- [Spring Boot] 6. 로깅(Logging)
- [Spring Boot] 5. Profiles
- [Spring Boot] 4. 스프링부트 외부설정
- [Spring Boot] 3. 스프링부트 핵심기능
- [Spring Boot] 2. 스프링부트 이해
- [Spring Boot] 1. 스프링부트 시작