배포 설명자: web.xml

리전 ID

REGION_ID는 앱을 만들 때 선택한 리전을 기준으로 Google에서 할당하는 축약된 코드입니다. 일부 리전 ID는 일반적으로 사용되는 국가 및 주/도 코드와 비슷하게 표시될 수 있지만 코드는 국가 또는 주/도와 일치하지 않습니다. 기존 앱은 App Engine URL에 REGION_ID.r을 포함하는 것이 선택사항이며, 신규 앱은 모두 곧 필수가 될 예정입니다.

원활한 전환을 위해 리전 ID를 사용하도록 App Engine을 천천히 업데이트하고 있습니다. 아직 Google Cloud 프로젝트가 업데이트되지 않은 경우에는 앱의 리전 ID가 표시되지 않습니다. 기존 앱에서 ID는 선택사항이므로 기존 앱에서 리전 ID를 사용할 수 있게 되더라도 URL을 업데이트하거나 다른 변경을 수행할 필요가 없습니다.

리전 ID에 대해 자세히 알아보세요.

자바 웹 애플리케이션은 배포 설명자 파일을 사용하여 URL이 서블릿에 매핑되는 방법, 인증이 필요한 URL 등의 정보를 확인합니다. 이 파일은 이름이 web.xml이며 앱의 WAR에서 WEB-INF/ 디렉터리에 위치합니다. web.xml은 웹 애플리케이션의 서블릿 표준에 포함됩니다.

web.xml 표준에 대한 자세한 내용은 Metawerx web.xml 참조 위키서블릿 사양을 참조하세요.

배포 설명자

웹 애플리케이션의 배포 설명자는 애플리케이션의 클래스, 리소스, 구성 및 웹 서버가 이를 사용해서 웹 요청을 처리하는 방법을 기술합니다. 웹 서버는 애플리케이션에 대한 요청이 수신되면 배포 설명자를 사용하여 요청의 URL을 해당 요청을 처리해야 하는 코드에 매핑합니다.

배포 설명자는 이름이 web.xml인 파일입니다. 이 파일은 앱의 WAR에서 WEB-INF/ 디렉터리에 위치하며, 루트 요소가 <web-app>인 XML 파일입니다.

다음의 간단한 web.xml 예시에서는 모든 URL 경로(/*)를 서블릿 클래스 mysite.server.ComingSoonServlet에 매핑합니다.

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
         http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
    <servlet>
        <servlet-name>comingsoon</servlet-name>
        <servlet-class>mysite.server.ComingSoonServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>comingsoon</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

서블릿 및 URL 경로

web.xml은 URL 경로와 해당 경로의 요청을 처리하는 서블릿 사이의 매핑을 정의합니다. 웹 서버는 이 구성을 사용하여 특정한 요청을 처리할 서블릿을 식별하고 요청 메서드에 해당하는 클래스 메서드를 호출합니다. 예를 들어 HTTP GET 요청에는 doGet() 메서드를 사용합니다.

URL을 서블릿에 매핑하려면 <servlet> 요소로 서블릿을 선언한 후 <servlet-mapping> 요소로 URL 경로에서 서블릿 선언으로 이어지는 매핑을 정의합니다.

서블릿을 선언하는 <servlet> 요소에는 파일의 다른 요소에서 서블릿을 참조하는 데 사용할 이름, 서블릿에 사용할 클래스, 초기화 매개변수가 포함됩니다. 동일한 클래스에 서로 다른 초기화 매개변수를 사용하여 여러 서블릿을 선언할 수 있습니다. 각 서블릿의 이름은 배포 설명자 내에서 고유해야 합니다.

    <servlet>
        <servlet-name>redteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>red</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#CC0000</param-value>
        </init-param>
    </servlet>

    <servlet>
        <servlet-name>blueteam</servlet-name>
        <servlet-class>mysite.server.TeamServlet</servlet-class>
        <init-param>
            <param-name>teamColor</param-name>
            <param-value>blue</param-value>
        </init-param>
        <init-param>
            <param-name>bgColor</param-name>
            <param-value>#0000CC</param-value>
        </init-param>
    </servlet>

<servlet-mapping> 요소는 URL 패턴 및 URL이 해당 패턴과 일치하는 요청에 사용할 선언된 서블릿의 이름을 지정합니다. URL 패턴의 시작 또는 끝 부분에 별표(*)를 사용하여 0개 이상의 모든 문자를 나타낼 수 있습니다. 표준에서는 문자열 중간의 와일드 카드를 지원하지 않으며, 패턴 하나에 여러 와일드 카드를 허용하지 않습니다. 패턴은 도메인 이름 다음에 오는 슬래시(/)부터 URL의 전체 경로와 일치하며, 슬래시 자체도 여기에 포함됩니다. URL 경로는 마침표(.)로 시작될 수 없습니다.

    <servlet-mapping>
        <servlet-name>redteam</servlet-name>
        <url-pattern>/red/*</url-pattern>
    </servlet-mapping>

    <servlet-mapping>
        <servlet-name>blueteam</servlet-name>
        <url-pattern>/blue/*</url-pattern>
    </servlet-mapping>

이 예시에서 URL http://www.example.com/blue/teamProfile에 대한 요청을 TeamServlet 클래스가 처리하며 teamColor 매개변수는 blue, bgColor 매개변수는 #0000CC입니다. 서블릿은 ServletRequest 객체의 getPathInfo() 메서드를 사용하여 와일드 카드와 일치하는 URL 경로의 일부를 가져올 수 있습니다.

서블릿에서 초기화 매개변수에 액세스하려면 자신의 getServletConfig() 메서드를 사용하여 서블릿 구성을 가져온 후 구성 객체에 대해 getInitParameter() 메서드를 호출하면서 매개변수 이름을 인수로 사용합니다.

String teamColor = getServletConfig().getInitParameter("teamColor");

JSP

앱에서 JSP(자바 서버 페이지)를 사용하여 웹페이지를 구현할 수 있습니다. JSP는 HTML 등의 정적 콘텐츠와 자바 코드를 함께 사용하여 정의된 서블릿입니다.

App Engine은 JSP 자동 컴파일 및 URL 매핑을 지원합니다. 애플리케이션의 WAR(WEB-INF/ 외부)에서 파일 이름이 .jsp로 끝나는 JSP 파일은 자동으로 서블릿 클래스로 컴파일되며, WAR 루트를 기준으로 JSP 파일 경로에 해당하는 URL 경로에 매핑됩니다. 예를 들어 WAR의 register/ 하위 디렉터리에 이름이 start.jsp인 JSP 파일이 앱에 포함된 경우 App Engine이 이를 컴파일하여 URL 경로 /register/start.jsp로 매핑합니다.

JSP가 URL에 매핑되는 방식을 더 세밀하게 제어하려면 배포 설명자의 <servlet> 요소에 매핑을 선언하여 명시적으로 지정할 수 있습니다. <servlet-class> 요소 대신 WAR 루트의 JSP 파일에 대한 경로로 <jsp-file> 요소를 지정합니다. JSP의 <servlet> 요소는 초기화 매개변수를 포함할 수 있습니다.

    <servlet>
        <servlet-name>register</servlet-name>
        <jsp-file>/register/start.jsp</jsp-file>
    </servlet>

    <servlet-mapping>
        <servlet-name>register</servlet-name>
        <url-pattern>/register/*</url-pattern>
    </servlet-mapping>

<taglib> 요소로 JSP 태그 라이브러리를 설치할 수 있습니다. 태그 라이브러리에는 JSP TLD(태그 라이브러리 설명자) 파일의 경로(<taglib-location>) 및 JSP에서 로드할 라이브러리를 선택하는 데 사용하는 URI(<taglib-uri>)가 포함됩니다. App Engine은 JSTL(자바 서버 페이지 표준 태그 라이브러리)은 App Engine에서 제공하므로 직접 설치할 필요가 없습니다.

    <taglib>
        <taglib-uri>/escape</taglib-uri>
        <taglib-location>/WEB-INF/escape-tags.tld</taglib-location>
    </taglib>

보안 및 인증

App Engine 애플리케이션은 사용자 인증에 Google 계정을 사용할 수 있습니다. 앱은 Google Accounts API로 사용자의 로그인 여부를 감지하고, 현재 로그인한 사용자의 이메일 주소를 가져오고, 로그인 및 로그아웃 URL을 생성할 수 있습니다. 또한 배포 설명자를 사용하여 Google 계정을 기준으로 URL 경로에 대한 액세스 제한을 지정할 수 있습니다.

<security-constraint> 요소는 패턴과 일치하는 URL에 대한 보안 제약조건을 정의합니다. 로그인하지 않은 사용자가 액세스하는 URL의 경로에 보안 제약조건이 있는 경우 App Engine은 사용자를 Google 계정 로그인 페이지로 리디렉션합니다. 사용자가 로그인에 성공하거나 새 계정을 등록하면 Google 계정에서 사용자를 애플리케이션 URL로 다시 리디렉션합니다. 앱에서 이외에 별도의 조치를 취하지 않아도 로그인한 사용자만 URL에 액세스할 수 있습니다.

보안 제약조건에는 어떠한 Google 계정 사용자가 경로에 액세스할 수 있는지를 지정하는 승인 제약조건이 포함됩니다. 승인 제약조건에서 사용자 역할을 *로 지정하면 Google 계정으로 로그인한 모든 사용자가 URL에 액세스할 수 있습니다. 제약조건에서 사용자 역할을 admin으로 지정하면 등록된 애플리케이션 개발자만 URL에 액세스할 수 있습니다. admin 역할을 사용하면 사이트의 관리자 전용 섹션을 쉽게 구축할 수 있습니다.

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>profile</web-resource-name>
            <url-pattern>/profile/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>*</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>admin</web-resource-name>
            <url-pattern>/admin/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>admin</role-name>
        </auth-constraint>
    </security-constraint>

App Engine은 배포 설명자에서 커스텀 보안 역할(<security-role>) 또는 대체 인증 메커니즘(<login-config>)을 지원하지 않습니다.

보안 제약조건은 정적 파일과 서블릿에 모두 적용됩니다.

보안 URL

Google App Engine은 REGION_ID.r.appspot.com 도메인을 사용하는 URL에 HTTPS를 통한 보안 연결을 지원합니다. 요청에서 HTTPS를 사용하여 URL에 액세스하며 web.xml 파일에 해당 URL이 HTTPS를 사용하도록 구성된 경우, 요청 데이터와 응답 데이터가 모두 발신자에 의해 암호화된 후에 전송되고 수신자는 데이터를 수신한 후 복호화합니다. 보안 연결은 연락처 정보, 비밀번호, 개인 메시지 등의 고객 데이터를 보호하는 데 유용합니다.

URL에 HTTPS를 사용하도록 선언하려면 보안 및 인증의 설명에 따라 배포 설명자에 보안 제약조건을 설정하면서 <user-data-constraint><transport-guarantee>CONFIDENTIAL로 지정합니다. 예를 들면 다음과 같습니다.

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>profile</web-resource-name>
            <url-pattern>/profile/*</url-pattern>
        </web-resource-collection>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

전송 보장이 CONFIDENTIAL인 URL에 비보안 HTTP를 사용하는 요청은 자동으로 HTTPS를 사용하여 같은 URL로 리디렉션됩니다.

JSP, 정적 파일을 포함하여 모든 URL에 CONFIDENTIAL 전송 보장을 사용할 수 있습니다.

개발용 웹 서버는 HTTPS 연결을 지원하지 않습니다. 전송 보장이 무시되므로 개발용 웹 서버에 대한 일반 HTTP 연결을 사용하여 HTTPS용으로 의도된 경로를 테스트할 수 있습니다.

https://1.latest.your_app_id.REGION_ID.r.appspot.com/과 같이 버전이 지정된 appspot.com URL을 사용하여 앱의 HTTPS 핸들러를 테스트하면 브라우저에서 HTTPS 인증서가 해당 특정 도메인 경로에 대해 서명되지 않았다는 경고가 표시됩니다. 인증서를 해당 도메인용으로 수락하면 페이지가 정상적으로 로드됩니다. 사용자가 https://your_app_id.REGION_ID.r.appspot.com/에 액세스할 때는 인증서 경고가 표시되지 않습니다.

버전이 지정된 appspot.com URL 중에서 이러한 문제가 나타나지 않도록 설계된 대체 형식을 사용할 수도 있습니다. 하위 도메인 구성요소를 구분하는 마침표를 '-dot-' 문자열로 바꾸면 됩니다. 예를 들어 앞의 예시에서 인증서 경고 없이 액세스하려면 https://VERSION_ID-dot-default-dot-PROJECT_ID.REGION_ID.r.appspot.com을 사용합니다.

Google 계정 로그인 및 로그아웃은 애플리케이션의 URL이 구성된 방식과 무관하게 항상 보안 연결을 사용하여 수행됩니다.

위에서 설명한 것처럼 보안 제약조건은 정적 파일과 서블릿에 모두 적용됩니다. 전송 보장도 여기에 포함됩니다.

참고: HTTPS 프로토콜을 사용하여 앱에 요청을 보내는 것이 좋습니다. Google은 appspot.com에서 호스팅되는 이중 와일드 카드 도메인에 SSL 인증서를 발급하지 않습니다. 따라서 HTTPS를 사용하는 경우 아래의 예와 같이 '.' 대신 '-dot-' 문자열을 사용하여 하위 도메인을 구분해야 합니다. 사용자의 커스텀 도메인 또는 HTTP 주소에는 간단히 '.'를 사용할 수 있습니다.

시작 파일 목록

사이트의 URL이 WAR에 포함된 정적 파일 또는 JSP에 대한 경로를 나타내는 경우 디렉터리 경로에 유용한 기능을 부여하는 것이 좋습니다. 계정 비밀번호를 확인하고자 URL 경로 /help/accounts/password.jsp를 방문하는 사용자는 계정 시스템에 대한 정보를 알려주는 페이지를 찾기 위해 /help/accounts/를 방문하려고 할 수 있습니다. 배포 설명자는 아직 서블릿에 명시적으로 매핑되지 않은 WAR 하위 디렉터리를 나타내는 경로에 사용자가 액세스할 때 서버에서 시도할 파일 이름 목록을 지정할 수 있습니다. 서블릿 표준에서는 이를 '시작 파일 목록'이라고 부릅니다.

예를 들어 사용자가 URL 경로 /help/accounts/에 액세스하면 배포 설명자에 있는 다음 <welcome-file-list> 요소는 서버가 URL이 존재하지 않음을 보고하기 전에 help/accounts/index.jsphelp/accounts/index.html이 있는지 확인하도록 지시합니다.

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
        <welcome-file>index.html</welcome-file>
    </welcome-file-list>

필터

필터는 서블릿과 같이 요청에 대해 작동하는 클래스이지만 다른 필터 또는 서블릿이 요청을 계속 처리하도록 허용할 수 있습니다. 필터는 로깅, 특화된 인증 검사, 서블릿 호출 전 요청 또는 응답 객체 주석 처리와 같은 보조 태스크를 수행할 수 있습니다. 필터를 사용하면 배포 설명자에서 요청 처리 작업을 구성할 수 있습니다.

필터 클래스는 doFilter() 메서드를 포함한 javax.servlet.Filter 인터페이스를 구현합니다. 다음은 메시지를 로깅하고 배포 설명자에 기술된 대로 다른 필터 또는 서블릿을 포함할 수 있는 체인을 따라 제어를 전달하는 간단한 필터 구현입니다.

package mysite.server;

import java.io.IOException;
import java.util.logging.Logger;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class LogFilterImpl implements Filter {

    private FilterConfig filterConfig;
    private static final Logger log = Logger.getLogger(LogFilterImpl.class.getName());

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
        throws IOException, ServletException {
        log.warning("Log filter processed a " + getFilterConfig().getInitParameter("logType")
            + " request");

        filterChain.doFilter(request, response);
    }

    public FilterConfig getFilterConfig() {
        return filterConfig;
    }

    public void init(FilterConfig filterConfig) {
        this.filterConfig = filterConfig;
    }

    public void destroy() {}

}

배포 설명자에 필터를 구성하는 방법은 서블릿과 비슷합니다. <filter> 요소로 필터를 선언한 후 <filter-mapping> 요소로 URL 패턴에 매핑하면 됩니다. 필터를 다른 서블릿에 직접 매핑할 수도 있습니다.

<filter> 요소에는 <filter-name>, <filter-class>, 선택사항 <init-param> 요소가 포함됩니다.

    <filter>
        <filter-name>logSpecial</filter-name>
        <filter-class>mysite.server.LogFilterImpl</filter-class>
        <init-param>
            <param-name>logType</param-name>
            <param-value>special</param-value>
        </init-param>
    </filter>

<filter-mapping> 요소에는 선언된 필터의 이름과 일치하는 <filter-name>이 포함되고, URL에 필터를 적용하는 <url-pattern> 요소 또는 선언된 서블릿의 이름과 일치하며 해당 서블릿이 호출될 때마다 필터를 적용하는 <servlet-name> 요소 중 하나가 포함됩니다.

    <!-- Log for all URLs ending in ".special" -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <url-pattern>*.special</url-pattern>
    </filter-mapping>

    <!-- Log for all URLs that use the "comingsoon" servlet -->
    <filter-mapping>
        <filter-name>logSpecial</filter-name>
        <servlet-name>comingsoon</servlet-name>
    </filter-mapping>

오류 핸들러

배포 설명자를 사용하여 오류가 발생할 때 서버가 사용자에게 전송하는 내용을 맞춤설정할 수 있습니다. 서버는 특정 HTTP 상태 코드를 전송하려고 할 때 또는 서블릿에서 특정 자바 예외가 발생할 때 대체 페이지 위치를 표시할 수 있습니다.

<error-page> 요소는 HTTP 오류 코드 값이 있는 <error-code> 요소(예: 500) 또는 예상되는 예외의 클래스 이름이 있는 <exception-type> 요소(예: java.io.IOException)를 포함합니다. 또한 오류가 발생할 때 표시할 리소스의 URL 경로를 갖는 <location> 요소가 포함됩니다.

    <error-page>
        <error-code>500</error-code>
        <location>/errors/servererror.jsp</location>
    </error-page>

지원되지 않는 web.xml 기능

다음 web.xml 기능은 App Engine에서 지원되지 않습니다.

  • App Engine은 서블릿 선언에 <load-on-startup> 요소를 지원합니다. 그러나 실제로 로드되는 시점은 웹 서버 인스턴스가 첫 번째 요청을 처리할 때이며, 그 이전에는 로드되지 않습니다.
  • 배포 설명자의 일부 요소는 IDE에서 사람이 읽을 수 있는 표시 이름, 설명, 아이콘을 사용할 수 있습니다. App Engine은 이러한 항목을 사용하지 않고 무시합니다.
  • App Engine은 JNDI 환경 변수(<env-entry>)를 지원하지 않습니다.
  • App Engine은 EJB 리소스(<resource-ref>)를 지원하지 않습니다.
  • 서블릿, 서블릿 컨텍스트 또는 필터 삭제 알림은 지원되지 않습니다.
  • <distributable> 요소는 무시됩니다.
  • <run-at>을 사용한 서블릿 예약은 지원되지 않습니다.