[JSP] 자바 웹 프로그래밍 시작하기

[Must Have] 성낙현의 JSP 자바 웹 프로그래밍 중
골든래빗 출판사
성낙현 지음

JSP(Java Server Pages)는 동적인 웹 페이지를 개발하기 위한 웹 프로그래밍 기술입니다. 이름에서처럼 자바(Java) 언어를 사용하여 서버(Server) 측에서 웹 페이지들(Pages)을 생성해 웹 브라우저로 전송해줍니다. 자바를 서버 개발 언어로 자리 잡게 한 일등공신입니다.

이 글은 자바 기초를 마치고 이제 막 웹 프로그래밍을 시작한 분들을 위한 가이드입니다. JSP의 개념, 탄생 배경, 동작 원리와 JSP 파일의 기본 구조와 핵심 요소를 정리했습니다.

 

[JSP] 자바 웹 프로그래밍 시작하기

 

JSP는 기업용 자바 기술의 집합체인 Java EE(Java Platform, Enterprise Edition)의 핵심요소이며, Java EE는 대한민국 정부 표준 프레임워크의 근간입니다. 따라서 정부나 공기업 주도의 사업 등 대규모 기업용 시스템 구축에 주로 사용됩니다. 또한 클라우드 시대가 되면서 구글 앱 엔진과 아마존 웹 서비스(AWS) 등에서도 지원하기 시작하면서 활용 폭이 더욱 넓어졌습니다.

 

💡 기본 용어 소개

기본적인 용어 몇 가지를 그림을 곁들여 설명하고 시작하겠습니다. 아시는 용어라면 건너뛰셔도 무방합니다. 이 외에도 알아야 할 용어가 많지만, 입문 과정에서 모두를 다룰 수는 없으니 단계별로 필요할 때 더 설명하겠습니다.

 

 

서버(Server)

웹에서 서비스를 제공하는 컴퓨터 시스템을 말합니다. 서버는 우리말로 레스토랑에서 ‘시중드는 사람’ 정도로 비유할 수 있습니다. 우리는 주로 정보를 검색하기 위해 포털 사이트를 이용하고, 필요한 물품을 구매하기 위해 쇼핑몰을 이용하게 되는데, 이런 서비스를 제공하는 웹 애플리케이션은 서버 컴퓨터에 파일의 형태로 저장되어 있습니다.

 

웹 서버(Web Server)

사용자로부터 HTTP를 통해 요청을 받거나, 웹 컨테이너가 전달해준 결과물을 정적인 페이지로 생성하여 사용자에게 응답해주는 소프트웨어를 말합니다. 웹 페이지는 주로 HTML, CSS, 자바스크립트 등으로 구성됩니다.

 

웹 컨테이너(Web Container)

웹 서버가 전송해준 요청을 기초로 동적인 페이지를 생성하여 웹 서버로 돌려줍니다. ‘동적’인 페이지라고 표현하는 이유는 사용자마다 다른 결과로 응답할 수 있기 때문인데, 간단한 예로 로그인이 있습니다. 로그인한 아이디를 보고 각자에 맞는 페이지를 구성해 보내주는 것입니다.

 

WAS(Web Application Server)

웹 애플리케이션이 실행될 수 있는 환경을 제공하는 소프트웨어로, 컴퓨터에서 운영체제(윈도우, 리눅스 등)와 비슷한 역할을 하는 소프트웨어라 할 수 있습니다. WAS는 앞에서 설명한 웹 서버와 웹 컨테이너를 포함한 개념입니다. 톰캣(Tomcat)이 대표적인 예이며, 그 외에 웹로직(WebLogic), 웹스피어(WebShpere) 등의 제품이 있습니다.

 

HTTP(HyperText Transfer Protocol) / HTTPS(HTTP Secure)

보통 www라고 줄여 쓰는 월드 와이드 웹(World Wide Web)에서 웹 서버와 사용자 사이의 통신을 위해 사용하는 통신 프로토콜입니다. 사용자가 요청하면 웹 서버가 응답하는 단순한 구조의 프로토콜입니다. HTTPS는 암호화된 HTTP입니다.

 

프로토콜(Protocol)

네트워크를 통해 컴퓨터들이 정보를 주고받는 절차 혹은 통신 규약을 말합니다. 한국인과 미국인이 각자의 모국어로만 말을 한다면 제대로 소통할 수 없겠죠? 컴퓨터도 마찬가지입니다. 이때 프로토콜은 서로 다른 컴퓨터들이 대화하는 데 필요한 공통 언어 역할을 해줍니다. 앞에서 설명한 HTTP도 프로토콜의 한 종류이고, 다른 프로토콜로는 파일 전송을 위한 FTP(File Transfer Protocol), 이메일 전송을 위한 SMTP(Simple Mail Transfer Protocol) 등이 있습니다.

 

포트(Port)

포트를 직역하면 ‘항구’라는 뜻인데, 컴퓨터 사이에서 데이터를 주고받을 수 있는 통로를 말합니다. 인터넷에서는 IP 주소를 통해 서버 컴퓨터의 위치를 파악합니다. 그런 다음 그 컴퓨터가 제공하는 특정 서비스는 포트 번호를 통해 알 수 있습니다. 우리가 이용하는 인터넷상의 모든 서비스는 IP 주소와 함께 포트 번호까지 지정해야 제대로 요청을 전달할 수 있습니다. 대표적으로 HTTP는 80번 포트를, 보안이 적용된 HTTPS는 443번 포트를 사용합니다.

 

1. 동적 웹 페이지로의 여정과 JSP

JSP란 동적 웹 페이지를 쉽고 빠르게 제작할 수 있도록 자바가 제시한 궁극적인 해법입니다. 그렇다면 동적 웹 페이지란 도대체 무엇이고 왜 필요한지, 그리고 JSP라는 해법을 찾기까지 어떤 여정을 거쳐왔는지를 가볍게 살펴보면서 JSP의 주요 특징까지 알아보겠습니다.

 

1.1 정적 웹 페이지와 동적 웹 페이지

정적 웹 페이지(Static Web Page)란 웹 서버에 ‘저장되어 있는 파일을 그대로’ 웹 브라우저에 전송해 출력하는 가장 기본적인 웹 페이지를 말합니다. 클라이언트가 어떤 형태로 요청하더라도 같은 페이지는 항상 동일한 모습을 보여주기 때문에 ‘정적’이란 수식어가 붙습니다.

반면 동적 웹 페이지(Dynamic Web Page)란 동일한 페이지라 할지라도 그때그때 내용이 달라질 수 있는 웹 페이지입니다. 달리 표현하면 서버가 클라이언트의 요청을 해석하여 가장 적절한 웹 페이지를 그때그때 생성해 보내주는 기술입니다. 따라서 클라이언트는 요청한 계정, 시간, 지역, 언어, 기타 입력값에 따라 다른 결과를 받습니다.

 

▼ 정적 웹 페이지 구동 방식

 

▼ 동적 웹 페이지 구동 방식

 

그림에서 보듯 동적 웹 페이지는 ‘전처리’ 과정을 거쳐 응답 페이지를 동적으로 생성합니다. 그리고 이 전처리를 어떻게 처리하느냐에 따라 구체적인 동적 웹 페이지 기술이 나뉩니다. 대표적으로는 JSP와 서블릿이 있고, 다른 기술로는 ASP와 PHP 등이 있습니다.

 

1.2 애플릿, 동적 웹을 향한 자바의 첫걸음

동적 웹 페이지 기술로 분류되지는 않습니다만 웹을 동적으로 만들기 위한 고대의 자바 기술이 있었으니, 바로 자바 애플릿(Java Applet)입니다. 자바 애플릿은 웹에서 실행되도록 설계된 자바 애플리케이션을 통째로 웹 브라우저로 전송한 후, 자바 가상 머신을 탑재한 웹 브라우저가 이를 실행하는 방식으로 구동됩니다.

동적 웹 기술이 발달하기 전 시절에는 한때 이목을 끌었지만, 표준 기술인 HTML과 자바스크립트가 발전하면서 지금은 더 이상 지원되지 않는 추억의 기술이 되었습니다.

 

1.3 서블릿, 자바 웹 기술의 새 지평을 열다

애플리케이션 전체가 클라이언트에 다운로드된 후 실행되는 자바 애플릿은 속도, 보안, 유연성 등에서 한계가 있었습니다. 그래서 서버 측에서 실행되는 서블릿(Servlet)이 등장했습니다. 서블릿은 클라이언트의 요청을 받으면 서버에서 처리한 후, 응답으로는 결괏값만 보내주는 구조입니다.

 

▼ 서블릿 구동 방식(저장소와 DB 생략)

 

앞서 보여준 동적 웹 페이지 방식에서의 ‘전처리’ 부분을 서블릿이 담당하는 구조입니다. 서블릿은 자바 파일(.java)을 컴파일한 클래스 파일(.class) 형태이며, 이를 실행하고 관리해주는 런타임을 서블릿 컨테이너라고 합니다. 대표적인 서블릿 컨테이너로는 아파치 톰캣(Apache Tomcat)이 있습니다.

 

1.4 JSP, 자바 웹 기술의 최종 진화

서블릿에도 단점이 있었습니다. 서블릿은 기본적으로 자바 코드인데, 결과로 보여줄 HTML 코드를 일일이 자바로 생성·조합하다 보니 너무 많은 코드가 필요했습니다. 그래서 발상을 전환하여, 기본을 HTML로 하고 필요한 부분만 자바 코드를 삽입하는 형태인 JSP가 탄생하게 되었습니다.

 

▼ JSP 구동 방식

 

그림에서 보듯 JSP의 구동 방식은 다소 복잡해 보이지만, 알고 보면 JSP 파일을 서블릿으로 변환하여 서블릿을 실행하는 방식입니다. 한 번 서블릿으로 컴파일된 JSP 파일은 캐시되므로 실질적인 성능 저하 없이 개발 생산성과 유지보수 편의성을 모두 얻는 멋진 아이디어인 셈이죠.

또한 JSP가 서블릿으로 변환되어 실행된다는 것은 서블릿 기술도 여전히 사용할 수 있다는 뜻입니다. 그래서 용도에 따라 더 유리한 기술을 골라 사용할 수 있습니다. 실제로 JSP는 클라이언트에 보여지는 결과 페이지를 생성할 때 주로 쓰이며, 서블릿은 UI 요소가 없는 제어나 기타 처리 용도로 쓰입니다. 두 기술의 주요 차이를 표로 정리해봤습니다.

 

▼ 서블릿과 JSP의 주요 차이

 

1.5 오늘날의 웹 사이트

지금까지 자바를 중심으로 동적 웹 페이지 기술의 발전 과정을 알아보았습니다. 하지만 동적 웹이 반드시 좋은 것만은 아닙니다. 정적 웹 페이지가 더 만들기 쉽고 속도도 빠르며 운영 비용도 저렴하죠. 그래서 내용이 변하지 않는 콘텐츠라면 정적 웹으로 구성하는 게 합리적입니다.

실제로 대부분의 웹 사이트나 웹 애플리케이션은 정적인 콘텐츠와 동적인 콘텐츠가 섞여 있습니다. 그래서 자연스럽게 오늘날의 웹은 정적 웹 페이지와 동적 웹 페이지가 혼합된 형태를 띱니다.

 

▼ 오늘날의 일반적인 웹 구동 방식(자바 중심)

 

이상으로 JSP의 탄생 배경과 특징, 그리고 오늘날의 웹 구동 방식을 알아봤습니다. 이어서 JSP 파일의 기본 구조, 핵심 구성요소인 지시어와 스크립트 요소를 차례로 살펴보겠습니다.

 

2. JSP 파일 기본 구조

JSP의 주된 목적은 웹 브라우저에 띄울 HTML 파일을 생성하는 것입니다. 그리고 그 형태는 다음 예제와 같습니다.

 

 

예제에서 보듯 일반적인 HTML 파일에 몇 가지 요소가 추가된 형태입니다. 크게 보면 지시어와 스크립트 요소가 있으며, 스크립트 요소는 다시 세 가지(선언부, 표현식, 스크립틀릿)로 나뉩니다. 지시어는 해당 JSP 페이지의 처리 방법을 JSP 엔진에 ‘지시’해주는 역할을 하며, 스크립트 요소는 HTML 파일 중간에 자바 코드를 삽입할 때 사용합니다.

본문에서는 지시어와 스크립트 요소 모두를 학습하도록 하겠습니다.

 

3. 지시어(Directive)

지시어는 JSP 페이지를 자바(서블릿) 코드로 변환하는 데 필요한 정보를 JSP 엔진에 알려줍니다. 주로 스크립트 언어나 인코딩 방식 등을 설정합니다. 지시자 혹은 디렉티브로 부르기도 합니다.

기본 구문은 다음과 같습니다.

 

<%@ 지시어종류 속성1="값1" 속성2="값2" ... %>

 

보다시피 지시어 종류 뒤에 다수의 속성을 지정할 수 있는 구조입니다. 사용할 수 있는 속성은 지시어마다 다르며, 지시어 종류는 다음 세 가지가 있습니다.

  • page 지시어 : JSP 페이지에 대한 정보를 설정합니다.
  • include 지시어 : 외부 파일을 현재 JSP 페이지에 포함시킵니다.
  • taglib 지시어 : 표현 언어에서 사용할 자바 클래스나 JSTL을 선언합니다.

하나씩 자세히 들여다보겠습니다.

 

3.1 page 지시어

page 지시어는 JSP 페이지에 대한 정보를 설정합니다. 예를 들어 문서의 타입, 에러 페이지, MIME 타입과 같은 정보를 설정합니다. 주요 속성들을 아래에 정리했습니다.

 

▼ page 지시어의 속성들

 

이어서 이 속성들이 실제로 어떻게 쓰이는지 예시와 함께 살펴보겠습니다.

 

language, contentType, pageEncoding 속성

이클립스에서 JSP 파일을 생성하면 다음의 3가지 속성을 포함한 page 지시어가 기본적으로 삽입됩니다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>

 

이 지시어를 해석하면 다음과 같습니다.

  • language : 스크립팅 언어는 자바를 사용합니다.
  • contentType : 문서의 타입, 즉 MIME 타입은 text/html이고, 캐릭터셋은 UTF-8입니다.
  • pageEncoding : 소스 코드의 인코딩 방식은 UTF-8입니다.

 

캐릭터셋이나 인코딩의 기본값은 ISO-8859-1인데, 영어와 서유럽어 문자만 포함하고 있어서 한글은 제대로 출력되지 않습니다. 그래서 한글을 표현하기 위해서는 EUC-KR이나 UTF-8을 사용해야 하며, 최근에는 다국어를 지원하는 UTF-8을 주로 사용합니다. 우리는 0장에서 이클립스 설치 후 기본 파일 인코딩을 UTF-8로 이미 변경했습니다.

 

import 속성

JSP 파일은 자바 파일로 변환된다고 했습니다. 자바에서 외부 클래스를 사용하려면 import문으로 해당 패키지나 클래스를 가져와야 하듯이, JSP 파일에서도 필요한 클래스가 있으면 임포트해야 합니다. 이때 사용하는 것이 바로 page 지시어의 import 속성입니다. 자바 프로그래밍 때와 마찬가지로 java.lang 패키지에 속하지 않은 클래스를 JSP 문서에서 사용하기 위해 사용합니다.

예를 보시죠.

 

▼ import 속성으로 외부 클래스 불러오기

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ page import="java.text.SimpleDateFormat"%>  // ❶ 필요한 외부 클래스 임포트
<%@ page import="java.util.Date"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - import 속성</title>
</head>
<body>
<%
Date today = new Date();  // ❷ 외부 클래스 생성
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String todayStr = dateFormat.format(today);
out.println("오늘 날짜 : " + todayStr);  // ❸ 오늘 날짜를 웹 브라우저에 출력
%>
</body>
</html>

 

이 코드는 ❷ Date와 SimpleDateFormat 클래스를 이용하여 ❸ 오늘 날짜를 출력하고 있습니다. 이 두 클래스는 java.lang 패키지에 속하지 않습니다. 그래서 현재 문서에서 사용하기 위해서는 ❶ 페이지 상단에서 page 지시어를 사용해 임포트해야 합니다.

Ctrl + F11 을 눌러 실행하면 다음과 같이 오늘 날짜를 보여줍니다.

 

 

💡Tip: 이클립스는 코드 자동완성 기능이 있어서 필요한 파일을 쉽게 임포트할 수 있습니다. 편집창에서 Date를 입력한 후 Ctrl + Space 를 눌러보면(메뉴에서 [Edit] → [Content Assist]) 다음과 같이 이름에 Date가 포함된 여러 가지 클래스가 목록으로 표시됩니다. 여기서 우리가 사용할 java.util 패키지의 Date 클래스를 선택하면 페이지 지시어가 자동으로 삽입됩니다.

 

 

errorPage, isErrorPage 속성

JSP는 실행 도중에 에러가 발생하면 “HTTP Status 500” 에러 화면을 웹 브라우저에 표시해줍니다. 개발을 진행하는 중이라면 어떤 에러가 발생되었는지 확인할 수 있으므로 도움이 됩니다. 하지만 실제로 서비스하는 도중 에러 화면이 뜬다면 고객의 신뢰를 잃는 요인이 될 것입니다. 또한 에러가 발생된 코드의 일부가 노출되므로 보안 측면에서도 좋지 않습니다.

에러가 발생하는 코드를 작성하여 결과를 확인해보고, 이어서 이를 적절히 처리할 수 있는 방법을 알아보겠습니다.

 

▼ 에러 발생 페이지

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - errorPage, isErrorPage 속성</title>
</head>
<body>
<%
int myAge = Integer.parseInt(request.getParameter("age")) + 10;  // ❶ 에러 발생
out.println("10년 후 당신의 나이는 " + myAge + "입니다.");  // 실행되지 않음
%>
</body>
</html>

 

❶ 에서는 내장 객체인 request로부터 “age” 매개변수의 값을 받아와 정수로 변환합니다. 하지만 최초 실행 시에는 매개변수가 없으므로 null 값이 전달되어 예외(에러)가 발생합니다.

그래서 위 예제를 실행하면 다음과 같은 에러 페이지가 표시됩니다. 스크립틀릿 안에 작성한 코드가 그대로 노출되는 걸 볼 수 있습니다.

 

 

고객이 웹서핑 도중 이런 페이지를 보게 된다면 사이트에 대한 신뢰가 많이 떨어져 두 번 다시 방문하지 않을지도 모릅니다. 따라서 이런 상황은 미연에 방지하는 것이 좋습니다. 방법은 두 가지입니다.

  1. try/catch를 사용하여 직접 에러를 처리합니다.
  2. errorPage, isErrorPage 속성을 사용하여 디자인이 적용된 페이지로 대체합니다.

 

먼저 try/catch를 사용하여 에러를 직접 처리해보겠습니다.

 

▼ try/catch 구문으로 직접 처리

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - errorPage, isErrorPage 속성</title>
</head>
<body>
<%
try {  // ❶ 예외 발생 부분을 감쌉니다.
    int myAge = Integer.parseInt(request.getParameter("age")) + 10;
    out.println("10년 후 당신의 나이는 " + myAge + "입니다.");
}
catch (Exception e) {
    out.println("예외 발생 : 매개변수 age가 null입니다.");
}
%>
</body>
</html>

 

보다시피 ❶ 예외 발생 부분을 try/catch 구문으로 감쌌습니다. 이 페이지는 실행하는 즉시 예외가 발생하므로 catch절이 실행됩니다. 다음은 이 페이지의 실행 결과입니다.

 

 

앞에서 봤던 뭔가 무시무시한 화면이 아닌 일반적인 화면이 나타났습니다. 에러 내용이나 관련 코드는 말끔히 사라졌습니다. 에러의 구체적인 내용은 로그를 통해 개발자만 확인할 수 있습니다.

두 번째는 개발자가 지정한 JSP 화면을 보여주는 방법인데, 이때 errorPage, isErrorPage 속성을 사용합니다.

❶ 우선 ErrorPage.jsp 파일을 생성한 후 ❷ 에러 발생 페이지 예제의 Error500.jsp 코드를 그대로 붙여 넣고 ❸ 아래 예제처럼 상단 지시어 부분에 errorPage 속성을 추가합니다.

 

▼ errorPage 속성으로 에러 페이지 지정

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    errorPage="IsErrorPage.jsp"%>  // ❶ 에러 페이지 지정

 

이렇게 하면 페이지에서 에러가 발생했을 때 직접 처리하지 않고, ❶ 에서 errorPage 속성으로 지정한 페이지를 웹 브라우저에 출력합니다. 즉, 이 페이지에서 에러가 발생하면 웹 브라우저에는 IsErrorPage.jsp가 출력됩니다.

그렇다면 IsErrorPage.jsp 파일은 어떻게 구성하면 될까요?

 

▼ isErrorPage 속성을 설정한 에러 페이지 작성

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    isErrorPage="true"%>  // ❶ isErrorPage 속성에 true를 지정
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - errorPage/isErrorPage 속성</title>
</head>
<body>
    <h2>서비스 중 일시적인 오류가 발생하였습니다.</h2>
    <p>
        오류명 : <%= exception.getClass().getName() %> <br />  ❷
        오류 메시지 : <%= exception.getMessage() %>
    </p>
</body>
</html>

 

에러 페이지에서는 1 반드시 isErrorPage 속성을 “true”로 설정해줘야 합니다. 그래야만 발생된 에러 내용을 그대로 넘겨받을 수 있습니다. 참고로 2 에서는 페이지 내용을 구성하기 위해 exception 내장 객체로부터 발생한 예외의 타입과 메시지를 얻어왔습니다.

ErrorPage.jsp를 실행해보겠습니다.

 

 

주소 표시줄에는 ErrorPage.jsp가 표시되지만, 화면에는 IsErrorPage.jsp의 내용이 출력됩니다. 이렇듯 exception 내장 객체를 통해 발생된 오류 이름과 오류 메시지를 확인할 수 있었습니다. 하지만 실제 서비스에서는 오류 메시지를 표시하지 않고 대부분 사용자에게 친근한 모습으로 디자인된 페이지를 사용하여 출력합니다.

 

trimDirectiveWhitespaces 속성

앞의 예제들을 실행한 후 → 마우스 우클릭 → [페이지 소스 보기]를 클릭해서 보면 상단에 항상 공백이 있는 걸 확인할 수 있습니다. 다음 이미지는 Import.jsp를 실행한 후 소스 보기를 한 모습입니다.

 

 

3줄의 공백이 보이는데, 이는 3개의 page 지시어가 있던 부분입니다. page 지시어가 웹 서버에서 처리된 후 공백으로 남게 되는 것입니다.

일반적으로는 큰 문제가 없지만 안드로이드와 같은 외부 기기와 연동 시 가끔 문제를 일으키기도 합니다. 공백space도 컴퓨터 입장에서는 엄연한 하나의 문자이기 때문입니다. 그래서 지시어 때문에 생성된 불필요한 공백을 제거하고 싶다면 trimDirectiveWhitespaces 속성을 사용합니다.

 

▼ page 지시어로 생긴 공백 제거

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"
    trimDirectiveWhitespaces="true"%>  ❶
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - trimDirectiveWhitespaces 속성</title>
</head>
<body>
    <h2>page 지시어로 생긴 불필요한 공백 제거</h2>
</body>
</html>

 

❶ page 지시어 속성에 trimDirectiveWhitespaces를 추가하여 true로 설정했습니다. 실행 후 소스 보기를 해보면 다음과 같이 상단 공백이 제거된 것을 알 수 있습니다.

 

 

buffer, autoFlush 속성

앞서 몇 가지의 예제를 통해 JSP 코드를 작성하고 실행해보았습니다. 마치 결과물이 즉시 웹 브라우저에 출력되는 것처럼 보이지만 실제로 JSP의 실행 과정은 복잡합니다. JSP 파일은 서블릿 코드로 변환된 후 컴파일되어 class 파일로 만들어집니다. 이를 실행한 결과물을 HTML 형태로 웹 브라우저에 보내 최종적으로 화면에 출력하는 것입니다.

또한 이 과정에서 응답 결과를 웹 브라우저로 즉시 전송하지 않고, 출력할 내용을 버퍼에 저장했다가 일정량이 되었을 때 전송하게 됩니다.

 

💡버퍼란?

버퍼(Buffer) 개념은 매우 다양하게 사용되며, 가장 쉽게 접할 수 있는 곳은 유튜브 같은 스트리밍 서비스입니다. 네트워크로 영상 데이터를 전송할 때, 작은 단위로 여러 번 전송하는 것보다 큰 단위로 묶어서 한 번에 보내는 편이 훨씬 효율적입니다. 그래서 이때 버퍼라는 임시 저장소를 두어 데이터들이 충분히 쌓일 때까지 기다렸다가 보내는 것입니다.

 

 

JSP에서는 버퍼를 사용함으로써 포워드(forward; 페이지 전달)와 에러 페이지 처리를 할 수 있습니다. JSP가 생성한 결과는 일단 버퍼에 저장됩니다. 만약 실행 도중 에러가 발생하면 버퍼에 저장된 내용을 삭제하고 에러 화면을 표시하는 것이죠.

 

page 지시어의 buffer 속성으로는 버퍼의 크기를 설정할 수 있습니다(기본값은 8kb입니다).

 

<%@ page buffer="1kb"%>

 

버퍼를 사용하고 싶지 않다면 “none”으로 지정합니다.

 

<%@ page buffer="none"%>

 

단, 버퍼를 사용하지 않으면 포워드나 에러 페이지 기능을 사용할 수 없습니다. 따라서 “none”으로 지정하는 경우는 거의 없습니다. 즉 buffer 속성을 통해 버퍼의 크기나 사용 여부를 지정할 수는 있으나, 크기를 줄이면 JSP의 기능을 온전히 사용할 수 없게 되므로 거의 사용하지 않습니다.

이어서 autoFlush 속성은 버퍼가 모두 채워졌을 때의 처리 방법을 정하는 데 쓰입니다. 값은 true”와 “false” 중 선택할 수 있으며, 의미는 다음과 같습니다.

  • true(기본값) : 버퍼가 채워지면 자동으로 플러시합니다.
  • false : 버퍼가 채워지면 예외를 발생시킵니다.

💡플러시(flush)란 버퍼 안의 데이터를 목적지로 전송하고 버퍼를 비우는 작업을 말합니다.

 

예제를 통해 버퍼와 플러시를 더 자세히 알아보겠습니다.

 

▼ 버퍼와 플러시

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" buffer="1kb" autoFlush="false"%>  // ❶ 버퍼 설정
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>page 지시어 - buffer, autoFlush 속성</title>
</head>
<body>
<%
for (int i = 1; i <= 100; i++) {  // ❷ 버퍼 채우기
    out.println("abcde12345");
}
%>
</body>
</html>

 

❶ 에서 버퍼를 “1kb”로, autoFlush를 “false”로 설정했습니다. 즉, 버퍼 크기를 줄인 후 버퍼가 가득 차면 에러가 나도록 했습니다.

그런 다음 ❷ 에서 for문을 이용해 10글자(10바이트)로 구성된 문자열을 100번 반복 출력합니다. 즉, 버퍼 크기에 해당하는 1kb를 출력합니다. 이 파일에는 <html>과 같은 태그가 포함되어 있으므로 결과적으로 1kb를 넘기게 됩니다.

그래서 예제를 실행하면 다음과 같은 에러가 발생합니다.

 

 

페이지에 출력되는 내용이 buffer 속성으로 설정한 1kb를 초과하여 에러가 발생한 겁니다. 보다시피 이와 같이 설정하면 JSP의 기능을 온전히 사용할 수 없으므로 특수한 경우가 아니라면 거의 사용되지 않습니다.

여기까지 page 지시어와 그 속성을 알아보았습니다. page 지시어는 JSP 페이지에 대한 정보를 설정합니다. 각 속성의 설정값에 따라 JSP의 동작 방식이 달라지므로, 속성별 기능을 정확히 알고 사용해야 할 것입니다.

 

3.2 include 지시어

많은 웹 사이트에서 상단 메뉴나 하단 정보(회사 연락처 등)가 여러 페이지에서 반복되어 사용되는 걸 볼 수 있습니다. 또한 뒤에서 학습할 세션 확인과 같은 작업도 모든 페이지에 삽입해야 하는 경우가 많습니다. 이럴 때 반복되는 부분을 별도의 파일에 작성해두고 필요한 페이지에서 include 지시어로 포함시킬 수 있습니다.

include 지시어의 형식은 다음과 같습니다.

 

<%@ include file="포함할 파일의 경로"%>

 

그럼 예제를 통해 알아보도록 하겠습니다. 2개의 파일을 작성할 것입니다. 먼저 포함시킬 첫 번째 JSP를 생성합니다.

 

▼ 공통 UI 요소를 담은 JSP 파일(포함될 파일)

<%@ page import="java.time.LocalDateTime"%>
<%@ page import="java.time.LocalDate"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%
LocalDate today = LocalDate.now();  // 오늘 날짜
LocalDateTime tomorrow = LocalDateTime.now().plusDays(1);  // 내일 날짜
%>

 

간단히 오늘 날짜와 내일 날짜를 구하는 코드를 담고 있는 파일입니다. 이 파일은 다음에 작성할 IncludeMain.jsp에 포함시킬 페이지이므로 <html>과 같은 태그는 모두 제거한 후 작성합니다. 단, page 지시어까지 제거하면 JSP가 동작하지 않으므로 주의해야 합니다. JSP 파일에서 page 지시어는 필수라는 사실을 절대 잊어서는 안 됩니다.

💡Warning: 포함시킬 파일에서도 page 지시어는 생략하면 안 됩니다.

 

이번에는 두 번째 JSP를 생성해보겠습니다.

 

▼ 다른 JSP 파일을 포함하는 JSP 파일

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ include file = "IncludeFile.jsp" %>  // ❶ 다른 JSP 파일(IncludeFile.jsp) 포함
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>include 지시어</title>
</head>
<body>
<%
out.println("오늘 날짜 : " + today);  // ❷ IncludeFile.jsp에서 선언한 변수 사용
out.println("<br/>");
out.println("내일 날짜 : " + tomorrow);
%>
</body>
</html>

 

❶ 에서 include 지시어를 이용하여 IncludeFile.jsp 파일을 포함시켰습니다. 그러면 대상 파일의 소스 자체가 이 문서에 포함됩니다. 그 결과 ❷ 에서는 IncludeFile.jsp에서 선언한 변수인 today와 tomorrow를 사용할 수 있게 됩니다.

 

 

include 지시어로 다른 문서를 포함시키면 먼저 ‘파일의 내용 그대로를 문서에 삽입’한 후 ‘컴파일’이 진행됩니다. 따라서 하나의 페이지가 됩니다.

 

3.3 taglib 지시어

taglib은 EL(표현 언어)에서 자바 클래스의 메서드를 호출하거나 JSTL(JSP 표준 태그 라이브러리)을 사용하기 위한 지시어입니다.

 

4. 스크립트 요소(Script Script Elements)

스크립트 요소는 JSP에서 자바 코드를 직접 작성할 수 있게 해줍니다. 용도에 따라 선언부, 스크립틀릿, 표현식이 있습니다.

JSP는 클라이언트의 요청을 받아 실행될 때 서블릿(자바 코드)으로 변환되고, 클래스로 컴파일된 후 응답하게 됩니다. 이 변환 과정에서 _jspService(   ) 메서드가 생성되는데, 변환된 코드의 위치는 스크립트 요소에 따라 _jspService(   ) 메서드 내부 혹은 외부에 놓일 수 있습니다.

 

4.1 선언부(Declaration)

선언부에서는 스크립틀릿이나 표현식에서 사용할 멤버 변수나 메서드를 선언합니다. 서블릿으로 변환 시 _jspService(   ) 메서드 ‘외부’에 선언됩니다.

 

<%! 메서드 선언 %>

 

메서드를 선언하는 방법은 자바와 동일하므로 예제를 다룰 때 설명하도록 하겠습니다.

 

4.2 스크립틀릿(Scriptlet)

JSP 페이지가 요청을 받을 때 실행돼야 할 자바 코드를 작성하는 영역입니다. 서블릿으로 변환 시_jspService(   ) 메서드 ‘내부’에 그대로 기술됩니다.

 

<% 자바 코드 %>

 

자바에서는 메서드 내부에 또 다른 메서드를 선언하는 게 불가능합니다. 이건 자바의 문법이죠.만약 스크립틀릿에 메서드를 선언한다면 _jspService(   ) 내부에 또 다른 메서드를 선언하는 꼴이므로 에러가 발생합니다. 즉, 스크립틀릿에서는 선언부에서 정의한 메서드를 호출만 할 수 있을 뿐, 다른 메서드를 선언할 수는 없습니다.

 

 

그림과 같이 스크립틀릿에서 메서드를 선언하면 IDE가 즉시 에러라고 표시해줍니다.

 

4.3 표현식(Expression)

프로그래밍 언어에서 표현식은 ‘실행 결과로 하나의 값이 남는 문장’을 뜻합니다. 즉, 상수, 변수, 연산자를 사용한 (수)식, ‘반환값이 있는’ 메서드 호출 등이 모두 표현식에 속합니다. JSP의 표현식도 이와 마찬가지로, 주로 변수의 값을 웹 브라우저 화면에 출력할 때 사용합니다. 스크립틀릿 안에서 변수를 출력할 때는 out.print(   )를 사용해야 하지만, 좀 더 단순한 방법으로 출력하기 위해 사용됩니다.

 

<%= 자바 표현식 %>

 

학습 마무리

JSP의 기본 구조를 학습하였습니다. JSP는 지시어와 스크립트 요소로 이루어집니다. 지시어는 JSP에 대한 가장 기본적인 설정을 하는 요소입니다. 지시어에는 page, include, taglib 3가지가 있습니다. 페이지에 대한 기본적인 설정을 하였다면 클라이언트의 요청을 처리할 자바 코드를 작성해야 할 텐데요, 이때 스크립트 요소를 이용해 자바 코드를 삽입할 수 있습니다. 스크립트 요소에는 선언부, 스크립틀릿, 표현식 3가지가 있습니다.

 

핵심 요약

지시어

  • page 지시어 : JSP 페이지에 대한 문서의 타입, 에러 페이지, MIME 타입과 같은 정보들을 설정합니다.
  • include 지시어 : JSP에서 또 다른 JSP나 HTML 페이지를 포함시킬 때 사용합니다.
  • taglib 지시어 : EL(표현 언어)에서 자바 클래스의 메서드를 호출하거나, JSTL(JSP 표준 태그 라이브러리)을 사용하기 위해 선언합니다.

 

스크립트 요소

  • 선언부 : 멤버 변수나 메서드를 선언할 때 사용하는 영역입니다.
  • 스크립틀릿 : 선언부에서 선언된 메서드를 호출하거나 자바 코드를 작성하는 영역입니다.
  • 표현식 : 주로 변수의 값을 간단하게 출력할 때 사용합니다.

성낙현
월드컵으로 뜨거웠던 2002년부터 웹 개발을 시작하여 에듀웰 모바일 웹 기획 및 개발, 마이닥터 웹/앱 개발(앱스토어 의료부문 1위), 국민건강보험 건강마라톤대회 앱 개발 등 다양한 앱 개발과 프로젝트를 두루 경험하였다. 현재는 한국소프트웨어인재개발원에서 JAVA 개발자 과정을 강의하고 있다.

1 Comment

Leave a Reply

©2020 GoldenRabbit. All rights reserved.
상호명 : 골든래빗 주식회사
(04051) 서울특별시 마포구 양화로 186, 5층 512호, 514호 (동교동, LC타워)
TEL : 0505-398-0505 / FAX : 0505-537-0505
대표이사 : 최현우
사업자등록번호 : 475-87-01581
통신판매업신고 : 2023-서울마포-2391호
master@goldenrabbit.co.kr
개인정보처리방침
배송/반품/환불/교환 안내