Spring Boot 애플리케이션에서 HTTPS(SSL/TLS)를 활성화하고, HTTP 요청을 HTTPS로 자동 리다이렉트 하도록 설정하는 역할을 한다
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
tomcat.addAdditionalTomcatConnectors(httpToHttpsRedirectConnector());
return tomcat;
}
🔹 @Bean 어노테이션을 통해 Spring 컨테이너에서 ServletWebServerFactory 빈을 등록한다
🔹 Tomcat 서블릿 웹 서버 팩토리를 생성하고 설정한다
🔹 postProcessContext 메서드를 오버라이드하여 보안 제약 조건을 설정한다
🔹 SecurityConstrait 를 생성하고 ‘CONFIDENTIAL” 제약 조건을 설정한다. 이는 해당 URL 패턴에 대해 보안 연결(HTTPS)이 필요함을 의미한다
🔹SecurityCollection 를 생성하고 “/*” 패턴(모든 URL)을 추가한다
🔹 이 보안 컬렉션을 보안 제약 조건에 추가한다
🔹 최종적으로 이 보안 제약 조건은 Tomcat 컨텍스트에 추가한다
🔹 HTTP에서 HTTPS로의 리다이렉트 커넥터를 추가한다
private Connector httpToHttpsRedirectConnector() {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme("http");
connector.setPort(8080);
connector.setSecure(false);
connector.setRedirectPort(443);
return connector;
}
🔹 HTTP 프로토콜을 사용하는 새로운 Tomcat 커넥터를 생성한다
🔹 이 커넥터의 스킴을 ‘http’로 설정한다
🔹 이 커넷터가 8080 포트에서 HTTP 요청을 수신하도록 설정한다
🔹 이 커넥터는 보안 연결이 아님을 명시한다(setSecure(false))
🔹 리다이렉트 포트를 443(HTTPS의 기본 포트)으로 설정한다. 이는 HTTP 요청이 들어오면 HTTPS(433 포트)로 자동 리다이렉트됨을 의미한다
📌 Application을 Run 하니 8080 포트를 사용 중이라고 뜬다
***************************
APPLICATION FAILED TO START
***************************
Description:
Web server failed to start. Port 8080 was already in use.
Action:
Identify and stop the process that's listening on port 8080 or configure this application to listen on another port.
✅ 코드 구조로 인한 문제
🔹 위 코드에서 httpToHttpsRedirectionConnector() 메서드를 통해 명시적으로 8080 포트를 HTTP 연결용으로 설정하고 있다
🔹 Spring Boot 는 기본적으로 8080 포트를 사용하려고 시도한다
🔹 따라서 Spring Boot 가 기본 커넥터를 위해 8080 포트를 바인딩하려고 시도하는 동시에, 코드에서 추가한 HTTP 리다이렉트 커넥터도 8080 포트를 사용하려고 시도할 수 있다
✅ 서버 구성 충돌
🔹 Tomcat 은 기본적으로 8080 포트를 사용하려고 한다
🔹코드에서 TomcatServletWebServeFactory 를 커스터마이징하면서 추가 커넥터를 설정했지만, 기본 커넥터와 포트 설정이 충돌할 수 있다
📌 처음에는 해당 코드를 localhost:8080으로 접속하면 https로 리다이렉트하는 단순한 코드로 생각했다
📌 그런데 알고 보니 내부에서 톰캣을 띄우는 코드였고, 점심 먹고 온 후 갑자기 동작하지 않아 원인을 찾는 데 어려움을 겪었다
문제 상황
1️⃣ 서버 포트를 8081로 변경하니 정상 동작했다
2️⃣ 그 후 "http → https"로 리다이렉트하는 부분도 8081로 변경 (변경해야하는 줄 알았다ㅠ)
connector.setPort(8080); => connector.setPort(8081);
3️⃣ 하지만 계속 "포트가 사용 중"이라는 오류 발생
해결 과정
1️⃣ 문제를 2시간 동안 반복해서 점검하다가 코드 자체에 문제가 있음을 인지했다
2️⃣ 내부 톰캣을 실행하는 부분을 주석 처리하니 정상 동작!!!
✨결론: 잘 작동하던 코드가 갑자기 안 되니 원인을 쉽게 파악하기 어려웠다. 결국 내부 톰캣 실행 코드가 문제였음을 발견하고 해결했다.
✅ application.properties 또는 application.yml 에서 서버 포트 변경
server.port=8443
server:
port:8443
🔹 이렇게 하면 Spring Boot 의 기본 커넥터가 8443 포트를 사용하게 되어 8080 포트와의 충돌을 피할 수 있다 ⇒ 굳이 8443 아니어도 된다 (8080만 아니면 되는듯)
✅ 실행 중인 프로세스 확인 및 종료
🔹 Windows: 명령 프롬프트(powershell에서 진행했다) : netstat -ano | findstr 8080 으로 8080 포트를 사용중인 프로세스 확인 후 종료
🔹 Mac/Linux : 터미널에서 lsof -i 8080 으로 확인 후 종료
✅ 코드 수정
🔹 HTTP 리다이렉트 커넥터에 다른 포트 번호 사용
connector.setPort(8081);