[webapp] 동적인 데이터를 처리하는 서버 톰캣과, 톰캣이 동작하는 가상의 컴퓨터 JVM 그리고 자바 기반의 웹프로젝트 구성
Apache / Tomcat
HTTP 웹서버는 정적인 데이터를 처리하는 서버를 말한다.
🐈 톰캣은 아파치 소프트웨어 재단의 자바 기반의 웹 애플리케이션 서버로써, 흔히 WAS(Web Application Server)라고 하는데, 해당 서버는 동적인 데이터를 처리하는 서버이다.
WAS는 웹서버와 🥥 서블릿 컨테이너의 결합으로 웹컨테이너라 불린다.
DB로 연결되어 데이터를 주고 받거나, 자바 등을 통해 데이터 조작이 필요한 경우에 WAS를 사용한다.
WAS는 자바 서블릿을 실행시키고, JSP 코드가 포함되어 있는 웹페이지를 만들어 준다.
- 🪭 Web Service 플랫폼으로써의 역할
- 🪭 프로그램 실행환경과 DB 접속 기능 제공
- 🪭 비즈니스 로직 처리
- 🪭 트랜잭션 관리
즉, WAS 중 하나인 톰캣은 아파치(웹서버)에서 넘어온 동적인 페이지를 읽어들여 프로그램을 실행하고
그 결과를 다시 HTML로 재구성하여 아파치에 되돌려준다.
아파치는 80포트로 클라이언트 요청이 왔을 때만 응답하고,
아파치가 알아서 톰캣에 8080포트로 접근한다.
톰캣의 구조
🔅 서블릿, JSP 구동환경을 제공할 뿐만 아니라 HTTP 웹서버 역할을 한다.
- 🥥 Catalina (Servlet Container)
- 톰캣의 웹컨테이너이다.
- URL을 특정 서블릿에 매핑
- 서블릿, JSP 파일에 대한 요청 처리
- 서블릿 생명주기 관리
- 🐈⬛ Coyote (HTTP Component)
- HTTP/1.1을 웹서버로 지원하는 톰캣의
Connector Component이다 Catalina는 Coyote를 사용해 웹서버로써 동작한다.
- 🎠 Jasper (JSP Engine)
- 톰캣의 JSP 엔진이다.
- JSP 파일 구문 분석, 서블릿으로 컴파일
HTTP 요청을 Coyote가 받아서 Catalina로 전달한다.
Catalina에서 전달받은 HTTP 요청을 처리할 웹 애플리케이션 Context을 찾고 🪛 WEB-INF/web.xml (deployment descriptor file) 파일 내용을 참조하여 서블릿에 요청을 전달한다.
요청된 서블릿을 통해 생성된 JSP파일들이 호출될 때, Jasper가 Validation Check/Compile 등을 수행한다.
🔅 클라이언트로부터 오는 요청을 파싱하여, HttpServlet객체로 변환하여 제공한다.
JVM (Java Virtual Machine)
os에 종속받지 않고, 자바를 실행하기 위해서 os위에서 자바를 실행시킬 무언가가 필요한데, 그게 JVM이다.
.java -> javac -> .class -> JVM -> 실행
JVM은 java byte code (.class)를 인식할 수 있다.
자바 컴파일러(javac)에 의해 변환된 코드의 명령어 크기가 1byte라서 java byte code라고 불린다.
java byte code는 기계어가 아니기 때문에 os에서 바로 실행되지 않는다.
JVM의 JIT 컴파일러에 의해 os가 이해할 수 있는 binary code로 변환되는데,
따라서, java byte code는 JVM 위에서 os와 상관없이 실행될 수 있다.
JVM의 구조
- 클래스 로더
Class Loader - 런타임 시, 동적으로 클래스 파일을 로드하고 링크하는 역할 수행
jar 파일 내에 저장된 클래스들을 JVM위에 탑재하는 역할 수행
런타임 데이터 영역에java byte code를 배치시킨다.
- 클래스 로더
- 실행엔진
🚂 Execution Engine - 클래스를 실행시키는 역할 수행
CPU가 실행할 수 있는 형태인binary code로 변환한다.
- 인터프리터
Interpreter java byte code를 명령어 단위로 읽어서 실행
- 인터프리터
- JIT 컴파일러
Just-In-Time Comliation - 동적 번역이라고도 하는데, 프로그램을 실제 실행하는 시점에 기계어로 번역하는 컴파일러이다.
인터프리터 방식의 단점을 보완하기 위해 도입되었다.
인터프리터 방식으로 실행하다가 적절한 시점에java byte code전체를 컴파일하여binary code로 번역하고
이후에는 인터프리팅하지 않고, 기계어로 직접 실행하는 방식을 말한다.
컴파일된 코드는 캐시에 보관하기 때문에, 한번 컴파일된 코드는 빠르게 수행된다.
⚠️ 내부적으로 특정 메서드가 얼마나 자주 수행되는지를 체크하고 일정정도를 넘을때 컴파일을 수행한다.
- JIT 컴파일러
- 가비지 콜렉터
🗑️ Garbage Collector - 더이상 사용되지 않는 인스턴스를 찾아 메모리에서 삭제한다.
- 가비지 콜렉터
- 실행엔진
- 런타임 데이터 영역
Runtime Data Area - 프로그램을 실행하기 위해, os에서 할당받은 메모리 공간을 말한다.
스레드가 시작될 때 생성되며, 스레드마다 하나씩 존재한다.
현재 수행중인 JVM 명령의 주소를 가지고 있다.
(1) JVM Stack Area- 프로그램 실행 과정에서 임시로 할당되었다가 메서드를 빠져나가면 소멸되는 데이터를 저장하기 위한 영역
ex. 변수, 임시데이터, 스레드, 메서드 정보를 저장
⚠️ 메서드 호출 시마다, 각각의 스택프레임이 생성
(2) PC Register(3) Method Area= Class Area= Static Area- 클래스 정보를 처음 메모리 공간에 올릴때, 초기화되는 대상을 저장하는 메모리 공간
⛱️ Runtime Constant PoolStatic Area에 존재하는 별도의 관리영역
상수 자료형을 저장하여 참조하고, 중복을 막는 역할을 수행
(4) Native Method Area- 실제 실행할 수 있는 기계어로 작성된 프로그램
(binary code)을 실행시키는 영역
(5) Heap- 객체를 저장하는 가상 메모리 공간
new 연산자로 생성되는 객체와 배열을 저장
Permanent Generation- 생성된 객체들의 정보의 주소값이 저장된 공간
클래스 로더에 의해 로드되는 클래스, 메서드 등에 대한 메타정보가 저장되는 영역
Reflection을 사용하여 동적으로 클래스가 로딩되는 경우 사용한다.
🍍 리플랙션 (reflection)- 객체를 통해 클래스 정보를 분석해내는 프로그래밍 기법을 말한다.
New / Young Area- 생명주기가 짧은 객체를 GC대상으로 하는 영역
이곳의 인스턴스들은 추후 가비지 콜렉터에 의해 사라진다.
여기서 일어나는 가비지 콜렉트를'Minor GC'라고 한다.
Eden- 객체들이 최초로 생성되는 공간
Survivor 0,1Eden에서 참조되는 객체들이 저장되는 공간
Eden에 객체가 가득차게 되면 GC가 발생
Eden에 있는 값들을Survivor 1영역에 복사하고, 나머지 객체 삭제
Old Area- 생명주기가 긴 객체를 GC대상으로 하는 영역
이곳의 인스턴스들은 추후 가비지 콜렉터에 의해 사라진다.
여기서 일어나는 가비지 콜렉트를'Major GC'라고 한다.
- 런타임 데이터 영역
- 🧶 스레드
- 프로세스 내에서 실제로 작업을 수행하는 주체를 말한다.
톰캣 인스턴스 (서버)
🍪 톰캣을 실행시키기 위해서 JRE 1.1 이상에 부합되는 자바 런타임 환경(Java Runtime Environment)이 필요하다.
JVM 위에서 하나의 톰캣 인스턴스(서버)가 하나의 프로세스로 동작한다.
하나의 톰캣 인스턴스에는 여러개의 Service가 존재할 수 있다.
각각의 Service는 하나의 Catalina Servlet Engine과 여러개의 Connector로 구성된다.
Connector로 들어온 HTTP 요청을 해당 Host에게 전달하는 역할을 한다.
하나의 Engine에는
- 여러개의
Host가 존재할 수 있다. - Host는 가상호스트 이름을 나타내며, 호스트이름이 곧 url에 매핑된다.
- 여러개의
- 여러개의
Context가 존재할 수 있다. Context는 하나의 웹애플리케션을 나타내며 주로 .war 파일의 형태로 배포된다.
- 여러개의
톰캣은 자체적으로 보유하고 있는 내부 웹서버와 함께 독립적으로 사용될 수 있지만
보통 아파치와 같은 다른 웹서버와 함께 사용된다.
굳이 다른 웹서버와 함께 사용하는 이유는
톰캣의 웹서버 기능은 아파치 웹서버보다 느린 처리속도를 보이기 때문이다.
즉, 모든 정적/동적 데이터를 톰캣이 처리한다면, 결과적으로 사용자의 요청에 대한 응답이 느려지게 될 것이다.
반면에, 정적데이터는 웹서버이 아파치가 처리하고 동적데이터는 WAS인 톰캣이 처리함으로써
서버의 전체적인 부하를 분산하여 응답을 빠르게 하기위해 두 서버를 연동해서 사용한다.
또한, 아파치에서 제공하는 유용한 모듈을 톰캣에서는 사용할 수 없는 부분 등의 이유가 있다.
IntelliJ 프로젝트 구성
intelliJ에서 하나의 프로젝트 안에 여러 모듈을 구성할 수 있다.
하위 모듈을 감싸는 프로젝트를 루트 프로젝트라 하는데,
모듈 관리만 담당하므로 루트 프로젝트의 src 폴더는 지워도 된다.
모듈을 사용하면 하나의 애플리케이션에서 여러 기술과 프레임워크를 결합할 수 있다.
각 모듈은 자체 프레임워크를 가질 수 있고, .jar 혹은 .war 형태의 단일 유형이다.
또한 모듈은 프로젝트에 맞게 구성된 것과는 다른 SDK, Language Level, 자체 라이브러리를 가질 수 있다.
각 모듈에 대한 정보는 📑 .iml 파일에 저장된다.
🎱 Project Structure ctrl + alt + shift + s
Platform Setting🌎 GlobalSDKs- 여기에 설정된 SDK는 여러 프로젝트(모듈)에서 사용할 수 있다.
⚠️ 각 모듈에 대한 개별적인 SDK도 지정가능하다.
Global Libraries
Project Setting.idea디렉토리에 .xml 형식으로 저장된다.
📑 .iml파일과🫠 .idea디렉토리를 생성하여 프로젝트 설정을 유지한다.
ProjectSDK- 여기에 설정된 SDK는 여러 하위 모듈에서 사용할 수 있다.
⚠️ 각 하위모듈에 대한 개별적인 SDK도 지정가능하다.
Language Level- compiler에도 영향을 미친다.
Compiler OutputIntelliJ에 컴파일 결과를 저장하는 디렉토리 경로를 지정할 수 있다.
두 개의 하위 디렉토리를 만든다.productiontest
⚠️ 각 하위모듈에 대한 개별적인 출력 경로 설정도 가능하다.
일반적인 프로젝트에는 일련의 설정과 하나 또는 여러개의 모듈이 있다.
프로젝트는 모듈을 함께 유지하고, 모듈 간 종속성을 제공하며, 공유 구성을 저장하는 껍데기이다.
🚀 모듈 (Module)은 모듈 구성을 유지하는 📑 .iml 파일과
소스코드, 리소스, 테스트를 저장하는 🩸 Contents Root로 구성된다.
🩸 Contents Root는 코드를 저장하는 폴더이다.
🩸 Contents Root 내의 폴더는 보관하는 콘텐츠에 따라 여러 카테고리에 할당할 수 있다.
📂 Source- 해당 폴더에는 컴파일해야하는 프로덕션 코드가 포함되어 있다.
📂 Generated Source- 소스폴더의 파일이 수동으로 작성되지 않고 자동으로 생성되며, 재생성할 수 있다고 간주한다.
📂 Test Source- 테스트와 관련된 코드를 프로덕션 코드와 별도로 보관한다.
⚠️ 테스트 소스에 대한 컴파일 결과는 일반적으로 다른 폴더에 배치된다. 📂 Generated Test Sources- 소스폴더의 파일이 수동으로 작성되지 않고 자동으로 생성되며, 재생성할 수 있다고 간주한다.
📂 Resources- 애플리케이션에 사용되는 리소스 파일, 이미지, xml 및 속성파일이 포함되어 있다.
⚠️ 해당 폴더의 파일은 기본적으로 그대로 출력폴더에 복사된다. 📂 Test Resources- 해당 폴더는 테스트 소스와 관련된 리소스 파일을 위한 것이다.
📂 Excluded- 해당 폴더의 파일은 코드 완성, 탐색 및 검사에 의해 무시된다.
⚠️ 일반적으로 컴파일 출력 폴더는 제외된 것으로 표시된다.
⚠️ 단, 배포에 영향을 미치지 않는다.

