728x90
SMALL

Web Server vs WAS( Web Application Server) 

구분핵심 역할주로 처리하는 것

 

Web Server “정적(Static) 콘텐츠 배달자” HTML, CSS, JS, 이미지, 동영상 등 요청‑받아 그대로 전송
WAS “동적(Dynamic) 로직 실행자” 서블릿·Spring MVC·EJB·JSP 같은 코드 실행 → DB/외부시스템과 대화 → 결과 생성
 

두 시스템 모두 HTTP 를 사용하지만, 웹 서버는 “파일 전송”에 특화, WAS는 “비즈니스 로직 수행”에 특화돼 있습니다. 


1️⃣ 동작 흐름 이해하기

브라우저 ──► [1] Web  Server (Apache HTTP / Nginx)
             │   ├─ 정적 파일이면 바로 응답
             │   └─ 동적 URL이면 WAS 로 프록시
             ▼
             [2] WAS (Tomcat / WebLogic / WildFly)
             ├─ 서블릿·Spring 실행
             └─ DB·외부 API 호출 후 결과 HTML·JSON 생성
             ▲
브라우저 ◄── 최종 응답
 
  • 요청이 정적이면 ① 단계에서 바로 끝.
  • 동적이면 ①이 요청을 ②로 넘기고, ②가 서블릿(SPRING) 로직을 수행해 응답을 돌려줍니다.

2️⃣ 왜 둘을 분리할까?

이유설명
성능 최적화 정적 파일(캐시·Gzip·HTTP/2)을 웹 서버가 초고속 처리 → WAS CPU/메모리 부담 감소
보안·DMZ 외부망엔 웹 서버만, 내부망에 WAS 배치 → 애플리케이션 코드 숨김
스케일링 유연성 Web → N:1 로드밸런싱, WAS → M대 수평 확장, 필요 시 각각 독립 증설
다양한 언어 혼합 하나의 웹 서버가 Java WAS(Tomcat)와 Python WAS(Gunicorn) 모두에게 리버스 프록시 가능
 

3️⃣ 제품별 특징 요약

군대표 제품특징
Web Server Apache HTTP(모듈 풍부) · Nginx(이벤트 기반, 고성능) · Microsoft IIS 정적 파일·SSL 종료·리버스 프록시·로드 밸런서
경량 WAS Tomcat(Servlet/JSP) · Jetty · Undertow 서블릿 컨테이너 중심, Jakarta EE 웹 프로파일
풀스택 WAS WebLogic · WildFly/JBoss · WebSphere EJB, JMS, JTA, CDI 등 Jakarta EE 전체 스펙 내장, 관리 콘솔·클러스터 기능
 

모든 WAS 는 Servlet API(이제 jakarta.servlet.*)를 구현하므로, 같은 WAR/서블릿이 서로 다른 WAS 에서 동일하게 동작합니다. 단, Spec 버전(javax.* vs jakarta.*)은 맞춰야 해요. docs.oracle.comopenlogic.com


4️⃣ “웹 서버 + WAS” 가 합쳐진 현대적 형태

  • Spring Boot: 내장 Tomcat/Jetty 를 포함한 java -jar 한 프로세스 ⇒ 실제로는 웹 서버 + WAS 가 한 JVM 에 같이 존재.
  • Nginx Unit, Node.js, Go Fiber 등: 애플리케이션 서버가 HTTP 처리까지 직접 수행.
    → “웹과 WAS 구분”은 아키텍처적인 개념이고, 구현체는 필요에 따라 합치거나 분리합니다.

5️⃣ 기억하면 좋은 포인트 3가지

  1. 웹 서버가 없이도 Tomcat 단독으로 서비스 가능하지만,
    대규모·보안·멀티스택 환경에서는 보통 둘을 분리합니다.
  2. 동적 로직이 필요한 순간부터는 WAS 가 필수—Java 에선 서블릿·Spring MVC·JSP 가 그 진입점입니다.
  3. 제품을 선택할 땐 필요 스펙(Jakarta EE 전체? / 서블릿만?) 과 운용 비용을 먼저 고려하세요.

🔑 정리 한 줄
Web Server = 정적 파일 전담, WAS = 동적 비즈니스 로직 전담.
구조는 분리·통합 모두 가능하지만, “역할” 자체는 언제나 이 두 층으로 나뉜다!

 

728x90
반응형
LIST
728x90
SMALL

✅ 핵심 한 줄 요약

Spring은 내부적으로 DispatcherServlet이라는 서블릿을 사용해서 모든 웹 요청을 처리합니다.


🔷 구조적으로 어떻게 되는가?

Spring MVC의 요청 흐름은 다음과 같아요:

 

브라우저 요청
    ↓  (HTTP 요청)
Tomcat (서블릿 컨테이너)
    ↓
DispatcherServlet (Spring이 만든 서블릿)
    ↓
Controller (@Controller or @RestController)
    ↓
Service, Repository 등 비즈니스 로직 처리
    ↓
DispatcherServlet
    ↓
응답 반환
 

🧩 DispatcherServlet이 뭐야?

🔍 DispatcherServlet = Spring이 만든 서블릿

  • HttpServlet을 상속받은 일반적인 서블릿
  • web.xml이나 ServletInitializer에서 /* 모든 요청을 가로채도록 등록됨
  • 그 후 내부에서 어떤 Controller가 이 요청을 처리할지 판단하고 실행함

즉, 서블릿인데 우리가 직접 만들 필요 없이 Spring이 대신 관리해주는 고급 서블릿이에요.

 

Spring 의 경우 web.xml 에 이렇게 등록했어요 : 

<servlet>
    <servlet-name>dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcher</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

 


🔧 예: DispatcherServlet 등록 (Spring Boot가 자동으로 해줌)

public class MyWebAppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext container) {
        AnnotationConfigWebApplicationContext context =
            new AnnotationConfigWebApplicationContext();
        context.setConfigLocation("com.example.config");

        ServletRegistration.Dynamic dispatcher =
            container.addServlet("dispatcher", new DispatcherServlet(context));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

※ 이 설정은 이제 Spring Boot에서는 자동으로 해줍니다.


🔄 DispatcherServlet은 어떤 역할을 할까?

DispatcherServlet은 Spring MVC의 "프론트 컨트롤러" 역할을 합니다.
모든 요청을 가로채서 아래와 같은 흐름으로 동작합니다:

  1. 요청 수신 (예: /hello)
  2. 적절한 @Controller 찾기 (@RequestMapping("/hello"))
  3. 서비스/DB 호출 등 로직 실행
  4. 결과를 View 또는 JSON으로 반환
  5. 응답 반환

즉, DispatcherServlet은 직접 doGet(), doPost() 등을 구현하고
그 안에서 Spring Bean(Controller 등)을 찾아 실행합니다.

 


⚙️ 요청 처리 순서 (좀 더 자세히)

  1. 사용자가 /hello에 접속
  2. Tomcat은 이 요청을 서블릿에게 전달
  3. DispatcherServlet이 요청을 가로챔
  4. 등록된 HandlerMapping을 통해 어떤 @Controller가 처리할지 찾음
  5. 그 @Controller의 메서드 실행 (@RequestMapping, @GetMapping 등)
  6. 리턴값(View 또는 JSON 등)을 ViewResolver나 HttpMessageConverter를 통해 변환
  7. 응답 객체에 담아 사용자에게 전송

💡 핵심 클래스 요약

클래스/인터페이스설명
DispatcherServlet 모든 요청을 처리하는 Spring의 핵심 서블릿
HandlerMapping URL에 맞는 컨트롤러 찾기
HandlerAdapter 컨트롤러를 실제로 호출
ViewResolver JSP 등 뷰 이름을 실제 경로로 변환
HttpMessageConverter 객체를 JSON/XML로 바꿔주는 역할 (REST 응답용)
 

📦 DispatcherServlet도 결국 HttpServlet이다!

public class DispatcherServlet extends FrameworkServlet {
    // FrameworkServlet은 HttpServlet을 상속
}

👉 즉, DispatcherServlet도 결국 HttpServlet이기 때문에
Tomcat이 서블릿을 실행하는 구조 그대로 동작합니다.


✅ 요약 정리

질문답변
Spring은 서블릿을 쓰나요? ✅ 내부적으로 DispatcherServlet이라는 서블릿을 씁니다.
누가 실행하나요? Tomcat 같은 서블릿 컨테이너가 실행합니다.
우리는 왜 몰랐을까요? Spring이 복잡한 서블릿 설정을 자동으로 해주기 때문입니다.
DispatcherServlet의 역할은? 요청을 받아서 어떤 Controller가 처리할지 결정하고 응답까지 처리
 
728x90
반응형
LIST
728x90
SMALL

✅ 1. Tomcat이란?

Apache Tomcat은 Java 기반의 **웹 애플리케이션 서버(Web Application Server)**입니다.

Tomcat의 역할:

역할설명
📦 웹 애플리케이션 실행 .war 파일(웹 앱 패키지)을 실행
🌐 HTTP 요청 처리 클라이언트의 요청(예: 브라우저)을 받아 처리
🔁 서블릿 실행 서블릿을 실행하고 그 결과를 클라이언트에 반환
📜 JSP 처리 JSP(Java Server Pages)를 실행하고 HTML로 변환
 

핵심: Tomcat은 서블릿 컨테이너입니다!


✅ 2. 서블릿 컨테이너란?

💡 "서블릿 컨테이너 = 서블릿을 실행시키는 환경"

서블릿은 자바 코드로 작성된 웹 컴포넌트예요.
이 서블릿을 실행하려면 다음이 필요합니다:

  • HTTP 요청을 받고,
  • 서블릿 객체를 생성하거나 재사용하고,
  • doGet() / doPost() 같은 메서드를 호출하고,
  • 응답을 클라이언트로 전송하는

이 모든 작업을 처리하는 것이 바로 서블릿 컨테이너입니다.
Tomcat이 그 역할을 합니다.


✅ 3. 서블릿(Servlet)이란?

📘 정의:

Servlet은 Java EE(지금은 Jakarta EE)의 표준 인터페이스로, HTTP 요청을 받아 처리하고 응답을 생성하는 Java 클래스입니다.

🔍 한마디로 요약하면:

서블릿은 Java로 만든 웹 요청 처리기예요.

HTML이나 JSP는 주로 **화면(UI)**을 만드는 데 쓰이지만,
서블릿은 클라이언트의 요청을 받고 처리한 뒤 응답을 만들어 보내는 역할을 합니다.

 

🧩 서블릿의 위치 (웹 요청 흐름 예시)

   [브라우저] → [Tomcat(서블릿 컨테이너)] → [서블릿 클래스] → 응답 반환
 
  1. 브라우저가 /hello 요청
  2. Tomcat이 HelloServlet을 찾고 실행
  3. 서블릿이 doGet() 또는 doPost() 메서드에서 요청 처리
  4. 처리 결과(HTML, JSON 등)를 응답으로 보냄

🔧 예시 구조:

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws IOException {
        
        response.setContentType("text/html");
        response.getWriter().println("<h1>Hello from Servlet!</h1>");
    }
}

해석:

  • @WebServlet("/hello") → /hello로 요청이 오면 이 서블릿이 실행됨
  • doGet() → HTTP GET 요청을 처리
  • response.getWriter().println() → 브라우저에 출력할 내용 작성

🔁 서블릿의 생명주기 (Tomcat이 관리):

  1. 생성: 최초 요청 시 서블릿 객체가 만들어짐 (1번만 생성)
  2. 초기화: init() 메서드 호출
  3. 요청 처리: doGet() or doPost() 호출
  4. 종료: 서버 종료 시 destroy() 호출

이 덕분에 우리는 서블릿 객체를 직접 만들거나 관리하지 않아도 됩니다. Tomcat이 다 해줍니다!


📚 서블릿의 핵심 기능

기능설명
요청(Request) 받기 HttpServletRequest 객체 사용
응답(Response) 보내기 HttpServletResponse 객체 사용
파라미터 읽기 request.getParameter("name") 등
세션 관리 request.getSession()
리다이렉트/포워딩 response.sendRedirect(), RequestDispatcher.forward()
 

✅ 4. 왜 서블릿을 쓰는가?

  • 자바 코드로 동적 웹페이지를 만들 수 있다.
  • 요청/응답 흐름을 쉽게 제어할 수 있다.
  • 보안, 스레드, 세션 등을 관리하기 편하다.

✅ 5. JSP와 서블릿 차이

항목서블릿JSP
작성 방식 Java 코드 HTML + Java
용도 로직 중심 화면 중심
유지보수 어려움 쉬움
컴파일 미리 컴파일됨 최초 실행 시 서블릿으로 변환
 

👉 실제로 JSP도 결국 서블릿으로 변환되어 Tomcat에서 실행됩니다.


✨ 요약

개념설명
Tomcat 서블릿을 실행하는 서버 (서블릿 컨테이너)
서블릿 컨테이너 서블릿의 생명주기를 관리하고, HTTP 요청/응답을 처리
서블릿 자바로 만든 웹 처리기 – HTTP 요청을 받아 로직 수행 후 응답 생성
 
728x90
반응형
LIST

'Self Study > Others' 카테고리의 다른 글

WEB 과 WAS  (0) 2025.07.07
Spring 과 Servlet  (1) 2025.07.05
[Server] 서버 기본 LinuxOS 에서 timezone 설정하기  (0) 2024.08.19
728x90
SMALL

Docker를 기본 Linux 배포판으로 사용하고 compose 파일을 만들어서 올릴때 타임존 설정을 하지 않았더니 UTC로 설정되어있어서 시간대가 맞지 않아서 timezone 변경이 필요했다. 

그런데.....너무 기본 linux 배포판이라 yum 도 apt 도 동작하지 않았다....또륵... 

그렇게 해서 알아낸 타임존 수동 설정 방법 ㅠ


타임존 파일 수동 설정

타임존 데이터를 직접 다운로드하고 설정할 수 있습니다. 

 

1. 타임존 파일 다운로드

     타임존 데이터가 /usr/share/zoneinfo/Asia/Seoul 경로에 없다면, 직접 파일을 다운로드해야 합니다.

mkdir -p /usr/share/zoneinfo/Asia
wget -O /usr/share/zoneinfo/Asia/Seoul https://raw.githubusercontent.com/eggert/tz/master/Asia/Seoul

 

2. 타임존 설정

     다운로드한 타임존 파일을 /etc/localtime으로 링크하여 설정합니다.

ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime

3. 환경 변수 설정

환경 변수를 설정하여 타임존을 지정할 수 있습니다

 
echo "Asia/Seoul" > /etc/timezone 
export TZ="Asia/Seoul"

4. 설정 확인

date
#결과 -> Mon Aug 19 16:30:48 KST 2024

이 방법으로 타임존을 수동으로 설정할 수 있습니다. 만약 wget도 사용이 불가능하다면, 타임존 파일을 미리 다운로드해 컨테이너에 복사하는 방법도 있다. 

728x90
반응형
LIST

'Self Study > Others' 카테고리의 다른 글

WEB 과 WAS  (0) 2025.07.07
Spring 과 Servlet  (1) 2025.07.05
Tomcat, 서블릿 컨테이너, 그리고 서블릿  (0) 2025.07.03
728x90
SMALL

프로젝트 중 상사가 리팩토링한 코드 중에서 immutableMap 을 사용한 부분이 있었다. 

몇가지 지정된 객체들을 특정 메소드에 파라미터로 보내는 과정에서 해당 맵을 사용했는데 

처음 보는 맵의 종류라 정리하게 되었다. 


ImmutableMap 이란?

Map 의 종류이지만 이 맵은 한 번 만들어지면 그 안의 키와 값이 변경될 수 없는 특징이 있다.

즉, 이미 지정해둔 키와 값의 쌍을 수정하거나 삭제할 수 없으며, 새로운 키-값 쌍을 추가할 수도 없다.


⭐예제

/**첫번째 방법*/
ImmutableMap<String, Object> map = ImmutableMap.of("bean", _bean, "regDt", _bean.getRegDt());
         
/**두번째 방법*/        
ImmutableMap<String, Object> map2 = ImmutableMap.<String,Object>builder()
                                    .put("bean", _bean)
                                    .put("regDt", _bean.getRegDt())
                                    .build();

ImmutableMap 도 map 의 종류이기에 선언이나 사용법은 비슷하나, 위에 두가지로 가장 많이 쓰인다. 

1. 첫번째 방법 : 최대 10쌍의 값을 정의할 수 있어 간단하게 정의할 경우 쓰인가.

2. 두번째 방법 : 더 많은 쌍의 값을 정의할때 더 유연하고 가독성이 좋기에 많은 쌍을 정의할 때 쓰인다. 


⭐일반 Map 과의 차이점

 

  • 수정 불가: ImmutableMap는 한 번 생성되면 수정할 수 없다. put, remove 등의 메서드 사용 불가능
  • 생성 시점: ImmutableMap는 생성할 때 모든 키-값 쌍을 정의해야함.

 

/**맵 정의*/
ImmutableMap<String, Object> map = ImmutableMap.of("bean", _bean, "regDt", _bean.getRegDt());

/**수정 및 삭제 불가 */
// map.put("regDt", "2025-01-01"); // 컴파일 에러
// map.remove("bean"); // 컴파일 에러

⭐ImmutableMap 사용이유 

 

  • 안전성: 불변이기 때문에 데이터가 변경될 염려가 없다. 특히 여러 군데에서 같은 데이터를 참조할 때 유용하다.
  • 성능: 동기화가 필요 없기 때문에, 여러 스레드가 동시에 읽을 때 성능이 향상된다.
  • 예측 가능성: 데이터가 변경되지 않기 때문에 항상 같은 값을 유지한다. 

중요한 점

  • 맵 자체는 변경 불가: ImmutableMap에 추가, 수정, 삭제할 수 없습니다.
  • 내부 객체는 변경 가능: ImmutableMap에 저장된 객체가 가변 객체라면, 그 객체의 내부 상태는 변경될 수 있습니다.

 

 

728x90
반응형
LIST

'Self Study > Java' 카테고리의 다른 글

[JAVA] instanceof 연산자 : 인스턴스의 타입을 확인  (0) 2024.07.01
728x90
SMALL

프로젝트에서 코드를 리팩토링 하는 과정에서 

같은 연산을 하지만은 상속받는 bean 이 다른 두개의 메소드가 있었다. 

물론 다른 패키지 내부의 dao 에서 연산을 하는 것이라 별다른 리팩토링 필요성을 못느꼈는데 

같은 연산을 두 패키지 뿐만 아니라 다른 곳에서도 쓰일 가능성을 보고 Util로 옮기며 intanceof 연산자를 사용하게 되었다. 


intanceof 연산자란? 

사용하는 이유 : 개체가 어떤 클래스인지, 어떤 클래스를 상속받았는지, 즉 인스턴스의 실제 타입을 알아보기 위해 사용

결과 : boolean (true 또는 false) 

⭐문법

object instanceOf type

object 가 내가 확인하고 싶은 객체이고 type이 비교 대상이다. 

object == type 또는 type을 상속받는 다면 true, 아닐경우 false 를 반환한다. 


⭐예제

class Parent{}

class Child extends Parent{}

public class intanceOfExample {
    public static void main(String[] args){
        Parent parent = new Parent();
        Child child = new Child();

        System.out.println( parent instanceof Parent );  // true
        System.out.println( child instanceof Parent );   // true
        System.out.println( parent instanceof Child );   // false
        System.out.println( child instanceof Child );   // true
    }
}

child 는 부모님 parent 를 상속받기에 true 이지만, parent는 child를 상속받지 않기에 false 가 나온다. 

물론 child끼리 parent 끼리 instanceof 연산자로 확인할 경우에는 같은 클래스이기에 true 가 나온다. 


이 처럼 한 메소드에서 혹 특정 bean 을 특정지어서 분기처리를 해야한다면 유용하게 쓰일 수 있는 연산자같다. 

728x90
반응형
LIST

'Self Study > Java' 카테고리의 다른 글

[JAVA] ImmutableMap : 변경 불가능한 맵(Map)  (1) 2024.07.08

+ Recent posts