FeelingXD

[Spring] 스프링 웹서버 멀티 포트로 열기 본문

프로그래밍/Spring

[Spring] 스프링 웹서버 멀티 포트로 열기

FeelingXD 2024. 9. 14. 00:25

멀티 포트의 필요성

대부분의 경우에선 그렇지 않겠지만 서버를 여러포트로 지원해야할 때가있다.

예를들어 https 와 http 둘 모두를 지원해야한다면 두개의 경우를 생각해서 포트를 구성해야한다.

코드

// kotlin 코드입니다. :)
package com.feelinxd.app.config

import org.apache.catalina.Context
import org.apache.catalina.connector.Connector
import org.apache.tomcat.util.descriptor.web.SecurityCollection
import org.apache.tomcat.util.descriptor.web.SecurityConstraint
import org.springframework.beans.factory.annotation.Value
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory
import org.springframework.boot.web.servlet.server.ServletWebServerFactory
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class ServerConfig {

    @Value("\${server.http.port}")
    val httpPort: Int = 0

    @Value("\${server.port}")
    val httpsPort: Int = 0

    @Bean
    fun servletWebServerFactory(): ServletWebServerFactory {
        val tomcat = object : TomcatServletWebServerFactory() {
            override fun postProcessContext(context: Context) {
                super.postProcessContext(context)
                val securityConstraint = SecurityConstraint().apply {
                    userConstraint = "CONFIDENTIAL"  // ssl를 강제로 설정한다.
                    addCollection(SecurityCollection())
                }
                context.addConstraint(securityConstraint)
            }
        }

        tomcat.addAdditionalTomcatConnectors(createHttpConnector())
        return tomcat
    }

    private fun createHttpConnector(): Connector { // http 커넥터에 대한 정의 
        val connector = Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL)
        connector.scheme = "http" // 사용할 프로토콜 http 
        connector.port = httpPort 
        connector.secure = true
        connector.redirectPort = httpsPort
        return connector
    }
}
// application.yml
server:
  port: 8443  // ssl 서버 사용을 위해 443 포트를 명시
  http:
    port: 8080 // http 프로토콜을 사용할 포트 명시
  ssl:
    enable: true
    key-store: classpath:keystore.p12
    key-store-type: PKCS12
    key-store-password: changeit

Spring boot 에서 필요한 클래스가 없어요 ! 🤔

Spring-boot-starter 를 사용해서 의존성을 주입 받았다면 위의코드를 그대로 사용할때

org.apache.catalina.~ 패키지 관련 문제가 생길수 있다. springboot 에서는 embedded-tomcat 을 지원하고있지만 사용할 톰캣 서버를 세세 하게 설정하려면 gradle 기준으로 다음 패키지 의존성이 추가로 필요하다.

implementation 'org.apache.tomcat.embed:tomcat-embed-core:9.0.0' // Spring Boot 버전에 맞춰 조정

위의 의존성을 추가하여 세부 조정할 수있다.

코드에 대한 시나리오

개인적으로 공부하면서 http 프로토콜을 https 로 리다이렉트 시켜보자 라는 챌린지에 도전했다.

예를들어 같은 api 를 http, https 를 지원하되 http 에대해 접근시 https 포트로 리다이렉트 를 강제한다.

위의 코드에서는 domain:8080 으로 접근시 domain:8443 으로 리다이렉트 하여 처리 한다고 보면된다.

현업에서는 직접 백엔드서버에 접근하기전 리버스 프록시를 두고 위의 멀티포트지원을 nginx에서 분기처리하는식으로 많이 구현할것이다. 사실상 쓸데 없는 삽질로 보일수도있지만 스프링에서도 멀티포트가 가능하고 또 구현해보고싶은 개인적인 챌린지였다.