동접자 100명 가량 되는 이벤트 페이지 개발 중 알게된 사실들입니다.
저는 Spring에 환멸과 회의를 느껴 개발 3~4년 차 때 과감히 스프링을 버리고
톰캣 제공 Servlet과 Filter를 이용해서 사이트 설계를 하는 사람입니다.
Class가 아닌 jsp 파일에서 서비스처리를 한다는 가정 하에 설명드리는 글이오니 참고 부탁드립니다.
때문에 Spring 을 이용해 사이트를 설계하시는 분들과는 맞지 않는 내용이니 지나가시면 됩니다.
----------
보통 제가 만든 웹프로젝트의 경우
1. Controller : /WEB-INF/controllers/**/*.jsp
2. View : /WEB-INF/veiws/**/*.jsp
의 형식을 띄고 있습니다.
컨트롤러 자체가 Class레벨인 경우에는 Thread Safe 처리가 어렵지 않은 반면
jsp 자체를 컨트롤러로 사용할 경우에는 Thread Safe 처리가 상당히 난해해집니다.
이런 구조의 웹사이트 동접자가 많은 경우
예상치 못한 Exception 과 동기화가 되지 않은 데이터들을 자주 보게 됩니다.
( 넘넘 자주 )
홍길동이 이벤트에 참여했는데, 김복순이라는 사람에게
"홍길동님! 이미 참여하셨으니 더는 안됩니다..." 라는 화면이 나오면
컴플레인이 빗발치고, 그러면 키보드에서 손을 놓고싶어집니다.
클라이언트에게 무지막지하게 깨져가면서 똥줄 타면서 알아낸 사실들이니 믿을만 합니다.
추후 저와 같은 실수를 방지하기 위해 넘어가는 글로 보는 사람들이 있었으면 합니다.
1. DBCP 사용 시 굳이 Connection 은 닫지 않아도 된다.
(이 부분은 논란의 여지가 있을거 같다.)
- 나는 무조건 close 해야 한다는 입장을 고수했다.
그러다 우연히 Stress Test 하던 중 Thread를 이용해 1000 Connection 을
동시에 접속하고 해제하고를 수십번 반복하는 과정에서
open & close 에 동기화 문제가 발생하는 것을 발견했고,
close 대신 delegate 에 null 을 대입하는 방식으로 close를 구현했더니
모든 커넥션에 동기화 문제가 말끔히 해결됐다. DB서버의 리소스도 멀쩡했다.
다만, DataSource에서 Connection을 가져올 때 동기화를 해줘야 하고
또한 트랜잭션을 사용할 경우 "트랜잭션 동기화"는 반드시 해줘야 한다.
2. JSP - Controller 페이지를 isThreadSafe="true"로 했을 경우 ( true가 기본값, 생략 가능 )
1) 페이지가 멀티쓰레드로 인식되어 접속자마다 쓰레드가 생성된다.
2) 선언부 영역 객체들의 데이터 간섭이 심하게 일어난다.
- 해당 페이지에 사용되는 데이터 처리 객체는 Thread-Safe 처리를 해야 한다.
- 그렇지 않을 경우 각 데이터에 대한 신뢰성은 보장할 수 없다.
3. JSP - Controller 페이지를 isThreadSafe="false"로 했을 경우
1) true로 지정했을 때보다 Exception 분기가 월등히 수월해진다.
- 페이지가 싱글쓰레드로 작동하게 되면 데이터간섭이 일어나지 않아,
예상된 Exception 만으로 처리할 수 있게 된다.
2) 선언부 영역 객체들의 데이터 간섭이 일어나지 않는다.
3) 안심하고 파라미터 가공을 할 수 있다.
아이러니 하게도 isThreadSafe="true" 는 전혀 Thread-Safe 하지 않았다....
https://www.tutorialspoint.com/what-is-isthreadsafe-attribute-in-jsp 에 의하면
isThreadSafe 라는 지시어는 Thread-Safe 한 페이지인지 아닌지를 구분하는 역할이라 한다.
즉, isThreadSafe="true" 라고 지정해놓고 코드 자체가 Thread-Safe 하지 않다면
해당 페이지의 동시접속자가 20~30명만 되어도 이벤트의 결과는 참담하다.
----------
이벤트 페이지만 열면 밀려오는 동접자로 인해 곤란한 상황에 처하신 분들이 종종 있습니다.
여러분들이 기억해야 할 것은, 동접자가 몰려오는 페이지를 isThreadSafe="true" (디폴트) 로 지정해놓으면,
해당 페이지에서 사용되는 객체들의 Thread-Safe 처리를 반드시 해줘야 하며,
그럴 자신이 없으면 저처럼 해당 페이지의 지시어에 isThreadSafe="false" 를 꼭 추가해주세요.
View페이지에는 isThreadSafe="true" 로 선언해주셔도 무방합니다.
조금 늦게 처리되더라도 데이터 안전성이 우선입니다.
그리고 성능면에서 크게 불리하지도 않습니다.
해당 페이지를 Thread-Safe 하게 작성하게 되면 결과론적으론 Thread 의 lock 이 반드시 일어나기 때문에
속도 저하를 감수해야 합니다. 그냥 맘 편하게 false 로 주시면 해결됩니다.