웹 프로그래밍의 시작(1) - Tomcat & Servlet & JSP

웹 프로젝트의 기본 구조

브라우저 혹은 클라이언트 프로그램
- 서버에서 전송할 결과를 화면에 보여주고 (렌더링(rendering)) 사용자의 화면 조작을 이용해서 서버에 원하는 데이터를 보내고 (요청 - request) 받는 (응답 - response) 프로그램

웹 서버 (Web Server) 혹은 WAS (Web Application Server)
- (웹 서버)이미지와 같은 정적인 데이터를 제공 하거나  동적으로 매번 새로운 데이터를 만들어 낼 수 있는 WAS (실제 운영 환경에서는 보통 웹 서버와 WAS를 분리해서 운영하지만, 대부분 WAS는 웹 서버 기능도 겸하고 있으므로 실습 시에는 WAS만으로 구성 가능하다)
- 관련 기술: 서블릿/JSP, 각종 플레임워크와 언어들

데이터베이스
- 영구적으로 데이터를 보관하고 운영하기 위한 프로그램으로 기본적으로 관계형 패러다임을 이용한 관계형 데이터베이스를 사용한다.
- 관련 기술: SQL, 데이터베이스 설계/구현


war는 무엇인가?
- 톰캣을 프로젝트에 적용하고 난 후,
인텔리제이에서 [Edit Configuration]를 선택하고 [Deployment]를 선택하면 ‘...war'라는 이름으로 서버에서 실행되도록 지정된 것을 확인할 수 있다.(exploaded로 되어있다면 그대로 사용)
- ’war'는 Web Application Archive'의 약자로 현재 프로젝트를 압축파일로 만들어서 톰캣에서 실행하는 방식이다.

변경된 코드의 반영
- 일반 자바 프로그램과 달리 톰캣을 적용한 서버 프로젝트는 gradle을 이용해서 컴파일 등의 작업이 처리되고 프로젝트의 build/libs 폴더 안에 내용이 톰캣을 통해서 실행된다. 그렇기 때문에 코드를 변경한 후에는 다시 톰캣을 재시작해야한다.


서블릿 코드 작성해보기
- 톰캣에서 작성한 자바 코드는 HttpServlet이라는 클래스를 상속해서 작성하는데 이를 흔히 서블릿(Servlet) 클래스를 생성한다고 표현한다.
- 예시) userServlet은 HttpServlet이라는 클래스를 상속하고 @WebServlet이라는 어노테이션을 이용해서 해당 서블릿의 경로(urlPatterns)를 지정한다.
- 코드 예시)

@WebServlet(name="userServlet", urlPatterns="/user")
public class userServlet extends HttpServlet { ....}

- @WebServlet은 브라우저의 경로와 해당 서블릿을 연결하는 설정을 위해서 사용된다.


어노테이션(Annotation): “주석이나 해석” , 주로 코드상에 추가적인 정보를 남겨두기 위해서 사용한다.
연극 대본의 지문처럼 특정한 코드에 대해 추가적인 처리나 설정을 위해서 사용한다.



JSP 코드 작성해보기
프로젝트 생성 시에 존재하는 webapp 폴더에 ~~.jsp 파일을 생성하고 브라우저를 통해 호출하면(localhost/~~.jsp) 결과가 출력된다.
jsp파일은 Servlet 클래스 파일보다 HTML에 더 유사하다.


웹 기본 동작 방식

Request(요청)/Response(응답)
브라우저는 일반적으로 정보 전달하기 위해서 두 가지 방식을 이용한다.
GET 방식: 주소창에 직접 원하는 데이터를 적거나 링크를 클릭해서 호출
- 원하는 웹의 주소를 호출할 때 필요한 데이터를 ‘?’와 ‘&=‘를 이용해서 같이 전송하는 방식
- 주소와 필요한 데이터를 한번에 같이 보내기 때문에 단순 링크로 처리되므로 다른 사람들에게 메신저나 SNS 등을 통해서 쉽게 공유가 가능하다.
- 특정한 정보를 조회하는 용도로 사용한다.

POST방식: 입력 화면에서 필요한 내용을 작성한 후에 ’전송‘과 같은 버튼 등을 클릭해서 호출
- 주소와 데이터를 따로 보내는 방식
- 보통 회원가입이나 로그인 등의 처리가 이에 해당
- 웹 화면을 통해서 실제 처리가 필요한 작업을 하기 위해서 사용

브라우저에서는 이러한 방식들로 데이터를 요구하는 것을 ’요청‘이라 하고
서버는 이에 대한 ’응답’데이터를 만들어서 브라우저로 보내는데, 정적인 데이터와 동적인 데이터를 다르게 처리한다.
정적(static) 데이터
- 항상 동일하게 고정된 데이터를 전송하는 방식으로 주로 파일로 고정된 HTML, CSS, 이미지 파일 등의 데이터
- 항상 정적 데이터를 보내는 역할만 수행하는 서버를 ’웹 서버‘라고 부른다.

동적(dynamic) 데이터
- 매번 필요할 때마다 다른 데이터를 동적으로 구성해서 전송하는 방식, 상황에 따라 동적으로 서버에서 데이터를 만들어 보내는 방식이라서 서버 사이드 프로그래밍(Server Side Programming)이라고 한다.
- 동적인 데이터를 만들어 보내는 서버는 ‘웹 애플리케이션 서버(Web Application Server = WAS)라고 부른다.

톰캣의 경우는 엄밀하게는 WAS로 보는 것이 좋지만 대부분의 WAS는 웹 서버 기능도 같이 포함하므로 정적인 자원들과 서블릿/JSP 같은 동적인 자원 모두를 처리할 수 있다.


HTTP라는 약속
- 브라우저의 요청과 서버의 응답 사이에는 ‘HTTP'라는 데이터 교환 약속을 통해 처리된다.
-웹에서는 HTTP(Hyper Text Transfer Protocol) 방식으로 데이터를 주고 받는다.  
- HTTPS는 좀 더 보안이 강화된 프로토콜이다. HTTP 메시지 구성
- HTTP 메시지는 브라우저에서 전송할 때 뿐 아니라 서버에서 데이터를 전송할 때도 사용된다.
- 다만, 브라우저에서 데이터를 보낼 때(요청(Request))의 데이터와 서버에서 브라우저로 데이터를 보낼 때 응답(Response))의 메시지는 내용과 구성이 조금 다르다.
- HTTP 메시지는 기본적으로 ’헤더(Header)'와 몸체(Body)'로 구성
- 예시로 편지와 유사한데 ‘편지’를 보내기 위해서는 편지의 봉투(헤더’Header‘)과 편지 내용물(몸체'Body')가 필요한 것 과 같다.

 


- 브라우저에서 특정 URL을 호출하면 요청과 응답이 하나의 쌍으로 묶여 처리되며, 개발자 도구에서는 [Network -> Headers] 항목에서 ‘Request Headers'와 ’Response Headers'라는 항목이 같이 보여지게 처리되어 있다. (즉, 요청과 응답이 하나의 단위로 처리된다.)

비연결성(Connectionless)
- 웹은 여러 명의 사용자가 브라우저를 통해 서버를 호출하는 구조이기 때문에 서버에서는 최대한 많은 사용자에게 서비스를 제공하기 위한 고민 끝을 했고 그 결과 HTTP는 비연결성(Connectionless)라는 방식을 채택했다.
- 이는 하나의 요청과 응답을 처리한 후에는 연결을 종료한다는 걸 의미한다.
- 예로 새로운 결과를 다시 확인하기 위해 ‘새로고침’을  하는 이유는 이미 브라우저와 서버의 연결이 끝났기 때문에 다시 연결하지 않으면 이전의 결과만 남아있기 때문이다.
- HTTP의 비연결성이라는 특징이 있어서 서버에서는 하나의 요청을 빨리 처리하고 연결을 종료해서 다음 요청을 받을 수 있어서 적은 리소스를 이용해서 많은 수의 요청들을 처리할 수 있다는 장점이 있다.

자바 서버 사이드 프로그래밍
- 서버 사이드 프로그래밍은 서버 쪽에서 프로그래밍을 통해 데이터를 처리할 수 있도록 구성하는 것을 의마하는데 개발할 때 다음 사항을 고려해야 한다.
1. 동시에 여러 요청이 들어온다면 어떻게 처리해야 하는가?
2. 서버에서 문제가 생기면 어떻게 처리해야 하는가?
3. 어떤 방법으로 데이터 전송을 최적화할 수 있는가?
4. 분산 환경이나 분산 처리와 같은 문제들은 어떻게 해결할 것인가?


매번 서비스를 개발할 때마다 이러한 고민을 새로 한다면 많은 개발 비용과 시간을 소모해야할 것이다.
그래서 자바의 경우는 이러한 처리를 JavaEE라는 기술 스펙으로 정리해 두었고, Servlet과 JSP는 JavaEE의 여러 기술 중에 하나이다.



서블릿(Servlet) 기술
- 서버에서 동적으로 요청과 응답을 처리할 수 있는 API들을 정의한 것
- 서블릿을 지원하는 환경에서 개발자는 서블릿에서 제공하는 API를 이용해서 코드를 작성하고, 이를 설정하는 방식으로 서블릿 프로그램을 작성하게 된다. (이런 이유로 톰캣 설치 시에는 어떤 서블릿 버전을 지원하는지 꼭 확인해야 한다.)

 

JSP는 근본적으로는 서블릿과 같은 원리지만, 좀 더 HTML을 쉽게 이용할 수 있는 방식으로 코드를 작성할 수 있기 때문에

'서블릿으로 코드를 이용한 처리, JSP로는 화면 개발'과 같이 역할을 분담해서 개발하는 것이 일반적이다. 

 

서블릿의 실행은 톰캣처럼 서블릿 컨테이너(Servlet Container)라는 서블릿을 실행할 수 있는 환경에서 실행이 가능하다.

과거에는 서블릿 엔진 이라고 했다. 현재는 앞서 언급했듯이 톰캣이 '서블릿 컨테이너' 역할을 하고 있다. 

 

서블릿 코드를 실행하는 주체는 톰캣과 같은 서블릿 컨테이너이므로, 일반 자바 프로그램과 비교했을 때 여러 다른 점이 있다. 

1. 객체를 생성하거나 호출하는 주체는 사용자가 아닌 서블릿 컨테이너(톰캣)가 하게 된다. 

2. 서블릿 클래스에서 생성하는 객체의 관리 자체가 서블릿 컨테이너(톰캣)에 의해 관리된다. 

3. 서블릿/JSP의 코드 개발은 기본적인 자바 API와 더불어 서블릿 API도 같이 사용해야 한다.

위의 코드를 참고해서 import의 경우 javax로 시작하는 서블릿 관련 API를 사용하고 있다. 

 

클래스 선언 자체가 HttpServlet이라는 부모 클래스가 지정되어 있다. 

내부에는 init(), doGet(), destory()가 작성되어 있는데 이는 서블릿 API에서 지정된 메소드이다. 

이 메소드들의 호출의 주체는 개발자가 아닌 서블릿 컨테이너가 서블릿을 관리하면서 호출된다. 

이러한 메소드들은 일반적으로 서블릿의 라이프 사이클(life-cycle)이라고 한다. 


JSP 기술

JSP - 'Java Server Pages'의 약자로 

서블릿 기술과 동일하게 서버에서 동적으로 데이터를 구성하는 기술이다. 

서블릿이 있는데도 '동일한 목적'으로 JSP가 제공되는 이유는 두 기술의 목적 자체가 좀 다르기 때문이다. 

 

JSP 기술은 서블릿과 달리 HTML 코드를 그대로 이용하고 필요할 때 약간의 자바 코드를 넣지만,

서블릿 코드는 자바 코드를 이용해서 HTML 문자를 만들어내는 방식의 차이가 있다. 

 

JSP 코드는 자바 코드가 아니지만 서블릿과 동일하게 처리되는데 이는 사실 JSP 파일도 서블릿 코드로 변환되어서 컴파일되고 실행되기 때문이다. 

JSP 파일은 필요한 순간 자바 파일로 생성되고, 이를 컴파일해서 class파일로도 만들어진다. 

 

결국 JSP는 서블릿 기술과 목적이 같지만, 브라우저에 보내는 HTML 데이터를 만들어내는데 좀 더 특화된 기술이다. 


서블릿과 JSP 정리

- 서블릿/JSP 모두 Java EE 스펙의 일부이다

- 서블릿/JSP를 실행하기 위해서는 서블릿 컨테이너(톰캣과 같은)가 필요하다

- 서블릿 컨테이너가 서블릿/JSP 객체를 생성하고 생명 주기를 관리한다.

- JSP는 내부적으로 서블릿과 같은 방식의 코드로 변환된다.

- JSP는 HTML 내에 자바 코드를 추가하는 방식이고, 서블릿 방식은 자바 코드 안에 HTML 코드를 추가하는 방식이다. 

 


그렇다면 JSP 위주로 개발할 때의 문제점이 무엇이기에 일반적으로 Servlet과 함께 사용하는 것일까?

우선 GET 방식과 POST 방식의 차이를 알고 가자.

 

GET 방식 - 입력과 조회

- 원하는 데이터 조회

- 사용자가 입력할 수 있는 화면을 보여주기 위해

 

쿼리 스트링(query string)과 파라미터(parameter)

- 웹 주소창 뒤에 '?'로 시작하는 내용물을 쿼리 스트링이라고 한다. 

- 번역하면 '질의 문자열'이라고 하는데, 뜻 그대로 무언가를 요구하거나 물어보는 용도로 데이터를 전달하기 위해서 사용한다. 

- '키=값'의 형태로 데이터를 전달하며 여러 개의 데이터가 필요한 경우 '&'를 이용해서 연결하다. 이러한 '키-값'형태를 흔히 '파라미터(parameter)이름과 값'이라고 한다. 

- 웹의 파라미터는 모두 문자열이다

 

POST 방식 - 처리

-주소와 전달하고자하는 데이터를 분리해서 전송하는 방식으로 브라우저를 통해서는 확인할 수 없고, 개발자 도구를 통해 확인가능하다. ([Network] - [Payload])

- GET 방식과 달리 정보의 확산이 목적이 아니므로 굳이 하나의 문자열로 모든 정보를 표현하지 않고, URL과 정보를 따로 구분해서 전달한다. (HTTP 몸체(Body)로 쿼리 스트링)

- 단순 조회가 아닌 원하는 작업을 처리할 수 있게 된다.

 

이제 JSP 위주로 개발시 문제점에 대해 살펴보자.

(1) JSP는 기본적으로 GET/POST 방식의 호출을 구분하지 않는다. 

따라서 POST방식으로 접근해야 하는데 GET 방식으로도 호출할 수 있다는 큰 문제가 있다.

(2) 유지 보수 측면에서의 문제인데, 예를 들어 a.jsp 대신 b.jsp처럼 다른 JSP 파일로 변경했을 때 과거의 a.jsp만 알고 있는 사용자들에게는 다시 주소가 변경되었다는 점을 알려줘야하는 작업이 발생하게 된다. 

 

따라서 최근에 JSP는 다음과 같이 제한적인 용도 사용한다.

- JSP에서 쿼리 스트링이나 파라미터를 처리하지 않는다. - JSP 대신에 서블릿을 통해서 처리

- JSP는 입력 화면을 구성하거나 처리 결과를 보여주는 용도로만 사용한다.

- 브라우저는 직접 JSP 경로를 호출하지 않고 서블릿 경로를 통해서 JSP를 보는 방식으로 사용한다. 

 

 

 

 

 

 


참고자료 - 자바 웹 개발 워크북(2022) | 프리렉

https://freelec.co.kr/book/%EC%9E%90%EB%B0%94-%EC%9B%B9-%EA%B0%9C%EB%B0%9C-%EC%9B%8C%ED%81%AC%EB%B6%812022/