본문 바로가기

카테고리 없음

[ Servlet & JSP ] 톰캣 설치, JSP 프로그램 작성 (수동)

자바 언어로 웹 프로그램을 개발하려면 서블릿(Servlet) api가 필요하다.

자바 프로그램에 서블릿 api를 추가하면 자바언어로 웹 프로그램을 개발할 수 있다.

문서를 출력하는 부분에 있어서 서블릿은 비효율적이기에 문서의 출력을 간결하게 입력할 수 있게 해주는 JSP라는 도구를 이용하게 된다.  JSP라는 도구를 이용했을 때 스파게티처럼 코드가 꼬이는? 문제가 발생하게 되는데 또 이런 점을 보완하기 위해 코드를 정리하는 구조?인 JSP MVC 방식으로 웹 프로그램을 개발하는 단계로 발전하게 되었다고 한다.

 

정리:

자바 언어 + Servlet api → 웹 프로그램 개발

Servlet으로 HTML 문서를 출력하는 코드를 작성하기에 비효율적인 부분이 있어 ( Servlet으로 HTML 문서를 작성하기 어려움 )

JSP라는 도구가 나왔고, JSP로 HTML 문서를 작성하기 간결해졌으나 스파게티처럼 코드가 복잡해지는 문제가 발생하게 됨.

그래서 유지보수하기 용이하고, 가독성이 높게, 코드를 잘 정리할 수 있는 방식인 JSP MVC 방식으로 발전하게 되었다.

 

--------------------------------

 

웹은 데이터를 요청할 수 있는 브라우저 환경과

요청받은 데이터를 응답하는 웹 서버와 연결이 가능한 환경을 HTTP(웹)이 갖추고 있다.

웹은 페이지를 요청 받고, 요청받은 페이지를 제공한다.

시간과 요청에 따라 서버에서는 DB와 연동하여 응답하는 페이지를 생성하는데

조건에 따라 동적으로 페이지를 생성하는 환경을 웹 서버에 추가하게 된다(웹 서버는 정적인 문서들을 다룬다)

웹 서버 프로그램은 사용자의 요청에 따라 동적으로 생성된 문서를(페이지) 전달,

자바스크립트는 실시간으로 데이터를 요청할 수 있어 오늘날에는

자바스크립트로 웹 기반으로 클라이언트 프로그램을 만들 수 있게 되었다.


--------------------------------

 

웹 서버 프로그램과 Servlet의 관계

 

사용자가 요청하는 데이터에 따라 웹 서버는 해당 요청에 응답할 문서가 홈 디렉토리에 있는지를 찾아보고,

없다면(응답할 페이지가 정적 문서가 아니라면) 웹 서버는 사용자의 데이터 요청에 응답할 수 있는,

요청 데이터를 기반으로 응답할 페이지를 생성할 수 있는 코드가 작성된 페이지를 찾는다.

클라이언트로부터 요청받은 데이터를 기반으로 응답할 페이지를 생성할 수 있는 코드를 실행하고

(이 과정에서 DB와의 연동으로 DB에 필요한 데이터를 요청하고, 해당 데이터를 응답받는다.

그리고 그 DB로부터 응답받은 데이터를 사용해 클라이언트에게 응답할 페이지 생성한다)

클라이언트에게 응답할 페이지를 생성한다 → 이렇게 사용자가 동적인 문서를 요청할 경우,

동적인 문서를 만들 수 있는 환경을 웹 서버에 더해야 하는데 그 환경을 WAS라고 한다.

사용자의 요청에 응답해야할 문서가 이미 만들어져 있는 문서(정적인 문서)가 아니라

동적으로 생성해야할 문서라면 WAS(Web Application Server, 웹 어플리케이션 서버)가 필요하다.

 

동적으로 문서를 만드는 코드를 Server App(서버 어플리케이션)이라 하고,

이 서버 어플리케이션을 실행할 수 있게 해주는 환경 두 가지가 필요하다.

하나는 웹 서버고, 하나는 서버 어플리케이션을 찾아서 실행할 수 있는 환경이다.

서버 어플리케이션을 실행할 수 있는 환경: Web Server + WAS(Web Application Server)

 

서블릿(Servlet, Server Application Let )은 서버 어플리케이션을 구성하는 단위다. 서버 어플리케이션은 여러 개의 서블릿으로 이루어져 있다. servlet은 an applet that runs on a server, typically within Java → 서블릿은 서버에서 실행되는 애플릿으로,

보편적으로 자바로 작성된다. 애플릿은 매우 작은 어플리케이션(프로그램)으로 하나 또는 매우 적은 기능을 수행하는 유틸리티 프로그램을 의미한다.

 

--------------------------------

 

동적 문서(페이지)를 실행할 수 있는 환경 세팅하기: Web Server + WAS

 

1. 톰캣 다운로드

 

- 브라우저 검색창에 tomcat.apache.org 입력 후 엔터

 

 

- 좌측 목록에서 Download 구간에 작성된 설치하고자 하는 톰캣 버전 클릭 (저는 Tomcat 11 선택)

 

*** 톰캣 버전을 아무거나 설치하면 안되고, 현재 사용하고 있는 JDK 버전을 확인할 것. 확인하는 방법은 Download 구간에 맨 첫번째 리스트인 'Which version?' 클릭 후 Currently Supported Versions 표 확인하기

저는 JDK 17이 기때문에 톰캣 버전 11.0.0(11버전)을 사용할 수 있지만

JDK 17미만, 11이상이라면 톰캣 버전 10.1.X 버전을, 11미만 8이상이라면 9.0.X 버전을 다운받길 바랍니다.

 

- Core 에서 Windows.zip 파일을 받고 압축풀기('여기에 풀기'로 진행)

 

*** 압축 그냥 풀면 tomcat 폴더 안에 또 tomcat 폴더 그리고 그 안에 bin, conf, lib 폴더가 존재하는 구조이기 때문에 '여기에 풀기'로 압축을 풀어야 합니다. 여기에 풀기로 압축 풀기 진행시 tomcat 폴더 클릭하면 바로 bin, cof, lib 폴더가 존재하는 구조가 됩니다.

 

그리고 tomcat > bin > startup.bat클릭하면 실행됩니다.

***만약 시커먼 창이 꺼져버린다면(계속 켜져 있어야 실행되는 것임) JDK가 환경변수에 설정되지 않아서 그런 것임.

톰캣은 자바라고 하는 JDK를 필요로 하는 어플리케이션인데 JDK가 어느 디렉토리에 설치되어 있는지를 알아야 하는데

알수있는 방법이 JAVA_HOME이라고 하는 환경 변수를 찾아서 그 JAVA_HOME에 등록되어 있는 값을 찾는데,

이 JAVA_HOME이 환경변수에 등록되어 있지 않다면 JDK를 찾을 수 없게 되고, JDK를 확인할 수 없기 때문에

JDK를 사용해야 하는데 톰캣이 실행이 되지 않게 되는 것이다.

***또는 다른 프로그램이 톰캣을 사용하고 있다면 포트(프로그램을 식별할 수 있는) 번호 충돌로 실행이 되지 않을 수 있다.

 

- 아래와 같이 start? 라는 문구가 입력되면 톰캣이 실행되고 있다는 것이고,

 

- 브라우저에 localhost:8080 을 입력하면 아래와 같은 페이지가 뜨면 톰캣 실행에 성공한 것이다.

 

--------------------------------

 

톰캣의 역할

톰캣의 역할은 1. 웹 클라이언트로부터 요청받은 데이터를 기반으로 동적으로 문서를 생성할 수 있는 환경을 제공하고,

2. WAS에 자바 어플리케이션을 개발할 때 사용되는 웹 서비스의 기능이 포함되어 있다. 그래서 웹 서버라고 볼 수 있고,

웹 서버는 웹 문서를 제공하는 기능이 있어 결국 톰캣은 웹 서버로써 웹 문서를 제공하는 역할도 한다.

 

톰캣이 갖는 홈 디렉토리(폴더)

톰캣이 갖고 있는 디렉토리중 문서를 보관하고 있는 디렉토리가 있다.

문서를 보관하고 있는 홈, 그래서 홈 디렉토리라고 한다.

톰캣이 갖고 있는, 문서를 보관하고 있는 홈 디렉토리 경로: apache-tomcat-11.0.0\webapps\ROOT

웹 서버는(ex. 톰캣은 웹 서버의 기능도 있다) 예약되어 있는(이미 약속되어 있는) 특정 폴더가 있고,

특정 폴더에 문서를 저장하고, 다른 원격에 있는 컴퓨터의 브라우저를 통해

서버의 주소와 함께 리소스의 이름을 작성하면 해당 리소스의 내용을 보여준다.  

 

톰캣 폴더 구조(일부만 작성)

 

tomcat

    └bin ----------------  tomcat 실행에 필요한 실행파일 폴더(바이너리), 윈도우의 경우 .bat확장자를 가진 실행파일을 실행할 것

    └conf --------------- 설정파일 폴더이며 여기서 가장 중요한 설정파일이 server.xml

                                          *** server.xml은 전체 컨테이너를 위한 주요 설정 파일이다. 이곳에서 포트번호와 Context path 설정 가능

    └ webapps --------- 웹 어플리케이션 홈 디렉토리가 존재하는 곳

               └ ROOT------- 웹 어플리케이션 홈 디렉토리

                        └ WEB-INF

                        └ index.jsp

      .

      .

      .

--------------------------------

 

Servlet 프로그램 만들기

Servlet 프로그램을 만든다는 것은 서버 어플리케이션을 만든다는 것

서버 어플리케이션은 기능별로 코드가 나누어져 있고, 필요에 따라 기능별로 선택에 따라 만들어진다.

 

WAS는 서블릿을 인식할 수 있고, 자바 언어로 서블릿을 작성하려면 WAS가 인식할 수 있는 HttpServlet 추상클래스를 상속해야 한다.

예를 들어 아래와 같이 작성할 수 있고, 그리고 이 서블릿을 실행시키기 위해 cmd에서 컴파일 작업을 하게 되면 → javac Nana.java

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

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

// HttpServlet 추상클래스를 상속하면 이 클래스는 서블릿이 된다.
public class Nana extends HttpServlet { 

	// 그리고 HttpServlet 추상클래스가 제공하는 service() 라는 메서드를 구현해야 한다.
	public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
		System.out.println("Hello Servlet");
	}
}

 

컴파일 하기위해 cmd에 javac Nana.java 라고 명령을 하면

 

cannot find Symbol 에러가 발생하는데, 이 에러는 import한 서블릿 라이브러리는 JDK에 포함되어 있지 않기에 JDK에서 HttpServlet 추상클래스를 인식하지 못하면서 발생하는 에러다. 그래서 cmd에서 Nana클래스를 컴파일 할 때

import해야할 javax.servlet.* 과 javax.servlet.http.* 그리고 java.io.* 라이브러리가 존재하는 경로를 함께 작성하여 명령한다.

톰캣 폴더 내 lib폴더 안에 존재하는 servlet-api.jar 를 이용해서 HttpServlet을 상속한 Nana클래스를 컴파일 해보겠다.

 

cmd에 이렇게 명령어를 작성한다.

javac 자바 컴파일러에게 사용할 라이브러리가 있는 경로를 알려주고 컴파일할 .java 파일을 작성한다.

javac -cp C:\Tool\apache-tomcat-9.0.73\lib\servlet-api.jar Nana.java

 

그리고 오류 없이 잘 실행이 됐다면 dir 명령어를 작성하여 Nana.java 파일이 컴파일 되었는지 확인한다.

만약 Nana.class 파일이 존재한다면 컴파일이 잘 된 것이다.

 

- 컴파일한 Nana.class 를 실행하기

톰캣이 운영하는 홈 디렉토리에서 WEB-INF 라는 폴더는 사용자가 요청했다고 해서 접근할 수 있는 폴더가 아니다.

WEB-INF 폴더 안에 있는 자원들을 서버만이 접근할 수 있다. 절대로 클라이언트쪽에서 WEB-INF 내부의 자원들에 접근할 수 없다.

WEB-INF 안에 classes 폴더 안에 서버만이 접근할 수 있는 클래스 파일을 둔다. 예를 들면 Nana.class 파일 같은 것들이 존재할 수 있다. 서블릿 클래스를 컴파일 했을 때 컴파일된 클래스 파일들이 WEB-INF 내부의 classes 폴더 내부에 위치하게 된다.

 

클라이언트 요청한 url과 서블릿 코드를 매핑하는 설정을 web.xml에 작성하면

WAS가 설정 파일을 보고 어떤 url로 들어왔을 때 어떤 클래스를 실행해야 하는지

WEB-INF폴더 내부의 classes폴더 내부의 클래스 파일을 찾아 응답한다.

 

WEB-INF폴더 내부의 web.xml파일 작성하기

<servlet>
	<servlet-name>na</servlet-name>
	<servlet-class>Nana</servlet-class>
</servlet>

<!--
    클라이언트가 요청한 url패턴이 /hello일 경우 servlet-name이 na인 것을 찾고
    servlet-name이 na인 것과 매핑된 서블릿 클래스를 찾아 클라이언트에게 전달한다.
    class를 찾는 곳은 WEB-INF내부의 classes폴더 내부에서
    WEB-INF 내부는 서버만이 접근할 수 있는 곳, 클라이언트는 접근할 수 없다.
-->
<servlet-mapping>
	<servlet-name>na</servlet-name>
    
    <url-pattern>/hello</url-pattern>
    
    <!--servlet-pattern 으로 작성하니 /이 경로와 /hello 경로 모두 404 에러가 떴다.
    servlet-pattern을 url-pattern으로 변경하니 잘 작동됨
	<servlet-pattern>/hello</servlet-pattern>
    -->
</servlet-mapping>

 

클라이언트로부터 요청받은 url을 WAS는 web.xml 파일을 보고

해당 url과 매핑된 클래스를 WEB-INF 폴더 내부의 classes 폴더 안에서 찾아

해당 파일의 내용이 서버의 콘솔에 출력된다.

 

Servlet 문자열 출력

- 서버의 콘솔에 출력하는 게 아니라 클라이언트의 화면에 출력하게 하기

HttpServlet 추상클래스를 구현한 클래스는 service()라는 메서드를 구현하는데,

service() 메서드는 2개의 인자를 전해준다 → HttpRequest request와 HttpResponse response

서블릿을 만들기 위한 두 개의 객체: request 객체는 요청 도구로써, response 객체는 응답 도구로써 사용된다. 

HttpResponse response 객체는 클라이언트에게 출력할 내용을 작성할 수 있다 → HttpResponse response 객체는 웹 출력 API다. 파일이나 문자열 입/출력을 수행할 때 사용하는 스트림 객체를 얻어서 클라이언트에게 출력해 보겠다.

 

public class Nana 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!");
    }
}

public class Nana extends HttpServlet {

    public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
    {
    
        /*1번째 방법
        
        클라이언트의 요청에 응답할 데이터를 클라이언트의 브라우저에 출력하기 위해
        /응답 객체로부터 출력할 객체를 얻는다(스트림)
        OutputStream os = response.getOutputStream();
        
		PrintStream out = new PrintStream(os, true);
        */
        
        // 1번 방법보다 PrintWriter를 직접 얻어서 출력할 내용을 적는 것이 더 많이 쓰임
        // 문자를 쓰는데, 다국어면 PrintWriter를 쓰는 것이 보편적
        PrintWriter out = new response.getWriter();

		out.println("Hello Servlet!");
    }
}

 

지금까지 서블릿 코드를 IDE(ex. 이클립스, 인텔리제이 등)가 아닌 직접 수동으로

 

1. 메모장에 코드를 작성[코드 수정]하고,  2. cmd를 통해 컴파일하고,

3. java파일을 컴파일한 class파일을 배포하고 (class 파일을 톰캣 폴더의 webapps폴더의 ROOT(홈 디렉토리) 폴더의

WEB-INF폴더의 classes폴더 안에 옮긴다) 4. 톰캣 서버를 재실행하고(톰캣 폴더의 bin폴더의 startup.bat실행) 5. 브라우저로 해당 url요청

 

하는 번거로운 과정을 거쳐 브라우저에 Hello Servlet이 출력되었다. IDE를 사용한다면 실행하는(run) 버튼 클릭 한 번만으로

이러한 복잡한 과정을 IDE가 직접해주기 때문에 편리하다. 다음에는 IDE를 사용한 JSP 개발을 실행해보겠다.