[강의요약] 스프링부트 개념과 활용 - 3부 스프링 부트 원리 (2/2)
개인적인 학습을 위한 inflearn - 스프링부트 개념과 활용(백기선) 강의 요약입니다.
개념과 원리 위주로 요약합니다.
https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81%EB%B6%80%ED%8A%B8/dashboard
이전 글 에서 이어집니다.
3부 - Springboot 원리
6. 내장 웹 서버 이해
6-1. 스프링 부트는 웹 서버가 아니다. (톰캣, 네티 등이 웹서버) application.setWebApplicationType(WebApplicationType.NONE); 만 봐도 알 수 있다
6-2. tomcat 을 띄우기
public class Application {
public static void main(String[] args) throws LifecycleException {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
Context context = tomcat.addContext("", "/");
HttpServlet servlet = new HttpServlet() {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
PrintWriter writer = resp.getWriter();
writer.println("<html><head><title>aaa</title></head>");
writer.println("<body><h1>Hello Tomcat!</h1></body>");
}
};
String servletName = "helloServlet";
tomcat.addServlet("", servletName, servlet);
context.addServletMappingDecoded("/hello", servletName);
tomcat.start();
tomcat.getServer().await(); // 요청을 기다린다
}
}
6-3. 내장 웹서버를 띄우는 것도 자동 설정의 기능
- 톰캣 만들기, 서블릿 만들기, web mvc 등
spring-boot-autoconfiguration > META-INF > spring.factories
spring-boot-autoconfiguration > ServletWebServerFactoryAutoConfiguration : 서블릿 웹 서버 생성
DispatcherServletAutoConfiguration : http 서블릿을 상속해서 만든 스프링 서블릿. 얘는 소스에 따라 잘 안 바뀌어서 빼둠
7. 내장 웹 서버 응용 1부 : 컨테이너와 포트
자동 설정에 의해 톰캣용 자동 설정이 읽혀짐 -> 톰캣이 컨테이너로 올라간다.
7-1. 다른 서블릿을 쓰고 싶다면?
- 톰캣 의존성 제거
- spring-boot-starter-web > org.springframework.boot:spring-boot-starter-tomcat exclusion
- 제거 후 실행하면 웹 어플리케이션으로 올라가지 않음
- 다른 컨테이너 의존성 추가
- org.springframework.boot:spring-boot-starter-jetty dependency 추가
- jetty, undertow
7-2. 프로퍼티를 사용한 설정값 변경
- 어플리케이션 타입 변경 : spring.main.web-application = none
- 포트 변경 : server.port = 7070 (0을 주면 랜덤으로 사용할 수 있는 포트가 할당)
- 설정된 포트 확인 방법 : ApplicationListener로 ServletWebserverInitializedEvent를 받아와서 확인 가능
8. 내장 웹 서버 응용 2부 : HTTPS와 HTTP/2
HTTPS
키스토어 -> ssl -> https
8-1. 키스토어 생성
$ keytool -genkey -alias spring -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 4000 22:56:33
키 저장소 비밀번호 입력:
새 비밀번호 다시 입력:
이름과 성을 입력하십시오.
[Unknown]: Cherrue
조직 단위 이름을 입력하십시오.
[Unknown]: CHERRUE
조직 이름을 입력하십시오.
[Unknown]: CEO
구/군/시 이름을 입력하십시오?
[Unknown]: Seoul
시/도 이름을 입력하십시오.
[Unknown]: Seoul
이 조직의 두 자리 국가 코드를 입력하십시오.
[Unknown]: KR
CN=Cherrue, OU=CHERRUE, O=CEO, L=Seoul, ST=Seoul, C=KR이(가) 맞습니까?
[아니오]: Y
$ ls
keystore.p12 pom.xml src
application.properties 에 정보 작성
# application.properties
server.ssl.key-store=keystore.p12
server.ssl.key-store-type=PKCS12
server.ssl.key-store-password=123456
server.ssl.key-alias=spring
8-2. 실행
https://localhost:8080 로 접속하면 비공개 설정이라고 빨간 화면을 띄움
브라우저가 공식 인증서가 아니라서 표시하는 위험 표시. 고급에 그래도 접속하기 버튼을 눌러서 들어감
$ curl -I -k https://localhost:8080/hello
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
Date: Fri, 28 Jan 2022 14:18:08 GMT
8-3. http2가 무시되었네?
기본 커넥터가 하나라서 https를 설정하면 http/2를 주어도 https만 된다. 커넥터를 두 개 사용하도록 설정해보자
# application.properties
server.port = 8443
@SpringBootApplication
@RestController
public class Application {
@GetMapping("/hello")
public String hello() {
return "Hello Spring!\n";
}
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Bean
public ServletWebServerFactory serverFactory() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
tomcat.addAdditionalTomcatConnectors(createStandardConnector());
return tomcat;
}
private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.setPort(8080);
return connector;
}
}
결과
❯ curl -I --http2 https://localhost:8443/hello -k 23:26:17
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
Date: Fri, 28 Jan 2022 14:26:21 GMT
❯ curl -I --http2 http://localhost:8080/hello -k 23:26:21
HTTP/1.1 200
Content-Type: text/plain;charset=UTF-8
Content-Length: 14
Date: Fri, 28 Jan 2022 14:26:31 GMT
HTTP/2
http/2를 쓰려면 ssl은 적용이 꼭 되어있어야 함
8-4. connector 설정 bean은 제거하고 application.properties에 설정 추가
# application.properties
server.http2.enabled=true
Undertow는 위 설정만 해주면 바로 됨. tomcat8.X대는 복잡하다.(java9 + tomcat9 이상이면 괜찮다)
8-5. undertow로 내장 웹서버 변경
// pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
</dependencies>
결과
❯ curl -I --http2 https://localhost:8443/hello -k 23:39:55
HTTP/2 200
content-type: text/plain;charset=UTF-8
content-length: 14
date: Fri, 28 Jan 2022 14:39:57 GMT
9. 톰캣 + HTTP2 적용
9-1. pom.xml
- java.version = 9
- tomcat.version = 9.0.10 (9.X 이상 버전)
9-2. intellij 설정
- Project Structure > Project Settings > Project > Project SDK : 9(java version “9”)
- Project Structure > Project Settings > Modules > Dependencies 탭 > Module SDK : 9(java version “9”)
10. 독립적으로 실행 가능한 JAR
mvn clean : 메이븐 하위의 파일 삭제
mvn package : 패키징 (jar로 만드는 것)
- mvn package -DskipTests : 테스트 스킵
- java -jar
만들어진 파일.jar
- dependencies가 하나의 jar에 다 들어간다 그 jar를 읽을 수 있는 loader가 같이 말린다 경로 : org/spring/framework/boot/loader/*
- main을 실행하는 것 = JarLauncher. WarLauncher, PropertyLauncher 도 있음 MANIFEST.MF > Main-Class 가 Start-Class 를 읽어서 실행 MANIFEST.MF > Main-Class를 읽는 것은 Java의 스펙. 그 뒤를 스프링이 추가한 것
11. 스프링 부트 원리 정리
11-1. 의존성 관리
- spring-boot-starter-web : 스프링 부트 의존성 관리
- Parent > spring-boot-parent > spring-boot-dependencies : 진짜 의존성 관리 내역
- parent VS pom.xml 에서 dependency 로 추가하는 것은 완전히 다르다.
11-2. 자동 설정
- @SpringBootApplication
- @EnableAutoConfiguration : 2단계. spring.factories (@ConditionalOnMissingBean 등의 조건을 보고 설정)
- @ComponentScan : 1단계. 소스코드의 @Component 등
11-3. 내장 웹서버
- 스프링 부트는 독립적으로 실행되는 것이 목표 : 내장 웹서버(default Tomcat) 을 가진다.
- 스프링부트는 서버가 아니다. Auto Configuration으로 설정한 웹 서버를 이용함
댓글남기기