스프링 부트 - 핵심 원리와 활용 - 섹션3. 스프링 부트와 내장 톰캣
CS/김영한 스프링 강의

스프링 부트 - 핵심 원리와 활용 - 섹션3. 스프링 부트와 내장 톰캣

웹 애플리케이션 서비스를 줄여서 WAS라고 부르는데, 서버를 실행하기 위해선 웹 애플리케이션 서버 설치하고, 여기에 빌드해서 나온 파일 WAR를 올리고 실행해줘야 해서 여기에 불편함을 느끼는 사람이 많았다. 그래서 어차피 톰캣도 자바로 만들었으니 그냥 라이브러리처럼 내장하면 되는거 아닌가? 해서 진짜 안에다가 넣었다.

 

 

이제 main 메소드만 실행해도 톰캣 서버가 알아서 실행된다. 따로 설치할 필요가 없음.

 

이제 스프링도 연동해보자.

 

컨테이너 만들고 이 컨테이너를 디스패처 서블릿 만들어서 연결하고, 이 디스패처 서블릿을 톰캣에 연결한다.

 

이걸 실제로 운영하려고 웹 서버에 올리려고 한다. 그럼 앞서 해봤던 빌드해서 나온 걸 서버에 올리면 될거다.

빌드는 gradle에서 설정하여 만들자. 물론 jar를 실행하려면 어떤 것의 main을 실행해야 할지 manifest를 통해 정해줘야 한다.

gradlew clean buildJar하면 저번처럼 .jar 파일이 생길텐데 근데 실행이 안된다.

 

압축된걸 풀어보면 코드 작성한 대로 나온걸 볼수 있다.

근데 안되는 이유는 라이브러리가 압축 안에 없기 때문. jar 파일 안에 또다른 jar는 포함할 수 없도록 자바 스펙이 구성되었기 때문. 전 섹션에서 된 이유는 war여서 안에 라이브러리들이 .jar도 되어있어도 문제가 없었다.

 

대안으로 FatJar방식을 사용하자. .jar은 안되지만 클래스는 되니, 라이브러리들에 있는 모든 .jar를 압축해제하여 클래스를 뽑아내 내꺼에 포함시키는 거다.

그래서 빌드할 때 이름이 중복된 것들이 있다고 경고한다. 최종 결과물도 모두 합쳤기 때문에 용량이 꽤 크다.

 

실행은 잘 된다.

압축 풀어보면 다른 라이브러리들의 클래스까지 가져왔기 때문에 정말 많이 들어있다.

 

그럼 라이브러리 문제는 해결하고 어쨋든 실행은 되었다. 이제 main()만 실행하면 알아서 서버 켜지고 코드까지 다 작동한다.

좋은것 처럼 보이지만 단점은 어떤 라이브러리를 사용하는지 추적이 어렵고 중복된 클래스가 만약 중요한 거일 경우, 서버는 안돌아가고 에러가 뜬다.

 

이것까지 해결한 부트 클래스를 만들어보자.

 

이전에 했던 bean 설정은 주석처리. 이 클래스는 main의 하위클래스로써 스캔되어 등록될거라 뺌.

그 뒤 맨 상위 위치에 main을 실행할 함수를 작성한다. 이게 스프링으로써 작동하는 이유는 어노테이션 안에 컴포넌트 스캔이 있고, 이 컴포넌트 스캔에 따로 지정된 범위가 없으면 하위의 모든 클래스들이 스캔되어 등록된다.

 

 

 

새로운 스프링부트로 프로젝트를 만들어본다.

 

main에서 어플리케이션 run을 하는게 직접 만든거랑 같다.

 

난 톰캣 웹서버 관련해서 설치하거나 한 것도 없는데 바로 실행되는 이유는 이미 라이브러리로써 내장되어 있기 때문.

 

이 run 안에 스프링 컨테이너 만들고 주입하고 서버 실행하고 설정하고 하는 과정들이 다 들어가 있다.

하지만 핵심은 2가지인데, 이 안의 코드는 복잡하지만 결국 스프링 컨테이너를 생성하고, WAS(내장 톰캣)을 생성하는 것.

 

빌드해서 실행해보고, 안에 뭐가 들었는지 확인해보자.

 

plain는 내 코드만 들어있고 없는건 라이브러리들 포함한 것.

 

실행 잘 된다.

안에 뭐가들었는지 압축을 해제해 보자.

 

 

눈 여겨볼건 manifest의 main이 내가 작성한 main 클래스가 아니라 무슨 이상한 거고 내가 만든건 start에 들어있다. 이유는 나중에 설명한다.

 

관련 라이브러리들 다 들어있고 내 코드도 들어가있다. 근데 외부 라이브러리는 lib 안에 있는데, jar로 되어있다. 근데 자바 스펙 상 jar 안에 jar는 있을 수가 없는데 스프링은 읽었다. 어떻게 된거냐?

 

 

이유는 자바 스펙에서 jar 안의 jar는 기능을 제공하지 않다보니 스프링 자체에서 해결한 것. 스프링 부트는 jar 내부에 jar를 포함할 수 잇는 특별한 구조의 jar를 만들고 동시에 만든 jar를 내부 jar를 포함해서 실행할 수 있게 했다. 이것을 실행 가능 Jar(Executable Jar)라고 한다. 기존 fat jar처럼 모든 jar 압축을 풀어 안의 클래스를 한 파일로 가져오는게 아니기 때문에 어디 라이브러리에서 왔는지, 이름 중복 문제를 해결했다.

 

 

 

그럼 아까 봤던 manifest를 다시 보자.

main 클래스로 실제 자바 main을 실행하는게 아닌, jar를 풀어낼 수 있는걸 main으로 두어서 이걸 실행한 다음 실행 주도권을 내가 만든 main 클래스한테 준다고 보면 된다.