JSP - 2. 웹서버 vs. WAS, 서블릿 vs. JSP

갓김치·2020년 11월 19일
0

JSP+Spring

목록 보기
2/43

서버

  • 포트의 갯수만큼 문을 열어놓고 있는 것
  • 서버의 역할
    • 첫번째 역할! : 클라이언트의 요청 대기
    • 24시간 포트(ex. 80)를 감지하다가 특정 포트에 요청이 들어오면요청을 분석하고 컨텐츠를 분석한 후 응답데이터 스트림을 감지한후 응답을 내보내는 역할
  • 개발자가 할 일: 80포트를 감시할 데몬스레드를 개발해야한다
    • 중프때는 톰캣이라는 서버가 그 역할을 해줌
  • 톰캣=미들티어

웹서버

  • 정적 요청 담당
    • 서버상에 존재하는 파일 요청
    • 예) 클라이언트가 서버에게 a.jpg, bb.mp3, ccc.docx 요청,...
  • 종류: IIS, NGIX, APACHE...
  • 하는 일
    • 요청이 들어 오면 요청을 분석해서 파일이 있나 없나 확인
    • 서버에 자원이 있으면 스트림으로 변환해서 응답을 보냄
    • 서버에 자원이 없으면 없다고 응답 (404 NOT FOUND)
  • 처리할 수 없는 경우?
    • 문제의 원인이 클라이언트일 수도, 서버일수도 있다.
    • 이런 다양한 상황에 대해 상태코드를 내보내야한다.
    • 웹개발자는 상태코드의 종류가 뭐가 있고 어떻게 핸들링해야할지 생각해야함. (HTTP★)

CGI: 처음만들어 진것

예시

  • 오늘몇시야? (동적요청)
  • 파일찾으러감
  • 파일없음
  • 처리할 수 없는 상태가 되버림
  • 그럼 우리는 웹서버한테 동적요청을 처리할 수 있는 기능을 만들어줘야함

설명

  • 요청받는순간 동적 요청을 처리할 수 있는 어플리케이션을 구동시킨후 중개해서 응답을 내보냄
  • 문제점
    • 동적요청 1000개가 들어오면 1000개 어플리케이션이 실행됨
    • = 하나의 요청당 하나의 프로세스가 실행됨
    • = 자원낭비
    • = 시스템부하
    • = 동시처리요청갯수 제한됨
    • = "동시 접속자 수가 많아 서버가 부하가 걸려있는 상태입니다. 당신의 요청을 처리할 숫 없으니 나중에 다시 들어오세요."

웹어플리케이션서버 WAS

  • 형태가 바뀌는 동적인 요청
    • 오늘자 주가현황, 오늘자 날짜, 이번달의 베스트셀러...
  • WAS의 역할
    • 웹어플리케이션의 운영
  • 내가 감당할 수 있는 요청인지를 어떻게 톰캣이 확인할까?
    • 1) url-pattern 확인
    • 2) servlet-name 확인
    • 3) 클래스의 싱글톤 객체가 만들어져있는지 확인 후, 없다면 객체생성
    • 4) thread pulling(만들어져있는 스레드중에 하나를 꺼내, 풀에서 하나 할당을 받는다) 콜백메서드 호출해서, doGet실행

확장CGI: 요즘 방식

  • 웹서버가 동적요청을 받고 처리할 수 없으니 뒤에 있는 WAS에게 위임
  • WAS가 요청을 처리할 수 있는지 확인, 처리가능하면 해당 요청을 처리할수있는 스레드를 돌리고 어플리케이션 돌려서 응답데이터돌린다음에 웹서버에게 줌. 그럼 웹서버가 다시 그걸받아서 클라이언트에게 전달
  • 미들티어가 2개로 쪼개짐

예시

  • KTX예매대기방식: 앞에 몇명있습니다

설명

  • 서블릿, 스레드, 확장CGI방식
  • 하나의 리퀘스트당 하나의 스레드가 실행
  • 어플리케이션은 하나(프로세스하나)만 실행되지만 요청처리하는 스레드를 계속 쪼갬
  • 멀티스레드 = 자원소모줄임 = 동시처리 요청갯수가 늘어남
  • 확장CGI를 위해 ASP, PHP도 있는데 왜 서블릿과 JSP를 쓸까?
    • Java기반이기때문에
      • 자바 기반의 장점은? 이식성
      • c언어: exe로 실행해야함 -> 윈도우 OK, 리눅스 NO = 플랫폼에 종속성이있음.
      • Java: 윈도우에서 개발하고 리눅스에 배포해도 잘 돌아감 (버추얼머신만 있으면 그위에서 돌아간다)
      • Java는 개발이 쉽다. -> 개발과정에서 필요한 재료를 구하기 쉽다 = api 생태계가 넓다

티어

  • Tier: 클라이언트 서버시스템의 구조 (=/=Peer: 양끝단의 단말)
    • 클라이언트(1티어), 웹서버(2티어), 중간의 WAS(3티어)
    • 정적요청처리시 2티어, 동적은 최소3티어
    • 이번 달의 베스트셀러목록: DB가 필요하기때문에 DB까지 4티어
      • 해당 요청을 위해서는 데이터 가공이 필요함
      • raw data는 db에 있음
      • WAS의 어플리케이션이 db의 데이터를 가져와 가공하고 뷰를 만들어서 응답을 내보내야함
      • 이런 4티어 구조를 N-tier 구조라고함
  • 동적어플리케이션 구동을 위해서는 적어도 N-tier이상이 필요함
    • 규모가 큰 시스템은 트래픽분산을 위해 4티어 사용
    • 우리가 톰캣만 쓰는 이유: WAS가 정적요청도 처리할 수 있기때문에

어플리케이션

스탠드얼론 어플리케이션

  • 초급프로젝트
  • 네트워크 고려할 필요 x
  • 단독으로 설치 가능한 어플리케이션

웹어플리케이션

  • 웹이라는 공간에 대한 이해 필요
  • 미들티어로 동작하는 서버가있기때문에 웹개발자가 상대적으로 쉽게 개발할 수 있음
  • 개발환경 셋팅시 서버를 생각해야하는 이유 : 미들티어로서의 역할을 맡기기 위해

이클립스 없이 개발하기

    • 독베이스는 웹서버상클라이언트에게 제공하기위한 가상경로
    • 독베이스 이후로는 파일경로와 url이 일치
    • WEB-INF내의 자원
      • 서버에서만 접근할 수 있는 자원
      • 클라이언트는 접근불가
      • 톰캣의 금고,

web.xml

    • web-app태그 : root element

클래스패스: 클래스 검색할 때 시작위치

  • 우리가 어떤 클래스를 사용한다며 반드시 클래스패스 이후부터의 모든 경로를 사용해야함
  • qualified name: 클래스 패스 이후의 경로

HelloJava.java

  • D:\>java -classpath d:\standalone kr.or.ddit.HelloJava
  • D:\>set classpath=d:\standalone
    • set: 윈도우명령어, 환경변수설정시 사용, 콘솔닫으면 사라짐
  • D:\>javac d:\standalone\HelloJava.java -encoding UTF-8 -d D:\standalone
    • 한글로 내용바꾸고 재컴파일
  • D:\>java kr.or.ddit.HelloJava
    • java와 kr사이에 -classpath는 이미 환경변수로 설정하고있어서 안써줘도됨

cmd창

Microsoft Windows [Version 10.0.18363.1198]
(c) 2019 Microsoft Corporation. All rights reserved.

C:\Users\PC-02>d: 

<!-- 해당경로로 ㄱㄱ -->
D:\>cd standalone 

<!-- 자바 컴파일러버전확인 -->
D:\standalone>javac -version 
javac 1.7.0_80

<!-- UTF-8로 컴파일 -->
D:\standalone>javac HelloJava.java -encoding UTF-8

<!-- 디렉터리 정보확인 -->
D:\standalone>dir
 D 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 0EE7-ADA3

 D:\standalone 디렉터리

2020-11-19  오전 10:37    <DIR>          .
2020-11-19  오전 10:37    <DIR>          ..
2020-11-19  오전 10:37               431 HelloJava.class
2020-11-19  오전 10:36               166 HelloJava.java
2020-11-19  오전 10:21    <DIR>          kr
               2개 파일                 597 바이트
               3개 디렉터리  977,665,257,472 바이트 남음
               
<!-- del: 해당 파일 삭제 -->
D:\standalone>del HelloJava.class 

<!-- 클래스패스 설정하여 컴파일 -->
D:\standalone>javac HelloJava.java -encoding UTF-8 -d .

D:\standalone>dir
 D 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 0EE7-ADA3

 D:\standalone 디렉터리

2020-11-19  오전 10:41    <DIR>          .
2020-11-19  오전 10:41    <DIR>          ..
2020-11-19  오전 10:36               166 HelloJava.java
2020-11-19  오전 10:41    <DIR>          kr
               1개 파일                 166 바이트
               3개 디렉터리  977,665,257,472 바이트 남음

D:\standalone>cd kr\or\ddit

D:\standalone\kr\or\ddit>dir
 D 드라이브의 볼륨에는 이름이 없습니다.
 볼륨 일련 번호: 0EE7-ADA3

 D:\standalone\kr\or\ddit 디렉터리

2020-11-19  오전 10:41    <DIR>          .
2020-11-19  오전 10:41    <DIR>          ..
2020-11-19  오전 10:41               431 HelloJava.class
               1개 파일                 431 바이트
               2개 디렉터리  977,665,257,472 바이트 남음

D:\standalone\kr\or\ddit>cd ../../../

D:\standalone>java HelloJava
오류: 기본 클래스 HelloJava을(를) 찾거나 로드할 수 없습니다.

D:\standalone>java kr.or.ddit.HelloJava
Hello Java
D:\standalone>cd ..

D:\>java kr.or.ddit.HelloJava
오류: 기본 클래스 kr.or.ddit.HelloJava을(를) 찾거나 로드할 수 없습니다.

D:\>java standalone.kr.or.ddit.HelloJava
Exception in thread "main" java.lang.NoClassDefFoundError: standalone/kr/or/ddit/HelloJava (wrong name: kr/or/ddit/HelloJava)
        at java.lang.ClassLoader.defineClass1(Native Method)
        at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
        at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
        at java.net.URLClassLoader.defineClass(URLClassLoader.java:449)
        at java.net.URLClassLoader.access$100(URLClassLoader.java:71)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:361)
        at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
        at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
        at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:482)

D:\>java
사용법: java [-options] class [args...]
           (클래스 실행)
   또는  java [-options] -jar jarfile [args...]
           (jar 파일 실행)
여기서 options는 다음과 같습니다.
    -d32          사용 가능한 경우 32비트 데이터 모델을 사용합니다.
    -d64          사용 가능한 경우 64비트 데이터 모델을 사용합니다.
    -server       "server" VM을 선택합니다.
    -hotspot      "server" VM의 동의어입니다[사용되지 않음].
                  기본 VM은 server입니다..

    -cp <디렉토리 및 zip/jar 파일의 클래스 검색 경로>
    -classpath <디렉토리 및 zip/jar 파일의 클래스 검색 경로>
                  클래스 파일을 검색할 ;(으)로 구분된 디렉토리,
                  JAR 아카이브 및 ZIP 아카이브 목록입니다.
    -D<name>=<value>
                  시스템 속성을 설정합니다.
    -verbose:[class|gc|jni]
                  상세 정보 출력을 사용으로 설정합니다.
    -version      제품 버전을 인쇄한 후 종료합니다.
    -version:<value>
                  실행할 버전을 지정해야 합니다.
    -showversion  제품 버전을 인쇄한 후 계속합니다.
    -jre-restrict-search | -no-jre-restrict-search
                  버전 검색에서 사용자 전용 JRE를 포함/제외합니다.
    -? -help      이 도움말 메시지를 인쇄합니다.
    -X            비표준 옵션에 대한 도움말을 인쇄합니다.
    -ea[:<packagename>...|:<classname>]
    -enableassertions[:<packagename>...|:<classname>]
                  세분성이 지정된 검증을 사용으로 설정합니다.
    -da[:<packagename>...|:<classname>]
    -disableassertions[:<packagename>...|:<classname>]
                  세분성이 지정된 검증을 사용 안함으로 설정합니다.
    -esa | -enablesystemassertions
                  시스템 검증을 사용으로 설정합니다.
    -dsa | -disablesystemassertions
                  시스템 검증을 사용 안함으로 설정합니다.
    -agentlib:<libname>[=<options>]
                  <libname> 고유 에이전트 라이브러리를 로드합니다(예: -agentlib:hprof).
                  -agentlib:jdwp=help 및 -agentlib:hprof=help도 참조하십시오.
    -agentpath:<pathname>[=<options>]
                  전체 경로명을 사용하여 고유 에이전트 라이브러리를 로드합니다.
    -javaagent:<jarpath>[=<options>]
                  Java 프로그래밍 언어 에이전트를 로드합니다. java.lang.instrument를 참조하십시오.
    -splash:<imagepath>
                  이미지가 지정된 스플래시 화면을 표시합니다.
자세한 내용은 http://www.oracle.com/technetwork/java/javase/documentation/index.html을 참조하십시오.

<!-- -classpath <디렉토리 및 zip/jar 파일의 클래스 검색 경로> -->
D:\>java -classpath d:\standalone kr.or.ddit.HelloJava
Hello Java <!-- 소스 내 print 구문 잘 출력됨-->

<!-- class path를 d:\standalone 으로 설정: 콘솔창 닫으면 초기화-->
D:\>set classpath=d:\standalone

<!-- 윈도우 환경설정값 -->
D:\>set
ALLUSERSPROFILE=C:\ProgramData
APPDATA=C:\Users\PC-02\AppData\Roaming
CATALINA_HOME=D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37
classpath=d:\standalone <!-- ★ -->
CommonProgramFiles=C:\Program Files\Common Files
CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files
CommonProgramW6432=C:\Program Files\Common Files
COMPUTERNAME=DESKTOP-67906HQ
ComSpec=C:\Windows\system32\cmd.exe
DriverData=C:\Windows\System32\Drivers\DriverData
FPS_BROWSER_APP_PROFILE_STRING=Internet Explorer
FPS_BROWSER_USER_PROFILE_STRING=Default
HOMEDRIVE=C:
HOMEPATH=\Users\PC-02
JAVA_HOME=D:\B_Util\2.Java\JDK1.8
LOCALAPPDATA=C:\Users\PC-02\AppData\Local
LOGONSERVER=\\DESKTOP-67906HQ
NUMBER_OF_PROCESSORS=8
OneDrive=C:\Users\PC-02\OneDrive
OS=Windows_NT
Path=d:\Anaconda3;d:\Anaconda3\Library\mingw-w64\bin;d:\Anaconda3\Library\usr\bin;d:\Anaconda3\Library\bin;d:\Anaconda3\Scripts;D:\B_Util\4.Oracle\appClient;D:\B_Util\4.Oracle\app\oracle\product\11.2.0\server\bin;D:\B_Util\2.Java\JDK1.7\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;D:\B_Util\Git\cmd;C:\Program Files\TortoiseSVN\bin;C:\Users\PC-02\AppData\Local\Microsoft\WindowsApps;C:\Program Files\Bandizip\
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PROCESSOR_ARCHITECTURE=AMD64
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 158 Stepping 13, GenuineIntel
PROCESSOR_LEVEL=6
PROCESSOR_REVISION=9e0d
ProgramData=C:\ProgramData
ProgramFiles=C:\Program Files
ProgramFiles(x86)=C:\Program Files (x86)
ProgramW6432=C:\Program Files
PROMPT=$P$G
PSModulePath=C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules
PUBLIC=C:\Users\Public
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:\Windows
TEMP=C:\Users\PC-02\AppData\Local\Temp
TMP=C:\Users\PC-02\AppData\Local\Temp
USERDOMAIN=DESKTOP-67906HQ
USERDOMAIN_ROAMINGPROFILE=DESKTOP-67906HQ
USERNAME=PC-02
USERPROFILE=C:\Users\PC-02
windir=C:\Windows

<!-- 클래스 패스 이후의 경로(qualified name)쓴 후 클래스 실행-->
D:\>java kr.or.ddit.HelloJava
Hello Java
D:\>java kr/or/ddit/HelloJava
Hello Java
D:\>java kr/or/ddit/HelloJava
Hello Java
<!-- -encoding: 인코딩 설정/ -d: 컴파일 후 저장 경로 -->
D:\>javac d:\standalone\HelloJava.java -encoding UTF-8 -d D:\standalone

<!-- 인코딩 설정 마쳐서 잘됨 -->
D:\>java kr.or.ddit.HelloJava
안녕 자바
D:\>javac d:\standalone\HelloJava.java -encoding UTF-8 -d D:\standalone

<!-- println(args[0]) 으로 코드 수정 -->
<!-- 매개변수 없어서 예외발생 -->
D:\>java kr/or/ddit/HelloJava
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at kr.or.ddit.HelloJava.main(HelloJava.java:9)
<!-- 띄어쓰기 기준으로 매개변수 갯수 측정 -->
D:\>java kr/or/ddit/HelloJava 안녕 자바
안녕
<!-- ""으로 문자열 묶어줌 -->
D:\>java kr/or/ddit/HelloJava "안녕 자바"
안녕 자바

HelloServlet

  • -d: 컴파일 후 저장될 곳
    • classes 폴더
  • 그동안 main도 없었는데 서블릿은 누구에 의해 운영이 됐을까: 톰캣이 돌리고 있었다

cmd

<!-- %catalina_home% == 톰캣 경로 -->
D:\>cd %catalina_home%

<!-- 우리가 만든 서블렛의 소스 폴더 -->
D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37>cd webapps\firstApp\WEB-INF\src

<!-- servlet-api.jar파일이 적용되지 않아 예외 발생 -->
D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\webapps\firstApp\WEB-INF\src>javac HelloServlet.java -d ..\classes
HelloServlet.java:3: error: package javax.servlet.http does not exist
import javax.servlet.http.*;
^
HelloServlet.java:4: error: package javax.servlet does not exist
import javax.servlet.*;
^
HelloServlet.java:7: error: cannot find symbol
public class HelloServlet extends HttpServlet {
                                  ^
  symbol: class HttpServlet
HelloServlet.java:9: error: cannot find symbol
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                          ^
  symbol:   class HttpServletRequest
  location: class HelloServlet
HelloServlet.java:9: error: cannot find symbol
        public void doGet(HttpServletRequest req, HttpServletResponse resp)
                                                  ^
  symbol:   class HttpServletResponse
  location: class HelloServlet
HelloServlet.java:10: error: cannot find symbol
        throws IOException, ServletException {
                            ^
  symbol:   class ServletException
  location: class HelloServlet
6 errors

D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\webapps\firstApp\WEB-INF\src>

D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\webapps\firstApp\WEB-INF\src>javac HelloServlet.java -d ..\classes -classpath ..\..\..\..\lib\servlet-api.jar

D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\webapps\firstApp\WEB-INF\src>javac HelloServlet.java -d ..\classes -classpath ..\..\..\..\lib\servlet-api.jar

서블렛 cmd로 실행하기

C:\Users\PC-02>d:

D:\>cd %catalina_home%

D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37>cd bin

D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\bin>startup.bat
Using CATALINA_BASE:   "D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37"
Using CATALINA_HOME:   "D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37"
Using CATALINA_TMPDIR: "D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\temp"
Using JRE_HOME:        "D:\B_Util\2.Java\JDK1.8"
Using CLASSPATH:       "D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\bin\bootstrap.jar;D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\bin\tomcat-juli.jar"
D:\B_Util\5.ApacheTomcat\apache-tomcat-8.5.37\bin>

서블릿 vs. JSP

  • 학습목표!!!
    • JSP는 곧 서블릿이지만, (=같은 스펙이지만) JSP와 서블렛을 운영할때 톰캣이 이런이런 역할을하며 차이점이있어요 -> 내 문장으로 설명할 수 있어야함
  • 톰캣의 역할
    • JSP 운영시 -> JSP컨테이너, 서블렛 운영 시 -> 서블렛컨테이너

컨테이너란?

  • 톰캣이 서블릿컨테이너로 동작할때 서블릿의 객체를 생성해주는 역할을 함
  • 이게 싱글톤 객체를 생성할지 말지 결정도 톰캣이함,..
  • 한번 컨테이너로 들어간 짐은 컨테이너들이 관리함
  • 컨테이너는 관리하는 컴포넌트를 태어나게하고 죽게도할수있고 태어나고 죽기전까지 컴포넌트의 라이프사이클을 관리한다.

서블릿의 life cycle vs. JSP의 life cycle

서블릿JSP
만들고 web.xml에 등록 후 부터 톰캣이 관리우리가 등록도 안했는데 어떻게 등록되어있고, url매핑은 언제했지?
톰캣이 다해놨지 짜샤 그니까 톰캣이 할일이 많아짐
개발자: 넘나 편하군
톰캣: 죽여줘
개발자: 죽여줘
톰캣: 넘나 편하군

서블릿의 단점

  • 코드가 섞여있다. (자바 코드 내에 html)
    • 협업이 어렵다.
  • 코드 변경시 서버를 재구동 해야한다
    • 싱글톤 객체가 이미 생성되어있어서 그 클래스의 객체가 생성되어있으면 다시 안만듬
  • web.xml에 등록 후 url 매핑도 해야한다
  • 컴파일도 다시 해야한다

JSP 사용시 기억할 점

  • 우리가 쓰는 코드는 가짜다..!

오늘복습

  • 클래스패스
  • 서블릿이라는 스펙에 따라서 어떻게 개발이 진행되는지
    • 그 과정에서 서블릿컨테이너가 어떻게 동작되는지
    • 컨테이너가 뭔지?
  • 서블릿의 단점
    • 단점을 해결할수있는 jsp스펙의 특징
    • jsp 작동시 컨테이너가 어떻게 작동하는지

내일수업

	<servlet>
		<servlet-name>HelloServlet</servlet-name>
		<servlet-class>kr.or.ddit.HelloServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>HelloServlet</servlet-name>
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>
  • 왜 url패턴을 hello라고만 써주면 서버키자마자 터질까?
profile
갈 길이 멀다

0개의 댓글