CGI(Common Gateway Interface)란 서버와 애플리케이션 간에 데이터를 주고 받는 방식 또는 컨벤션을 의미한다.
웹 서버에서 외부 프로그램을 실행하고 그 결과를 웹 페이지로 돌려주기 위한 표준 인터페이스이며, 클라이언트의 요청에 대한 응답을 동적으로 생성하는 데 사용된다.
언어 독립성 : CGI는 언어에 독립적이기 때문에 다양한 프로그래밍 언어로 개발된 스크립트를 서버 측에서 실행할 수 있다. (Perl, C, Python 등)
간단한 구현 : 상대적으로 간단하게 구현할 수 있다. 특히 동적인 콘텐츠를 생성하는 간단한 웹 페이지나 폼 처리에 유용하다.
표준 인터페이스 : 웹 서버와 외부 프로그램 간의 표준 인터페이스를 제공하므로, 이로 인해 서버와 프로그램 간의 통신이 단순하게 이루어질 수 있다.
성능 : 매번 요청이 들어올 때마다 외부 프로그램을 실행해야 하므로, 성능이 저하될 수 있다. 특히 많은 요청이 들어오는 경우에는 부하가 크게 증가할 수 있다.
보안 취약성 : 보안에 취약할 수 있다. 외부 프로그램이 서버에서 실행되는데, 이로 인해 적절한 보안 조치가 없으면 보안 공격의 대상이 될 수 있다.
프로세스 생성 오버헤드 : 매번 요청마다 새로운 프로세스를 생성하고 종료하는 오버헤드가 있다. 이로 인해 서버 자원을 많이 사용하게 된다.
환경 변수 사용 : 클라이언트의 요청에 대한 정보를 환경 변수로 제공한다. 이를 통해 스크립트는 클라이언트의 요청을 파악하고 처리할 수 있다.
유연성 : 어떠한 프로그래밍 언어로도 구현 가능한 언어 독립성과 표준 인터페이스를 통해 유연성을 제공한다.
Servlet이란 Java 웹 애플리케이션에서 동적인 웹 페이지를 생성하는 자바 프로그램을 말한다.
클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍 기술이다.
언어 독립성 : Servlet은 Java로 작성되기 때문에 Java의 언어 독립성을 지닌다.
플랫폼 독립성 : Java의 플랫폼 독립성 덕분에 서블릿은 다양한 운영체제와 웹 서버에서 실행될 수 있다.
높은 생산성 : Java 개발자들은 이미 익숙한 언어와 API를 사용하여 서블릿을 개발할 수 있다. 또한, Servlet은 Java EE 스펙의 일부로 표준화되어 있어 개발자들이 일관된 방식으로 웹 애플리케이션을 개발할 수 있다.
강력한 확장성 : Servlet은 Java의 강력한 객체 지향 기능을 활용할 수 있어 모듈화와 확장성이 뛰어나다. 이는 대규모 웹 애플리케이션에서 유용하다.
서버 사이드 로직 : Servlet은 주로 서버 사이드 로직을 처리하는 데에 사용된다. 데이터베이스 연동, 업무 로직 처리 등을 효과적으로 수행할 수 있다.
코드 복잡성 : Servlet은 일반적으로 HTTP 요청 및 응답 처리에 대한 상세한 코드를 포함하므로, 간단한 작업에도 비교적 많은 코드를 작성해야 한다.
HTTP 프로토콜에 직접 의존 : Servlet은 주로 HTTP 프로토콜을 다루는 데에 중점을 둔다. 따라서, 다른 프로토콜을 다뤄야 하는 경우에는 추가적인 작업이 필요할 수 있다.
서버 리소스 사용 : 각 클라이언트 요청마다 새로운 스레드가 생성되기 때문에, 많은 동시 요청이 발생하는 경우 서버 리소스를 많이 사용할 수 있다.
앞서 말한 "Java"만의 플랫폼 독립성과 서블릿 컨테이너 내에서 실행되기 때문에 오버헤드가 적으므로, CGI보다 더 빠른 성능을 제공한다.
CGI는 매번 요청에 따라 외부 프로그램이 새로 생성, 실행되고 종료되는 반면, Servlet은 컨테이너에 의해 관리 되므로 여러 요청에 대해 재사용될 수 있다.
이로 인해 CGI는 서버 리소스를 많이 소비되지만, 서블릿은 리소스를 효율적으로 사용하는 스레드를 매번 생성한다.
그렇다면 Servlet Spec이란 무엇일까? 앞서 설명한 Servlet이 작동하기 위한 표준 규격을 의미한다. 즉, Java 웹 개발자가 Servlet을 개발하고 사용할 때 따라야하는 규칙과 규격을 가리킨다고 볼 수 있다.
규격 : Servlet Spec은 Java EE(Java Platform, Enterprise Edition) 또는 Jakarta EE(현재) 스펙의 일부로서, 서블릿 컨테이너가 지켜야 하는 규칙과 API를 정의한다.
기능 : Servlet Spec은 Servlet의 생명주기, HTTP 프로토콜과의 상호 작용, 요청 및 응답 객체의 사용 방법 등을 규정하여 서블릿이 일관된 방식으로 동작할 수 있도록 한다.
자동 코드 생성 : Servlet Spec을 따르는 서블릿 컨테이너는 Servlet 클래스를 실행하기 위한 보일러플레이트 코드를 자동으로 생성한다.
웹 서버는 클라이언트로부터 HTTP 요청을 받아 정적인 웹 페이지(HTML, 이미지, CSS 등)를 제공하는 소프트웨어 또는 하드웨어 시스템이다.
웹 애플리케이션의 기초적인 서비스를 제공하며, 주로 정적 콘텐츠를 처리한다. 가장 일반적인 웹 서버 소프트웨어로는 Apache, Nginx, Microsoft IIS 등이 있다.
WAS는 동적인 콘텐츠를 생성하고 실행하는 서버 환경을 제공하는 소프트웨어다. 웹 서버와는 달리, WAS는 서버 측에서 프로그램 실행, 데이터베이스 연동, 비즈니스 로직 처리 등과 같은 동적인 작업을 담당한다.
서블릿 컨테이너 : 동적인 콘텐츠를 처리하기 위해 서블릿 컨테이너를 제공한다. 서블릿은 Java 언어로 작성되어 웹 애플리케이션의 로직을 실행한다.
JSP 컨테이너 : JSP(JavaServer Pages)를 처리하기 위한 컨테이너를 제공한다. JSP는 서버 측에서 동적인 웹 페이지를 생성하는 데 사용된다.
데이터베이스 연동 : WAS는 데이터베이스와의 효율적인 통신을 위한 기능을 제공한다. 데이터베이스와의 연결 관리, 트랜잭션 처리 등이 포함된다.
업무 로직 처리 : 웹 애플리케이션의 비즈니스 로직을 실행하고 관리하는 데 필요한 여러 서비스를 제공한다.
보안 및 인증 기능 : 사용자의 인증 및 권한 부여를 처리하며, 웹 애플리케이션의 보안을 강화한다.
WAS는 웹 서버의 확장으로 볼 수 있으며, Java EE(Jakarta EE) 스펙에 따라 동작하는 경우가 많다.
라고 생각했는데, 웹서버와 WAS는 분리해서 사용해야 한다고 한다.
이유는 다음과 같다.
성능 및 부하 분산 : 정적인 콘텐츠를 처리하는 웹 서버와 동적인 콘텐츠를 생성하고 처리하는 WAS가 각각 특화된 역할을 수행할 수 있다. 이로써 부하 분산이 가능하며, 각 서버의 성능을 최적화할 수 있다.
확장성 : 필요에 따라 각각을 독립적으로 확장할 수 있다. 예를 들어, 웹 서버는 로드 밸런싱을 통해 여러 WAS 인스턴스로 요청을 분배하고, WAS는 필요에 따라 수평적으로 스케일 아웃할 수 있다.
유연성과 기술 선택의 자유 : 웹 서버에서는 Nginx, Apache와 같은 웹 서버를 사용하고, WAS에서는 Tomcat, WildFly, WebSphere 등을 선택할 수 있는데, 이는 기술 스택의 다양성을 허용하며, 특정 업무에 최적화된 서버를 선택할 수 있는 유연성을 제공한다.
보안 강화 : 외부에서 접근 가능한 웹 서버와 내부에서만 통신하는 WAS 사이에 방화벽 등의 보안 장치를 두어 보안을 강화할 수 있다.
서버 유지보수 용이성 : 웹 서버와 WAS를 분리하면 각각의 역할에 맞게 서버를 관리하고 유지보수할 수 있다. 각각의 서버가 특정 역할에만 집중하므로 서버 유지보수 및 업그레이드가 용이해진다.
로드 밸런싱 및 고가용성 : 로드 밸런싱을 통해 여러 WAS 인스턴스 간의 트래픽을 분산시킬 수 있으며, 고가용성을 제공할 수 있다. WAS의 장애 시에도 웹 서버는 정적 콘텐츠를 제공하고, 로드 밸런서를 통해 다른 정상적인 WAS로 트래픽을 분산시킬 수 있다.
일반적으로 분리된 아키텍처가 성능 및 확장성을 향상시키고 유지보수를 용이하게 만든다고 한다.