-
Context 란 무엇인가?컴퓨터 2008. 5. 15. 11:29
개발자라면 context 라는 단어를 한번쯤은 모두 접해 보았을 것입니다. 그런데 context가 뭐냐? 누군가 이렇게 물어본다면 딱히 대답하기가 힘들죠. 사용만 할 줄 알지 정확히 개념이 서지 않아서 그렇습니다.
서블릿은 누군가에 의해 한번 호출되어 로드되거나 혹은 서블릿엔진 시작시에 로드(load) 될 수 있습니다. 한번 로드된 서블릿은 메모리에 로드된 채 남아 있습니다. 이 때 또 다시 다른 사람에 의해 그 서블릿이 호출되면 file에서 다시 읽어들이는 것이 아니라 이미 로드된 서블릿을 사용하여 빠르게 응답하게 됩니다.Context 란 용어는 어떤 한글번역본에는 "문맥"이란 용어로 직역됩니다만 사실 적절한 의미전달은 안되고 있습니다. C++ 언어에서 보면, Print을 하기 위해 PrintContext 객체를 사용하고, Java Applet에서 Applet의 AppletContext를 얻기 위해 Applet.getAppletContext()를 사용하지요. 결국 "Context"란 "어떤 객체를 핸들링하기 위한 접근 수단"의 의미를 가집니다. 위에서 해당 서블릿을 수행하려면 "서블릿 Context"를 획득해야 그것을 통해 그 서블릿을 수행할 수 있는 것이지요.
서블릿은 CGI와는 다르게 멀티쓰레드(Multi-thread)로 동작합니다. 한 순간에 하나의 수행만 있는 것이 아니라, 같은 서블릿이 여러 client의 호출에 대해 동시다발적으로 같이 수행되는 구조이지요.
서블릿의 호출에 대해 실질적인 수행을 해주는 녀석이 "Servlet Invoker" 입니다. 이 Servlet Invoker는 말그대로 별도의 쓰레드로 동작합니다. 서블릿 엔진의 가장 근본적인 역할이지요. 즉, "Servlet Invoker"는 별도의 쓰레드로 동작하면서 누군가가 어떤 서블릿을 호출하면 이미 메모리에 로드된 해당 서블릿의 Context(!)를 얻어내어, 그 서블릿에 당연히 있는 아래의 메소드를 호출시켜 줍니다.
public void service(ServletRequest req, ServletResponse res) throws ...."service 메소드"를 호출시켜 주는 거지요.
public void service( ... req, ... res ) 메소드는 기본적으로 multi-thread로 호출됩니다. 즉, 해당 서블릿을 많은 사람이 동시에 호출하면, 호출된 갯수만큼 새로운 쓰레드가 만들어지면서( 별도의 프로세스가 뜨는 것이 아닙니다.) 해당 service() 메소드내로 동시에 같이 막 들어 옵니다.예를 들어 아래의 경우를 생각해 보겠습니다.
public class MyServlet extends .....
private int count = 0;
public void service ( .... req, ... res ) throws ....
{
count ++;
....
}
}이 서블릿을 여러사람이 동시에 막 같이 호출하면 count 값이 어떻게 될까요? 각 client는 한번씩 호출했지만, 다른 사람도 같이 호출했기에, 메모리 상의 같은 공간에 있는 count 값은 client가 호출한 갯수만큼 증가 될 것입니다.
따라서 해당 서블릿이 global 변수(엄밀히 global 변수가 아니라 instance변수죠)를 사용하고 있는 경우는 반드시 Multi-treading 을 염두에 두면서 개발하셔야 합니다.
흔히들 실수하는 부분이 DB Connection을 Servlet의 init()부분에서 맺어 두고 public void service(... req, ... res)에서 그 DB Connection을 이용해 DB SQL작업을 하는 경우입니다. 이 경우, 여러 client가 같은 DB Connection 을 공유하기 때문에 주의하지 않으면 DB Transaction 이 얽힐 수가 있는 거지요...그런데...., Servlet을 "정의"하실 때, SingleThreadModel을 implements 하면, 해당 서블렛은 Multi-Thread로 동작하지 않고 한 순간에 하나의 Client만이 service() 메소드 내로 들어오는 것을 보장해 줍니다.
즉,
public class MyServlet extends HttpServlet이라 하지 않고,
public class MyServlet extends HttpServlet implements SingleThreadModel
라고만 하면, "Servlet Invoker"는 해당 서블렛을 Single Thread 형식으로 동작시켜 줍니다. 한순간에 하나씩 service() 메소드가 호출되는 거죠...