์คํ๋ง ๋ถํธ ์ธ๋ํ ์ฐ
์ธํ ๋ฆฌ์ ์ด ๋๋ ์คํ๋ง ์ด๋์ ๋ผ์ด์ ๋ฅผ ํตํด ์คํ๋ง ๋ถํธ ํ๋ก์ ํธ๋ฅผ ๊ฐ๋จํ๊ฒ ์์ฑํ ์ ์๋ค. ์คํ๋ง ์ด๋์ ๋ผ์ด์ ๋ฅผ ํตํด ๋ง๋ค๊ณ ์ ํ๋ ํ๋ก์ ํธ์์ ํ์ํ ๋ชจ๋์ ์ฝ๊ฒ ์ ํํ ์ ์๊ฒ ์ง์ํ์ง๋ง ์ธ๋ถ์ ์ธ ๋ชจ๋์ ์ ํ์ ์ง์ํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ง๋ค์ด์ง ํ๋ก์ ํธ๋ฅผ ์์ ํด์ผํ ํ์์ฑ์ด ์๊ธธ ์ ์๋ค. ์ํ์น ํฐ์บฃ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ง์ํ๋ ๊ธฐ๋ณธ ์ปจํ ์ด๋๋ก์จ ์ถฉ๋ถํ ์ ์ฆ๋ ๊ธฐ์ ์ด์ง๋ง ํ์ฌ ์กฐ์ง๊ณผ ๊ฐ์ด ์ผ๋ถ ์ค๋ฌด ํ๋ก์ ํธ์์๋ ์ธ๋ํ ์ฐ๋ฅผ ์ฌ์ฉํ๋ ํธ์ด๋ค.
configurations.configureEach {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-websocket'
implementation 'org.springframework.boot:spring-boot-starter-undertow'
}
์ ์์์์ spring-boot-starter-websocket ๋ชจ๋์ ์ํด spring-boot-starter-web์ ๋ช ์ํ ํ์๊ฐ ์๋ค.
WebSocketDeploymentInfo ๊ฒฝ๊ณ ๋ก๊ทธ ์์ ๊ธฐ
spring-boot-starter-websocket ๋ชจ๋์ ์ถ๊ฐํ๋ฉด ์๋์ฒ๋ผ WebSocketDeploymentInfo๊ฐ ์ค์ ๋์ง ์์ ๊ธฐ๋ณธ ๋ฒํผ ํ์ด ์ฌ์ฉ๋๋ค๋ ๊ฒฝ๊ณ ๋ก๊ทธ๊ฐ ์ถ๋ ฅ๋๋ค. ๋ก๊ทธ ๋ ๋ฒจ ์กฐ์ ์ ํตํด ๋ฌด์ํด๋ ๋์ง๋ง WebServerFactoryCustomizer๋ฅผ ํตํด์ WebSocketDeploymentInfo๊ฐ ๋ฑ๋ก๋๋๋ก ๊ตฌํํ ์ ์๋ค.
2023-03-16T21:49:43.249+09:00 WARN 35488 --- [main] io.undertow.websockets.jsr : UT026010: Buffer pool was not set on WebSocketDeploymentInfo, the default pool will be used
@Component
public class UndertowWebsocketCustomizer implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
private final ServerProperties.Undertow undertow;
public UndertowWebsocketCustomizer(final ServerProperties serverProperties) {
this.undertow = serverProperties.getUndertow();
}
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addDeploymentInfoCustomizers(deploymentInfo -> {
boolean direct = this.undertow.getDirectBuffers() != null && this.undertow.getDirectBuffers();
int bufferSize = this.undertow.getBufferSize() != null ? (int) this.undertow.getBufferSize().toBytes() : 1024;
WebSocketDeploymentInfo webSocketDeploymentInfo = new WebSocketDeploymentInfo();
webSocketDeploymentInfo.setBuffers(new DefaultByteBufferPool(direct, bufferSize));
deploymentInfo.addServletContextAttribute("io.undertow.websockets.jsr.WebSocketDeploymentInfo", webSocketDeploymentInfo);
});
}
}
HTTPS ํฌํธ๋ก ๋ฆฌ๋ค์ด๋ ํธ
์ด์ ๋ AWS ELB์ ๊ฐ์ ๋ก๋๋ฐธ๋ฐ์ ๋๋ ์์ง์์ค์ ๊ฐ์ ์น ์๋ฒ๋ค์ ํตํด์ ๋ฆฌ๋ฒ์ค ํ๋ก์๋ฅผ ๊ตฌ์ฑํ๋ฏ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด HTTP/2๋ฅผ ์ง์ํ๋๋ก ๊ตฌ๋ํ์ง ์๋ ํธ์ด์ง๋ง TLS ์คํ๋ก๋๊ฐ ํ์ํ๋ค๋ฉด ์๋์ ๊ฐ์ด HTTP๋ก ์ฐ๊ฒฐ๋์์๋ HTTPS๋ก ์ฐ๊ฒฐ๋๋๋ก ๊ตฌ์ฑํ ์ ์๋ค.
@Component
public class UndertowHttp2Customizer
implements WebServerFactoryCustomizer<UndertowServletWebServerFactory> {
private final ServerProperties serverProperties;
private final int httpPort;
public UndertowHttp2Customizer(final ServerProperties serverProperties,
final Environment environment) {
this.serverProperties = serverProperties;
this.httpPort = environment.getProperty("server.http-port", Integer.class, 8080);
}
@Override
public void customize(UndertowServletWebServerFactory factory) {
factory.addBuilderCustomizers(builder -> builder.addHttpListener(this.httpPort, "0.0.0.0"));
factory.addDeploymentInfoCustomizers(deploymentInfo -> deploymentInfo.addSecurityConstraint(
new SecurityConstraint()
.addWebResourceCollection(new WebResourceCollection().addUrlPattern("/*"))
.setTransportGuaranteeType(TransportGuaranteeType.CONFIDENTIAL)
.setEmptyRoleSemantic(SecurityInfo.EmptyRoleSemantic.PERMIT))
.setConfidentialPortManager(exchange -> serverProperties.getPort()));
}
}