서블릿(Servlet)
뉴렉처 - 서블릿/JSP 강의
서블릿은 HTTP 기반 통신에서 사용되는 서버 측의 응용 프로그램이다. 브라우저에서 요청을 보내면 웹 서버에서는 요청의 성격을 판단하여 정적으로 처리할 수 있는 경우에는 웹 서버에 저장되어 있는 정적 리소스를 즉시 브라우저로 응답하게 된다. 하지만 HTML,CSS와 같은 정적 리소스에 대한 요청이 아니라 별도의 로직 수행을 통한 결과를 얻고 싶은 경우에는 동적으로 이 작업을 처리해줄 웹 어플리케이션 서버로 요청을 전달하게 된다.
웹 어플리케이션 서버에서는 웹 서버로부터 전달 받은 내용을 토대로 작업을 처리하게 되는데, 이때 실행되는 어플리케이션을 서블릿이라 부른다.
톰캣 설치
톰캣은 자바로 작성된 어플리케이션을 실행할 수 있는 웹 어플리케이션 서버다. 톰캣의 홈페이지에서 tar 파일을 받고 압출을 해제해 주면 된다.
tar zxvf [ tomcat tar 경로] -C [ 압축 해제 경로]
# 심볼릭 링크 걸기 - 톰캣 버전 여러개 사용할 경우
ln -s [ tomcat 설치 경로 ] [ 심볼릭 링크 이름 ]
ln -s apache-tomcat-9.0.50 tomcat9
톰캣이 설치된 경로로 들어가면 /bin
디렉토리에 여러 스크립트 파일이 있는데, startup.sh
을 실행하면 톰캣을 실행할 수 있다. 정상적으로 실행됐다면 다음과 같은 출력이 나올 것이다. 그리고 브라우저에서 localhost:8080
으로 요청을 보내 톰캣이 나타나면 정상적으로 실행되고 있는 것이다.
Using CATALINA_BASE: []
Using CATALINA_HOME: []
Using CATALINA_TMPDIR: []
Using JRE_HOME: []
Using CLASSPATH: []
Using CATALINA_OPTS:
Tomcat started.
종료 역시 스크립트 shutdown.sh
로 진행한다. 정상적으로 종료가 되었다면 localhost:8080
으로 요청을 보내면 정상적인 응답이 오지 않게 된다.
톰캣에 웹 페이지 추가
톰캣은 웹 어플리케이션 서버이면서 동시에 웹 서버의 역할을 할 수 있다. 톰캣을 설치하면 다음과 같은 디렉토리를 가지고 있는데, 각각의 역할은 다음과 같다.
bin : 톰캣의 바이너리 파일 + 스크립트
conf : 톰캣의 설정파일
logs : 로그 정보
temp : 임시 저장용
work : JSP 실행시 중간 파일 저장
wepapps : 웹 어플리케이션이 있는 곳
- JSP는 HTML 내부에서 자바 코드를 사용할 수 있도록 만든 확장자이다.
웹 페이지를 추가할 디렉토리는 webapps
이다. 톰캣을 실행하고 localhost:8080
으로 요청을 보내면 webapps/ROOT
로 요청이 들어간다. 그리고 index.jsp
가 홈 디렉토리에 대한 요청의 응답으로 리턴되어 톰캣 화면을 볼 수 있게 된다.
webapps
에 간단한 텍스트 파일을 만들고 이것을 톰캣으로 응답받아 웹 서버로 톰캣을 사용해보자.
# 톰캣 설치 경로/webapps/ROOT
echo "Hello World" >> hello.txt
# bin에서 statup.sh로 톰캣 실행 후 locatlhost:8080/hello.txt 요청보내기
톰캣 컨텍스트 추가
webapps/ROOT
경로에 새로운 파일이나 디렉토리를 추가하면 브라우저에서 접근이 가능한 것을 확인했다. 그런데 하나의 ROOT
디렉토리 하위에 여러 디렉토리가 존재한다면 점점 관리가 힘들어질 것이다. 그래서 톰캣에서는 컨텍스트라는 기능을 제공한다. 가상 경로라고 부르기도 하는데, 개념은 다음과 같다.
localhost:8080/sub1
localhost:8080/sub2
localhost:8080/sub3
ROOT
하위에 sub1
, sub2
, sub3
라는 경로가 존재하는데, 각각의 하위 디렉토리의 사이즈가 증가하여 ROOT
하위에 담기 힘들어진 상황이라면 컨텍스트를 만들어 별도의 톰캣으로 관리가 가능해진다는 것이다. 그래서 sub1
은 다른 톰캣의 ROOT
에서 작성하고 컨텍스트를 이어서 기존에 사용하던 localhost:8080
에서 접근이 가능해지는 것이다.
컨텍스트 설정은 conf
디렉토리의 server.xml
에서 진행하면 된다.
webapps/academy/academy.txt
라는 새로운 경로를 생성한다. 텍스트 파일의 내용은 아무거나 입력해도 된다.conf/server.xml
에서Host
부분 아래에Context
태그를 추가해준다..... <Host name="localhost" appBase="webapps" unpackWARs="true" autoDeploy="true"> ... <Context path="academy" docBase="{톰캣설치경로/webapps/academy}" privileged="true"/> ... </Host>
톰캣을 실행하고
localhost:8080/academy/academy.txt
경로로 브라우저를 통해 요청을 보낸다.
서블릿 프로그램 만들기
서블릿은 WAS에서 로드되어 실행된다. WAS에서 실행될 수 있는 어플리케이션의 종류는 매우 다양하기 때문에 이를 추상화한 계층을 만들어 WAS에서 이를 인식하게 만들었다. 이것이 바로 HttpServlet
추상 클래스이다.
HttpServlet
에는 service
라는 추상 메서드가 존재하는데, 이 메서드가 바로 WAS에서 호출될 때 실행되는 서블릿 어플리케이션의 로직이 된다. 따라서 가장 기본적인 서블릿 프로그램의 포맷은 다음과 같다.
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
public class MyClass extends HttpServlet {
public void service(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
// application run
System.out.println("Hello Servlet");
}
}
이렇게 파일을 만들고 WAS에서 실행을 하도록 만들기 위해 자바 컴파일러로 바이트코드를 만들어야 한다. 이렇게 작성하고 바로 javac MyClass.java
로 컴파일을 하면 다음과 같은 에러가 발생한다.
MyClass.java:7: error: cannot find symbol
public void service(HttpServletRequest request,
이는 HttpServlet
이라는 클래스가 JDK에서 제공되는 라이브러리가 아니기 때문에 발생하는 에러이다. 따라서 컴파일을 할 때 외부 라이브러리를 함께 컴파일 할 수 있는 옵션인 -cp <PATH>
를 함께 사용해야 한다.
WAS로 사용하는 톰캣에서는 바로 여기에 컴파일에 사용할 클래스들을 제공해주고 있다. 톰캣 설치 경로의 lib
로 들어가면 다양한 jar
파일들이 있는데, 그 중에서 servlet-api.jar
를 사용해주면 된다.
javac -cp {톰캣설치경로}/lib/servlet.api.jar MyClass.java
이렇게 컴파일을 하게 되면 MyClass.class
파일이 나오게 된다. 이제 이것을 톰캣에서 실행하면 된다.
클래스 파일의 위치와 서블릿 실행
톰캣의 webapps/ROOT
경로를 보면 WEB-INF
라는 경로가 있다. 클래스 파일은 여기에 classes
라는 디렉토리를 만들고 이동시켜주면 된다.(없으면 만듬)
cp {서블릿경로}/Myclass.class {톰캣설치경로}/webapps/ROOT/WEB-INF/classes/MyClass.class
이렇게 클래스 파일을 복사하고 나서 톰캣에서 실행하는 방법을 알아야 한다. WAS에서 실행되는 서블릿은 정적 리소스와는 다른 방식으로 접근해야 한다. 정적 리소스는 localhost:8080/hello.txt
와 같은 방식으로 직접적으로 필요한 파일의 경로를 지정하고, 서버에서 이를 응답해주었는데, 서블릿의 경우 이렇게 직접적으로 클래스 파일을 리턴해줄 수 없다.
WEB-INF
경로는 외부에서 직접 요청할 수 있는 경로가 아니기 때문에 정적 리소스 파일을 여기에 만들어도 요청할 수 없다.
서블릿의 경우 사용자마다 다른 결과값을 리턴해주는 동적 리소스이기 때문에 프로그램이 실행되고 나서 요청한 값에 대한 결과가 리턴되기 때문에 별도로 매핑과정을 거치게 된다. WEB-INF
경로에는 web.xml
이라는 파일이 있는데, 이 파일에 서블릿을 매핑시켜 주는 코드를 작성해준다.
<servlet>
<servlet-name>myClass</servlet-name>
<servlet-class>MyClass</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>myClass</servlet-name>
<url-pattern>/my-class</url-pattern>
</servlet-mapping>
<servlet>
태그를 사용해서 우리가 만든 MyClass
라는 클래스 파일을 myClass
라는 이름의 서블릿으로 톰캣에 등록해주고, <servlet-mapping>
태그를 사용해서 /my-class
경로로 요청이 들어오면 myClass
를 실행할 수 있도록 매핑을 해준다.
이렇게 web.xml
을 작성하고 톰캣을 재시작한 뒤, .localhost:8080/my-class
로 요청을 해보자. 위의 코드에서 사용자에게 반환하는 값을 주지 않았기 때문에 아무것도 없는 흰 페이지가 나타나면 정상적으로 작동하는 것이다.
표준 출력으로 작성한 Hello Servlet
이라는 문자열은 logs/catalina.out
에서 확인할 수 있다. 하지만 우리가 원하는 것은 톰캣의 로그에 문자열을 출력하는 것이 아니라 브라우저의 화면에 Hello Servlet
을 출력하는 것이다. System.out.println
은 콘솔에다 출력을 하는 것이고, 브라우저로 출력을 하기 위해선 HttpServletResponse
클래스를 사용해주어야 한다.
HttpServletResponse, HttpServletRequest
서블릿 실행에 필요한 데이터를 WAS에 전달하거나, WAS에서 서블릿을 실행시켜 얻게 된 결과를 사용자에게 돌려주기 위해 사용할 수 있는 클래스가 바로 HttpServletRequest
, HttpServletResponse
클래스이다.
public class MyClass extends HttpServlet {
public void service(HttpServletRequest request,
HttpServletResponse response) throws IOException, ServletException {
OutputStream os = response.getOutputStream();
PrintStream out = new PrintStream(os, true);
out.println("Hello Servlet");
}
}
이 코드에서 response
를 사용하면 사용자에게 전달하고 싶은 내용을 작성할 수 있다. HTTP를 통한 데이터는 스트림 방식으로 처리하는데, response
객체에는 getOutputStream
이라는 메서드가 존재한다. 아웃풋스트림은 서버에서 클라이언트로 전달할 데이터를 쓰기 위한 용도라고 생각하면 된다.
여기에 PrintStream
객체를 만들어서 아웃풋스트림을 보다 편리하게 출력하도록 하였다. 프린트스트림 생성자의 두 번째 매개변수는 아웃풋스트림에 작성되는 내용을 버퍼에 담아 두었다가 전송하는데, 이를 버퍼가 가득 찰 때까지 기다리지 않고 바로 전송하도록 만드는 옵션이다.
그 다음 println
메서드에 출력하고 싶은 문자열을 입력해주면 된다. 이렇게 하면 콘솔이 아닌 브라우저에 Hello Servlet
이 나타나게 될 것이다.
코드를 수정하고, 컴파일을 하고, webapps/ROOT/WEB-INF/classes
로 클래스 파일을 이동하고 톰캣을 실행해서 확인해보자.
'프로그래밍 언어 > Java' 카테고리의 다른 글
자바 8 람다식 해설서 - 2장 스트림과 함수형 인터페이스 (0) | 2022.12.21 |
---|---|
자바 8 람다식 해설서 - 1장 람다식 (0) | 2022.12.21 |
서블릿 필터 (0) | 2022.07.12 |
람다식 (0) | 2022.06.14 |