본문 바로가기
웹 프로그래밍/Servlet & JSP

Servlet 지역 변수와 멤버 변수의 차이점

by kgvovc 2021. 3. 11.
반응형

서블릿 변수

 

서블릿 동시 요청

웹 프로그램을 개발하는 방식은 두 가지가 있습니다. 웹서버의 직접적인 호출로 실행하는 CGI 방식애플리케이션 서버가 실행하는 방식입니다. 지금 학습하고 있는 서블릿은 서블릿 컨테이너라고 하는 웹 애플리케이션 서버가 실행하는 방식입니다. CGI와 서블릿 실행 방식은 서로 다른데요. 두 가지 방식의 차이점에 대해 알아보겠습니다.

 

[CGI 프로그램 실행 방식]

CGI 프로그램 실행 방식

사진 출처: https://tmxhsk99.tistory.com/134

 

CGI 프로그램은 클라이언트로부터 요청이 들어올 때마다 독립적인 프로세스가 만들어지며, 메모리에는 프로세스를 실행하기 위한 데이터가 로딩됩니다.

 

이러한, CGI 실행 방식은 여러 사용자 요청이 빈번한 성격의 웹 서비스로는 적합하지 않습니다. 왜냐하면 클라이언트의 요청 수에 비례하여 프로세스가 만들어지고 그만큼 메모리 사용량도 함께 증가하기 때문입니다. 따라서 대량의 트래픽이 발생할 수 있는 서비스에는 서버에 부하가 가중될 수 있습니다.

 

 

[서블릿 실행 방식]

서블릿 실행 방식

사진 출처: https://tmxhsk99.tistory.com/134

 

 

서블릿은 최초 요청일 때 프로세스를 만들고 서블릿 요청이 있을 때마다 그 안에 스레드를 만들어서 service() 메소드를 실행하며, 두 번째 이후의 요청부터는 이미 만들어진 프로세스 안에 service() 메소드를 실행하기 위한 스레드만 새로 생성한 다음, 이 스레드 안에서 service() 메소드를 실행합니다.

 

이것이 CGI 프로그램의 실행 방식과의 차이점입니다. CGI 프로그램요청할 때마다 독립적으로 프로세스를 만들어서 실행하지만, 서블릿최초 요청 시 하나의 프로세스를 생성하고 이후부터는 이 프로세스 안에 스레드만 새로 생성하여 실행합니다. 그래서 CGI 프로그램 실행 방식보다 서블릿 실행 방식이 서버 부하나 메모리 사용 면에서 훨씬 효율적입니다.

 

 

 

서블릿 변수 특징

서블릿을 개발하면서 변수를 사용할 때 멤버변수인지 지역변수인지 구분하여 사용할 수 있어야 합니다. 하나의 서블릿에 여러 클라이언트가 공유해서 사용해야 하는 데이터는 멤버변수로 선언하며, 각각의 클라이언트가 독립적으로 사용해야 하는 데이터는 지역변수로 선언해야 합니다.

 

서블릿은 하나의 프로세스를 생성한 다음, 동일한 서블릿을 요청하는 클라이언트에 대하여 공통적인 프로세스를 사용하며 service() 메소드를 실행하기 위한 스레드만 클라이언트별로 독립적으로 생성하여 실행합니다.

 

다음 그림은 앞에서 살펴본 서블릿 실행 방식의 그림에서 힙 메모리와 스택 메모리를 표시한 그림입니다.

 

 

멤버변수는 객체 생성 시 메모리에 생성되며 서블릿을 실행하는 클라이언트들이 공통으로 사용합니다. 그러나 service() 메소드가 사용하는 지역변수스택 메모리에 생성되며, 클라이언트마다 독립적으로 사용하는데요. 이는 서블릿의 service() 메소드를 실행하는 스레드마다 스택 메모리가 독립적이기 때문입니다. 따라서 지역변수는 클라이언트마다 별개로 사용됩니다.

 

 

서블릿 지역 변수

서블릿의 지역 변수는 여러 클라이언트가 동시에 요청했을 때, 요청마다 개별적으로 할당됩니다. 그러므로 각 클라이언트의 요청 수만큼 메모리 영역을 개별적으로 할당하여 지역적으로 처리할 때만 지역변수를 선언하여 활용합니다.

 

다음은 서블릿의 지역변수 특성을 확인하는 예제입니다. 새로운 서블릿 LocalTestServlet을 작성합니다.

 

package com.edu.test;

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;


@WebServlet("/local")
public class LocalTestServlet extends HttpServlet{
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int number = 0;
		String str = req.getParameter("msg");
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.println("<html><head><title>MultiThread Test</title></head>");
		out.println("<body><h2>처리 결과(지역 변수)</h2>");
		while(number++ < 10) {
			out.print(str + " : " + number + "<br>");
			out.flush();
			System.out.println(str + " : " + number);
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				System.out.println(e);
			}
		}
		
		out.println("<h2>Done " + str + " !!</h2>");
		out.println("</body></html>");
		out.close();
	}
}

 

 

위의 URL들에 동시에 접속하면 아래와 같은 결과가 나온다.

 

[실행 결과]

 

 

클라이언트가 보낸 질의 문자열 mst의 값을 추출하여 저장하는 변수 str을 지역변수로 선언했습니다. 그래서 각 스레드의 스택 영역에 별도의 str 변수가 클라이언트별로 만들어져 사용되므로 한 클라이언트가 str 변숫값을 수정해도 다른 클라이언트에게는 영향을 미치지 않습니다.

 

 

서블릿 멤버 변수

동일한 서블릿을 여러 클라이언트가 동시에 요청했을 때 서블릿 객체는 하나만 생성되어 멀티 스레드로 동작하므로 서블릿의 멤버변수는 여러 클라이언트가 공유하게 됩니다. 그러므로 각 클라이언트들의 동시 요청 수와 관계없이 하나의 메모리 공간을 할당하여 전역적으로 처리할 때만 멤버변수를 선언하여 활용합니다.

 

다음은 서블릿의 멤버변수 특성을 점검하는 예제입니다.

 

새로운 서블릿 MemberTestServlet을 작성합니다.

package com.edu.test;

import java.io.*;
import javax.servlet.http.*;
import javax.servlet.*;
import javax.servlet.annotation.WebServlet;


@WebServlet("/member")
public class MemberTestServlet extends HttpServlet{
	String str; 
	
	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		int number = 0;
		str = req.getParameter("msg");
		resp.setContentType("text/html;charset=UTF-8");
		PrintWriter out = resp.getWriter();
		out.println("<html><head><title>MultiThread Test</title></head>");
		out.println("<body><h2>처리 결과(지역 변수)</h2>");
		while(number++ < 10) {
			out.print(str + " : " + number + "<br>");
			out.flush();
			System.out.println(str + " : " + number);
			try {
				Thread.sleep(1000);
			} catch (Exception e) {
				System.out.println(e);
			}
		}
		
		out.println("<h2>Done " + str + " !!</h2>");
		out.println("</body></html>");
		out.close();
	}
}

 

 

 

위의 URL들에 동시에 접속하면 아래와 같은 결과가 나온다.

 

[실행 결과]

 

 

 

예제의 처리 결과를 보면 이전의 지역변수 예제와 다릅니다. str 변수는 멤버변수로 선언하였기 때문에 객체 생성 시 힙 영역에 만들어진 후 모든 클라이언트가 공유합니다.

반응형

댓글