http://www.daesangit.com/ditboard/board/read.cgi?board=oralib&y_number=46&nnew=2


   ▒   자료실   ▒    

 이름 관리자 
 등록일 2002/9/21(토) 20:33 
 
 서블렛 + JDBC 연동시 코딩 고려사항 ①   
서블렛에서 instance variable의 공유 - PrintWriter - 

다음과 같은 코드가 있다고 가정하자. 

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

public class CountServlet extends HttpServlet {
  private PrintWriter out = null; // <-------------- (1)

  public void doGet(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException
{
    res.setContentType("text/html");
    out = res.getWriter();
    for(int i=0;i<20;i++){
      out.println("count= " + (i+1) + "
"); // <---- (2)
      out.flush();
      try{Thread.sleep(1000);}catch(Exception e){}
    }
  }
}

위의 CountServlet.java를 컴파일해 돌려 보면 1초 간격으로 일련의 숫자가 올라가는 것이 보인다. 서블렛 엔진의 구현방식에 따라 Buffering 이 되어 20초가 모두 지난 다음에야 퍽이 나올 수도 있다. 

혼자서 단일 Request를 날려 보면 아무런 문제가 없겠지만, 이제 브라우져 창을 두개 이상 띄우고 10초의 시간 차를 두시면서 동시에 호출하면 이상한 증상이 나타난다. 먼저 호출한 창에는 10까지 정도만 나타나고, 10초 뒤에 호출한 창에서는 먼저 호출한 창에서 나타나야 할 내용까지 나타난다.

이는 서블렛의 각 호출은 Thread로 동작해 각 호출은 위의 (1) 에서 선언한 instance variable 들을 공유하기 때문에 나타나는 문제이다. 

위 부분은 다음과 같이 고쳐져야 합니다.

public class CountServlet extends HttpServlet {
  //private PrintWriter out = null;

  public void doGet(HttpServletRequest req, HttpServletResponse res) 
    throws ServletException, IOException
  {
    PrintWriter out = null; // <--- 이 쪽으로 와야죠 !!!
    res.setContentType("text/html");
    out = res.getWriter();
    for(int i=0;i<20;i++){
      out.println("count= " + (i+1) + "
"); // <---- (2)
      out.flush();
      try{Thread.sleep(1000);}catch(Exception e){}
    }
  }
}

국내 일부 서블렛 관련 서적의 일부 예제에서 위와 같이 잘못된 형태로 설명한 소스코드가 발견된다. 실제 프로젝트 환경에서 개발된 실무 시스템에서도, 이러한 책을 통해 공부한 것처럼 동일하게 잘못된 코딩을 하고 있는 개발자가 있다. 

결과적으로 테스트 환경에서는 나타나지 않더니만, 막상 시스템을 오픈하고나니 고객으로 부터 다음과 같은 소리를 듣게된다. "다른 사람의 데이터가 내 화면에 나타나는 경우가 간혹 있다. refresh를 눌러야 제대로 나타난다" @ 
