

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# OpsWorks 스택 사용자 지정
<a name="customizing"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

OpsWorks Stacks 내장 계층은 다양한 용도로 충분한 표준 기능을 제공합니다. 하지만 다음과 같은 상황을 마주할 수 있습니다.
+ 내장 계층의 표준 구성이 적당하지만 이상적이지는 않아 특정 요구 사항에 맞게 최적화하기를 원할 경우

  예를 들어 최대 worker 프로세스 수 또는 `keepalivetimeout` 값과 같은 설정에 자체 값을 지정하여 Static Web Server 계층의 Nginx 서버 구성을 조정할 수 있습니다.
+ 내장 계층의 기능이 훌륭하지만 추가 패키지를 설치하거나 몇몇 사용자 지정 설치 스크립트를 실행하여 확장하기를 원할 경우

  예를 들어 Redis 서버도 설치하여 PHP 앱 서버 계층을 확장할 수 있습니다.
+ 내장 계층으로 처리할 수 없는 요구 사항이 있는 경우

  예를 들어 OpsWorks Stacks에는 일부 인기 있는 데이터베이스 서버에 대한 기본 제공 계층이 포함되어 있지 않습니다. 계층의 인스턴스에 이러한 서버를 설치하는 사용자 지정 계층을 생성할 수 있습니다.
+ 사용자 지정 계층만 지원하는 Windows 스택을 실행하는 경우

OpsWorks Stacks는 특정 요구 사항에 맞게 계층을 사용자 지정하는 다양한 방법을 제공합니다. 다음 예제는 복잡성 및 파워가 증가하는 순서로 나열되어 있습니다.

**참고**  
일부 접근 방식은 Linux 스택에서만 작동합니다. 자세한 정보는 이하의 주제를 참조하세요.
+ 사용자 지정 JSON을 사용하여 기본 OpsWorks Stacks 설정을 재정의합니다.
+ 기본 스택 설정을 재정의하는 속성 파일을 사용하여 사용자 지정 Chef OpsWorks 쿡북을 구현합니다.
+ 기본 Stacks 템플릿을 재정의하거나 확장하는 템플릿을 사용하여 사용자 지정 Chef OpsWorks 쿡북을 구현합니다.
+ shell 스크립트를 실행하는 간단한 레시피를 사용하여 사용자 지정 Chef 쿡북을 구현합니다.
+ 디렉터리 구성, 패키지 설치, 구성 파일 생성, 앱 배포 등의 작업을 수행하는 레시피를 사용하여 사용자 지정 Chef 쿡북을 구현합니다.

스택의 Chef 버전 및 운영 체제에 따라 레시피를 재정의할 수도 있습니다.
+ Chef 0.9 및 11.4 스택에서는 동일한 쿡북 및 레시피 이름의 사용자 지정 레시피를 구현하여 내장 레시피를 재정의할 수 없습니다.

  각 수명 주기 이벤트에 대해 OpsWorks Stacks는 항상 기본 제공 레시피를 먼저 실행한 다음 사용자 지정 레시피를 실행합니다. 이러한 Chef 버전은 동일한 쿡북 및 레시피 이름을 두 번 실행하지 않으므로 내장 레시피가 우선 순위를 가져 사용자 지정 레시피를 실행되지 않습니다.
+ Chef 11.10 스택에서는 내장 레시피를 재정의할 수 있습니다.

  자세한 내용은 [쿡북 설치 및 우선 순위](workingcookbook-chef11-10.md#workingcookbook-chef11-10-override) 섹션을 참조하세요.
+ Windows 스택에서는 내장 레시피를 재정의할 수 없습니다.

   OpsWorks Stacks가 Windows 스택용 Chef 실행을 처리하는 방식에서는 내장 레시피를 재정의할 수 없습니다.

**참고**  
많은 기법이 사용자 지정 쿡북을 사용하기 때문에 쿡북 구현에 익숙하지 않은 [쿡북과 레시피](workingcookbook.md) 경우 먼저를 읽어야 합니다. [쿡북 기본 사항](cookbooks-101-basics.md)에서는 사용자 지정 쿡북 구현에 대한 자세한 자습서를 제공하고 Stacks 인스턴스용 OpsWorks 쿡북을 구현하는 방법에 대한 몇 가지 세부 정보를 [OpsWorks 스택용 쿡북 구현](cookbooks-101-opsworks.md) 다룹니다.

**Topics**
+ [속성을 재정의하여 OpsWorks 스택 구성 사용자 지정](workingcookbook-attributes.md)
+ [사용자 지정 템플릿을 사용하여 OpsWorks 스택 구성 파일 확장](workingcookbook-template-override.md)
+ [계층 확장](workingcookbook-extend.md)
+ [사용자 지정 Tomcat 서버 계층 생성](create-custom.md)
+ [스택 구성 및 배포 속성](workingcookbook-json.md)

# 속성을 재정의하여 OpsWorks 스택 구성 사용자 지정
<a name="workingcookbook-attributes"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

**참고**  
Windows 스택 및 Chef 12 Linux 스택의 경우 OpsWorks Stacks는 기본 제공 레시피 및 사용자 지정 레시피에 별도의 Chef 실행을 사용합니다. 즉, 이 섹션에 설명된 기법을 사용해서는 Windows 스택과 Chef 12 Linux 스택의 내장 속성을 재정의할 수 없습니다.

레시피와 템플릿은 계층 구성 또는 애플리케이션 서버 설정 같은 인스턴스 또는 스택별 정보를 다양한 Chef 속성에 의존합니다. 이들 속성에는 몇 가지 소스가 있습니다.
+ **사용자 지정 JSON** - 필요한 경우, 스택을 생성, 업데이트 또는 복제하거나 앱을 배포할 때 사용자 지정 JSON 속성을 지정할 수 있습니다.
+ **스택 구성 속성** -OpsWorks 스택은 콘솔 설정을 통해 지정하는 정보를 포함하여 스택 구성 정보를 보유하도록 이러한 속성을 정의합니다.
+ **배포 속성** — AWS OpsWorks는 Deploy 이벤트의 배포 관련 속성을 정의합니다.
+ **쿡북 속성** - 내장 쿡북과 사용자 지정 쿡북은 일반적으로 애플리케이션 서버 구성 설정 등 쿡북별 값을 나타내는 속성이 포함된 [속성 파일](workingcookbook-installingcustom-components-attributes.md)을 포함하고 있습니다.
+ **Chef** - Chef의 [Ohai 도구](http://docs.chef.io/resource_ohai.html)는 CPU 유형과 설치된 메모리 같은 다양한 시스템 구성 설정을 나타내는 속성을 정의합니다.

스택 구성 및 배포 속성과 내장 쿡북 속성의 완전한 목록은 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 [내장 쿡북 속성](attributes-recipes.md)를 참조하세요. Ohai 속성에 대한 자세한 정보는 [Ohai](https://docs.chef.io/ohai.html)를 참조하세요.

배포 또는 구성과 같은 [수명 주기 이벤트](workingcookbook-events.md)가 발생하거나 `execute_recipes` 또는 `update_packages`같은 [스택 명령](workingstacks-commands.md)을 실행하면 OpsWorks Stacks는 다음을 수행합니다. 
+ 해당 명령을 각각의 해당 인스턴스의 에이전트에 전송합니다.

  이 에이전트는 적절한 레시피를 실행합니다. 예를 들어 Deploy 이벤트의 경우, 에이전트는 내장 Deploy 레시피를 실행한 다음 사용자 지정 Deploy 레시피를 실행합니다.
+ 사용자 지정 JSON 및 배포 속성을 스택 구성 속성에 병합하고 인스턴스에 설치합니다.

사용자 지정 JSON의 속성, 스택 구성 및 배포 속성, 쿡북 속성 및 Ohai 속성은 레시피에 속성 값을 제공하는 *노드 객체*에 병합됩니다. 인스턴스는 사용자 지정 JSON을 비롯한 스택 구성 속성에 관한 한 기본적으로 상태 비저장입니다. 배포 또는 스택 명령을 실행하면 연결된 레시피는 명령과 함께 다운로드된 스택 구성 속성을 사용합니다.

**Topics**
+ [속성 우선 순위](workingcookbook-attributes-precedence.md)
+ [사용자 지정 JSON을 사용한 속성 재정의](workingcookbook-json-override.md)
+ [사용자 지정 OpsWorks 쿡북 속성을 사용하여 스택 속성 재정의](workingcookbook-cookbook-attributes.md)

# 속성 우선 순위
<a name="workingcookbook-attributes-precedence"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

속성이 고유하게 정의되는 경우, Chef는 해당 속성을 노드 객체에 단순히 통합합니다. 하지만 모든 속성 소스는 어떤 속성도 정의할 수 있으므로 동일한 속성이 값이 각기 다른 여러 정의를 가질 수 있습니다. 예를 들어 내장 `apache2` 쿡북은 `node[:apache][:keepalive]`를 정의하지만 사용자 지정 JSON 또는 사용자 지정 쿡북에서도 해당 속성을 정의할 수 있습니다. 한 속성에 여러 정의가 있는 경우, 이 정의들은 뒤에 설명하는 순서대로 평가되며, 노드 객체는 우선 순위가 가장 높은 정의를 수신합니다.

속성은 다음과 같이 정의됩니다.

```
node.type[:attribute][:sub_attribute][:...]=value
```

속성에 여러 정의가 있는 경우 유형에 따라 우선 순위가 있는 정의가 결정되고 해당 정의가 노드 객체에 통합됩니다. OpsWorks Stacks는 다음 속성 유형을 사용합니다.
+ **default** - 이것은 가장 일반적인 유형이며, 기본적으로 "속성이 아직 정의되지 않았다면 이 값을 사용하라"는 뜻입니다. 속성의 모든 정의가 `default` 유형인 경우, 평가 순서에서 첫 번째 정의가 우선하며 후속 값들은 무시됩니다. Stacks는 모든 스택 구성 및 배포 속성 OpsWorks 정의를 `default` 유형으로 설정합니다.
+ **normal** - 이 유형의 속성은 모든 `default` 속성 또는 평가 순서에서 앞서 정의된 `normal` 속성을 재정의합니다. 예를 들어 첫 번째 속성이 내장 쿡북의 속성이고 `default` 유형을 가지고 있으며 두 번째는 사용자가 정의한 속성으로 `normal` 유형을 가지고 있다면 두 번째 속성이 우선합니다.
+ **set** - 이전의 쿡북에서 볼 수 있는 사용되지 않는 유형입니다. 이 유형은 같은 우선 순위를 갖는 `normal`로 대체되었습니다.

Chef는 다른 모든 속성 정의에 우선하는 `automatic` 유형을 비롯한 몇 가지 추가 속성 유형을 지원합니다. Chef의 Ohai 도구에 의해 생성되는 속성 정의는 모두 `automatic` 유형이므로 사실상 읽기 전용입니다. 이는 일반적으로 문제가 되지 않습니다. 재정의할 이유가 없고 OpsWorks Stacks의 속성과 별개이기 때문입니다. 다만 사용자 지정 쿡북 속성의 이름을 지정할 때는 Ohai 속성과 구별되도록 주의해야 합니다. 자세한 정보는 [속성 정보](http://docs.chef.io/attributes.html)를 참조하세요.

**참고**  
Ohai 도구는 명령줄에서 실행할 수 있는 실행 파일입니다. 인스턴스의 Ohai 속성을 나열하려면 인스턴스에 로그인하고 터미널 창에서 `ohai`를 실행합니다. 매우 긴 출력이 생성되므로 유의하세요.

다음은 다양한 속성 정의를 노드 객체에 통합하는 단계입니다.

1. 모든 사용자 지정 스택 구성 속성을 스택 구성 및 배포 속성에 병합합니다.

   스택이나 특정 배포에 대해 사용자 지정 JSON 속성을 설정할 수 있습니다. 사용자 지정 JSON 속성은 평가 순서에서 첫 번째이며 사실상 `normal` 유형입니다. 사용자 지정 JSON에서 하나 이상의 스택 구성 속성도 정의되는 경우, 사용자 지정 JSON 값이 우선합니다. 그렇지 않으면 OpsWorks Stacks는 단순히 사용자 지정 JSON 속성을 스택 구성에 통합합니다.

1. 모든 배포 사용자 지정 JSON 속성을 스택 구성 및 배포 속성에 병합합니다.

   배포 사용자 지정 JSON 속성도 사실상 `normal` 유형이므로 내장 및 사용자 지정 스택 구성 JSON과 내장 배포 JSON보다 우선합니다.

1. 스택 구성 및 배포 속성을 인스턴스의 노드 객체에 병합합니다.

1. 인스턴스의 내장 쿡북 속성을 노드 객체에 병합합니다.

   내장 쿡북 속성은 모두 `default` 유형입니다. 일반적으로 사용자 지정 JSON으로 정의했기 때문에 스택 구성 및 배포 속성에도 하나 이상의 내장 쿡북 속성이 정의된 경우 스택 구성 정의가 내장 쿡북 정의보다 우선합니다. 다른 모든 내장 쿡북 속성은 단순히 노드 객체에 통합됩니다.

1. 인스턴스의 사용자 지정 쿡북 속성을 노드 객체에 병합합니다.

   사용자 지정 쿡북 속성은 일반적으로 `normal` 또는 `default` 유형입니다. 고유한 속성은 노드 객체에 통합됩니다. 1\$13단계에서 사용자 지정 쿡북 속성도 정의한 경우(일반적으로 사용자 지정 JSON으로 정의했기 때문에) 우선 순위는 사용자 지정 쿡북 속성 유형에 따라 달라집니다.
   + 1-3단계에서 정의된 속성은 사용자 지정 쿡북 `default` 속성보다 우선합니다.
   + 사용자 지정 쿡북 `normal` 속성은 1-3단계의 정의보다 우선합니다.

**중요**  
사용자 지정 쿡북 `default` 속성을 사용하여 스택 구성 또는 내장 쿡북 속성을 재정의하지 마십시오. 사용자 지정 쿡북 속성은 마지막으로 평가되기 때문에 `default` 속성은 우선 순위가 가장 낮으며 아무것도 재정의할 수 없습니다.

# 사용자 지정 JSON을 사용한 속성 재정의
<a name="workingcookbook-json-override"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

**참고**  
 OpsWorks Stacks는 Windows 스택의 Chef 실행을 Linux 스택의 경우와 다르게 처리하기 때문에 Windows 스택의 경우이 섹션에서 설명하는 기술을 사용할 수 없습니다.

Stacks 속성을 재정의하는 가장 간단한 방법은 기본 제공 및 사용자 지정 OpsWorks 쿡북 속성뿐만 아니라 스택 구성 및 배포 속성보다 우선하는 사용자 지정 JSON으로 정의하는 것입니다`default`. 자세한 내용은 [속성 우선 순위](workingcookbook-attributes-precedence.md) 단원을 참조하십시오.

**중요**  
스택 구성 및 배포 속성을 재정의할 때는 주의해야 합니다. 예를 들어 `opsworks` 네임스페이스에서 속성을 재정의하면 내장 속성을 방해할 수 있습니다. 자세한 내용은 [스택 구성 및 배포 속성](workingcookbook-json.md) 섹션을 참조하세요.

사용자 지정 JSON을 사용하여 고유한 속성을 정의할 수도 있습니다(일반적으로 데이터를 사용자 지정 레시피에 전달하기 위해). 속성은 노드 객체에 통합되며, 레시피는 표준 Chef 노드 구문을 사용하여 속성 단원을 참조할 수 있습니다.

## 사용자 지정 JSON 지정 방법
<a name="workingcookbook-json-override-specify"></a>

사용자 지정 JSON을 사용하여 속성 값을 재정의하려면 먼저 속성의 정규화된 속성 이름을 확인해야 합니다. 그런 다음 재정의하려는 속성을 포함한 JSON 객체를 생성하고 선호하는 값으로 설정합니다. 편의상 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 [내장 쿡북 속성](attributes-recipes.md) 문서에는 일반적으로 사용되는 스택 구성, 배포 및 내장 쿡북 속성과 그 정규화된 이름이 나와 있습니다.

객체의 상위-하위 관계는 적절한 정규화된 Chef 노드와 일치해야 합니다. 예를 들어 다음과 같은 Apache 속성을 변경하려 한다고 가정하겠습니다.
+ 노드가 `node[:apache][:keepalivetimeout]`이고 `3` 기본값을 가진 [`keepalivetimeout`](attributes-recipes-apache.md#attributes-recipes-apache-keep-timeout) 속성입니다.
+ 노드가 `node[:apache][:logrotate][:schedule]`이고 `"daily"` 기본값을 가진 `logrotate` [`schedule`](attributes-recipes-apache.md#attributes-recipes-apache-log-schedule) 속성입니다.

이 속성들을 재정의하고 값을 각각 `5`와 `"weekly"`로 설정하려면 다음 사용자 지정 JSON을 사용합니다.

```
{
  "apache" : {
    "keepalivetimeout" : 5,
    "logrotate" : {
       "schedule" : "weekly"
    }
  }
}
```

## 사용자 지정 JSON을 지정할 시기
<a name="workingcookbook-json-override-when"></a>

다음 작업에 사용자 지정 JSON 구조를 지정할 수 있습니다.
+ [새 스택 생성](workingstacks-creating.md)
+ [스택 업데이트](workingstacks-edit.md)
+ [스택 명령 실행](workingstacks-edit.md)
+ [스택 복제](workingstacks-cloning.md)
+ [앱 배포](workingapps-deploying.md)

각 작업에 대해 OpsWorks Stacks는 사용자 지정 JSON 속성을 스택 구성 및 배포 속성과 병합하고 인스턴스로 전송하여 노드 객체에 병합합니다. 다만 다음을 참고하세요.
+ 스택을 생성, 복제 또는 업데이트할 때 사용자 지정 JSON을 지정하는 경우, 속성은 모든 후속 수명 주기 이벤트 및 스택 명령의 스택 구성 및 배포 속성에 병합됩니다.
+ 배포를 위해 사용자 지정 JSON을 지정하는 경우, 속성은 해당 이벤트의 스택 구성 및 배포 속성에만 병합됩니다.

  후속 배포에 이러한 사용자 지정 속성을 사용하려면 사용자 지정 JSON을 다시 명시적으로 지정해야 합니다.

속성은 레시피에 의해 사용될 때 인스턴스에만 영향을 미친다는 점을 명심해야 합니다. 속성 값을 재정의해도 해당 속성 단원을 참조하는 후속 레시피가 없다면 변경은 효과가 없습니다. 연결된 레시피가 실행되기 전에 사용자 지정 JSON을 전송하거나 적절한 레시피를 다시 실행해야 합니다.

## 사용자 지정 JSON 모범 사례
<a name="workingcookbook-json-override-best"></a>

사용자 지정 JSON을 사용하여 모든 OpsWorks Stacks 속성을 재정의할 수 있지만 정보를 수동으로 입력하는 것은 다소 번거롭고 어떤 종류의 소스 제어도 하지 않습니다. 사용자 지정 JSON은 다음과 같은 용도로 가장 잘 활용할 수 있습니다.
+ 소수의 속성만 재정의하고 그 밖에는 사용자 지정 쿡북을 사용할 필요가 없을 때.

  사용자 지정 JSON을 사용하면 단지 2가지 속성을 재정의하기 위해 쿡북 리포지토리를 설정하고 유지 관리하는 부담을 피할 수 있습니다.
+ 암호 또는 인증 키 같은 중요한 값.

  쿡북 속성은 리포지토리에 저장되므로 중요한 정보가 침해될 위험이 있습니다. 그 대신 더미 값으로 기본값을 정의하고 사용자 지정 JSON을 사용하여 실제 값을 설정하세요.
+ 값은 다양할 것으로 예상됩니다.

  예를 들어 권장되는 관행은 프로덕션 스택을 별도의 개발 및 스테이징 스택으로 지원하는 것입니다. 이 스택들이 지불을 받는 애플리케이션을 지원한다고 가정해 보십시오. 사용자 지정 JSON을 사용하여 지불 엔드포인트를 지정하는 경우, 스테이징 스택에 테스트 URL을 지정할 수 있습니다. 업데이트된 스택을 프로덕션 스택으로 마이그레이션할 준비가 되면 같은 쿡북을 사용하고 사용자 지정 JSON을 사용하여 지불 엔드포인트를 프로덕션 URL로 설정할 수 있습니다.
+ 특정 스택 또는 배포 명령에 고유한 값.

# 사용자 지정 OpsWorks 쿡북 속성을 사용하여 스택 속성 재정의
<a name="workingcookbook-cookbook-attributes"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

**참고**  
Windows 스택의 경우 OpsWorks Stacks는 기본 제공 레시피와 사용자 지정 레시피에 별도의 Chef 실행을 사용합니다. 즉, 이 섹션에 설명된 기법을 사용해서는 Windows 스택의 내장 속성을 재정의할 수 없습니다.

사용자 지정 JSON은 Stacks 스택 구성 및 내장 OpsWorks 쿡북 속성을 재정의하는 편리한 방법이지만 몇 가지 제한이 있습니다. 특히 사용 시마다 사용자 지정 JSON을 수동으로 입력해야 하므로 정의를 관리할 확실한 방법이 없습니다. 더 좋은 방법은 사용자 지정 쿡북 속성 파일을 사용하여 내장 속성을 재정의하는 것입니다. 이렇게 하면 소스 제어 아래에 정의를 배치할 수 있습니다.

사용자 지정 속성 파일을 사용하여 OpsWorks Stacks 정의를 재정의하는 절차는 간단합니다.

**Stacks 속성 OpsWorks 정의를 재정의하려면**

1. [쿡북과 레시피](workingcookbook.md) 단원의 설명에 따라 쿡북 리포지토리를 설정합니다.

1. 재정의할 속성이 포함된 내장 쿡북과 같은 이름으로 쿡북을 생성합니다. 예를 들어 Apache 속성을 재정의하려면 쿡북의 이름을 apache2로 지정해야 합니다.

1. 쿡북에 `attributes` 폴더를 추가하고 `customize.rb` 폴더에 파일을 추가합니다.

1. 재정의할 내장 쿡북의 속성별로 이 파일에 속성 정의를 추가하고 원하는 값으로 설정합니다. 속성은 `normal` 유형 이상이어야 하며 해당 OpsWorks Stacks 속성과 노드 이름이 정확히 동일해야 합니다. 노드 이름을 포함한 OpsWorks Stacks 속성의 자세한 목록은 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 섹션을 참조하세요[내장 쿡북 속성](attributes-recipes.md). 속성 및 속성 파일에 대한 자세한 정보는 [속성 파일 정보](http://docs.chef.io/attributes.html)를 참조하세요.
**중요**  
 OpsWorks Stacks 속성을 재정의하려면 속성`normal`이 유형이어야 합니다. `default` 유형에는 우선 순위가 없습니다. 예를 들어, `customize.rb` 파일에 `default[:apache][:keepalivetimeout] = 5` 속성 정의가 있어도 내장된 `apache.rb` 속성 파일의 해당 속성이 먼저 평가되면 그 속성이 우선 적용됩니다. 자세한 내용은 [속성 재정의](workingcookbook-attributes.md) 섹션을 참조하세요.

1. 재정의할 속성이 포함된 각 내장 쿡북에 대해 2 - 4단계를 반복합니다.

1. 스택에 대해 사용자 지정 쿡북을 활성화하고 Stacks가 OpsWorks 쿡북을 스택의 인스턴스에 다운로드하는 데 필요한 정보를 제공합니다. 자세한 내용은 [사용자 지정 쿡북 설치](workingcookbook-installingcustom-enable.md) 단원을 참조하십시오.

**참고**  
이 절차에 대한 완전한 안내는 [내장 속성 재정의](cookbooks-101-opsworks-attributes.md) 단원을 참조하세요.

이제 후속 수명 주기 이벤트, 배포 명령 및 스택 명령에 사용되는 노드 객체에 OpsWorks Stacks 값 대신 속성 정의가 포함됩니다.

예를 들어 `keepalivetimeout`에서 설명한 내장 `logrotate schedule` 및 [사용자 지정 JSON 지정 방법](workingcookbook-json-override.md#workingcookbook-json-override-specify) 설정을 재정의하려면 `apache2`apache 쿡북을 리포지토리에 추가하고 `customize.rb` 파일을 다음 콘텐츠와 함께 쿡북의 `attributes` 폴더에 추가합니다.

```
normal[:apache][:keepalivetimeout] = 5
normal[:apache][:logrotate][:schedule] = 'weekly'
```

**중요**  
연결된 내장 속성 파일의 사본을 수정하여 OpsWorks Stacks 속성을 재정의해서는 안 됩니다. 예를 들어 `apache.rb`를 `apache2/attributes` 폴더에 복사하고 일부 설정을 수정하는 경우, 기본적으로 내장 파일의 모든 속성이 재정의됩니다. 레시피는 사본의 속성 정의를 사용하고 내장 파일은 무시합니다. OpsWorks Stacks가 나중에 내장 속성을 수정하는 경우, 수동으로 사본을 업데이트하지 않는 한 레시피는 변경 사항에 액세스하지 못합니다.  
이런 상황을 피하기 위해 모든 내장 쿡북에는 `customize.rb` 명령을 통해 모든 모듈에 필요한 빈 `include_attribute` 속성이 포함되어 있습니다. `customize.rb` 사본의 속성을 재정의하면 이러한 특정 속성에만 영향을 미칠 수 있습니다. 레시피는 그 밖의 모든 속성 값을 내장 속성 파일에서 가져오며, 재정의하지 않은 속성의 현재 값을 자동으로 가져옵니다.  
이 방법은 쿡북 리포지토리의 속성 수를 적게 유지하도록 도움으로써 유지 관리 부담이 줄어들고 향후 업그레이드 관리가 쉬워집니다.

# 사용자 지정 템플릿을 사용하여 OpsWorks 스택 구성 파일 확장
<a name="workingcookbook-template-override"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

**참고**  
 OpsWorks Stacks는 Windows 스택의 Chef 실행을 Linux 스택의 경우와 다르게 처리하기 때문에 Windows 스택의 경우이 섹션에서 설명하는 기술을 사용할 수 없습니다.

OpsWorks Stacks는 템플릿을 사용하여 일반적으로 많은 설정의 속성에 의존하는 구성 파일과 같은 파일을 생성합니다. 사용자 지정 JSON 또는 사용자 지정 OpsWorks 쿡북 속성을 사용하여 Stacks 정의를 재정의하는 경우 기본 설정이 OpsWorks Stacks 설정 대신 구성 파일에 통합됩니다. 그러나 OpsWorks Stacks는 가능한 모든 구성 설정에 대한 속성을 반드시 지정하지는 않습니다. 일부 설정의 기본값을 수락하고 템플릿에서 직접 다른 설정을 하드코딩합니다. 해당하는 Stacks 속성이 없는 경우 사용자 지정 JSON 또는 사용자 지정 OpsWorks 쿡북 속성을 사용하여 기본 설정을 지정할 수 없습니다.

사용자 지정 템플릿을 생성해 추가 구성 설정을 포함하도록 구성 파일을 확장할 수 있습니다. 그런 다음 필요한 구성 설정이나 그 밖의 콘텐츠를 파일에 추가하고 하드코딩된 설정을 재정의할 수 있습니다. 템플릿에 대한 자세한 정보는 [템플릿](workingcookbook-installingcustom-components-templates.md) 단원을 참조하세요.

**참고**  
opsworks-agent.monitrc.erb를 *제외*한 어떤 내장 템플릿도 재정의할 수 있습니다.

**사용자 지정 템플릿을 생성하려면**

1. 내장 쿡북과 동일한 구조 및 디렉터리 이름으로 쿡북을 생성합니다. 그런 다음 해당 디렉터리에서 사용자 지정하려는 내장 템플릿과 동일한 이름을 가진 템플릿 파일을 만듭니다. 예를 들어 사용자 지정 템플릿을 사용하여 Apache `httpd.conf` 구성 파일을 확장하려는 경우 리포지토리에서 `apache2` 쿡북을 구현해야 하고 템플릿 파일은 `apache2/templates/default/apache.conf.erb`여야 합니다. 정확히 동일한 이름을 사용하면 OpsWorks Stacks가 사용자 지정 템플릿을 인식하고 기본 제공 템플릿 대신 사용할 수 있습니다.

   [내장 쿡북의 GitHub 리포지토리](https://github.com/aws/opsworks-cookbooks)에서 쿡북으로 내장 템플릿 파일을 복사한 다음 필요에 따라 수정하는 것이 가장 간단합니다.
**중요**  
사용자 지정하려는 템플릿 파일을 제외하고는 내장 쿡북에서 어떠한 파일도 복사하지 마십시오. 다른 유형의 쿡북 파일(예: 레시피)을 복사하면 중복 Chef 리소스가 생성되어 오류가 발생할 수 있습니다.

   또한 쿡북에는 사용자 지정 속성, 레시피 및 관련 파일이 포함될 수 있지만 파일 이름이 내장 파일 이름과 중복되면 안 됩니다.

1. 템플릿 파일을 사용자 지정하여 요구 사항을 충족하는 구성 파일을 생성합니다. 설정을 더 추가하고, 기존 설정을 삭제하고, 하드코딩된 설정을 대체하는 등의 작업을 수행할 수 있습니다.

1. 아직 수행하지 않은 경우에는 스택 설정을 편집해 사용자 지정 쿡북을 사용하고 쿡북 리포지토리를 지정할 수 있습니다. 자세한 내용은 [사용자 지정 쿡북 설치](workingcookbook-installingcustom-enable.md) 섹션을 참조하세요.

**참고**  
이 절차에 대한 완전한 안내는 [내장 템플릿 재정의](cookbooks-101-opsworks-templates.md) 단원을 참조하세요.

템플릿을 재정의하기 위해 레시피를 구현하거나 [계층 구성에 레시피를 추가할](workingcookbook-assigningcustom.md) 필요가 없습니다. OpsWorks Stacks는 항상 기본 제공 레시피를 실행합니다. 구성 파일을 생성하는 레시피를 실행할 때는 내장 템플릿 대신 사용자 지정 템플릿을 자동으로 사용합니다.

**참고**  
 OpsWorks Stacks가 기본 제공 템플릿을 변경하면 사용자 지정 템플릿이 동기화되지 않아 더 이상 제대로 작동하지 않을 수 있습니다. 예를 들어 템플릿이 종속 파일을 참조하고 파일 이름이 변경된다고 가정해 보겠습니다. OpsWorks Stacks는 이러한 변경을 자주 수행하지 않으며 템플릿이 변경되면 변경 사항을 나열하고 새 버전으로 업그레이드할 수 있는 옵션을 제공합니다. Stacks OpsWorks 리포지토리에서 변경 사항을 모니터링하고 필요에 따라 템플릿을 수동으로 업데이트해야 합니다.

# 계층 확장
<a name="workingcookbook-extend"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

 OpsWorks Stacks 속성 수정 또는 템플릿 사용자 지정으로 처리할 수 있는 것 이상으로 내장 계층을 사용자 지정해야 할 경우가 가끔 있습니다. 예를 들어 symlink를 생성하거나 파일 또는 폴더 모드를 설정하거나 추가 패키지를 설치하는 등의 작업이 필요하다고 가정해 봅시다. 최소 기능 이상을 제공하려면 사용자 지정 계층을 확장해야 합니다. 이 경우 사용자 지정 작업을 처리하기 위한 레시피로 하나 이상의 사용자 지정 쿡북을 구현해야 합니다. 이 항목에서는 레시피를 사용하여 계층을 확장하는 방법을 예시합니다.

Chef를 처음 사용하는 경우 먼저 다양한 일반적인 작업을 수행하기 위한 쿡북을 구현하는 기본적인 방법을 소개하는 [쿡북 101](cookbooks-101.md) 섹션을 읽어야 합니다. 사용자 지정 계층을 구현하는 방법의 상세한 예는 [사용자 지정 Tomcat 서버 계층 생성](create-custom.md) 단원을 참조하세요.

**Topics**
+ [레시피를 사용하여 스크립트 실행](workingcookbook-extend-scripts.md)
+ [Chef 배포 후크 사용](workingcookbook-extend-hooks.md)
+ [Linux 인스턴스에서 Cron 작업 실행](workingcookbook-extend-cron.md)
+ [Linux 인스턴스에서 패키지 설치 및 구성](workingcookbook-extend-package.md)

# 레시피를 사용하여 스크립트 실행
<a name="workingcookbook-extend-scripts"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

필요한 사용자 지정 작업을 수행하는 스크립트가 이미 있는 경우 가장 간편하게 계층을 확장하는 방법은 종종 스크립트를 실행하기 위한 간단한 레시피를 구현하는 것입니다. 그런 다음 레시피를 적절한 수명 주기 이벤트(일반적으로 설정 또는 Deploy)에 할당하거나 `execute_recipes` 스택 명령을 사용하여 수동으로 레시피를 실행할 수 있습니다.

다음 예제는 Linux 인스턴스에서 shell 스크립트를 실행하지만, Windows PowerShell 스크립트 등 다른 유형의 스크립트에도 동일한 접근 방식을 사용할 수 있습니다.

```
cookbook_file "/tmp/lib-installer.sh" do
  source "lib-installer.sh"
  mode 0755
end

execute "install my lib" do
  command "sh /tmp/lib-installer.sh"
end
```

`cookbook_file` 리소스는 쿡북의 `files` 디렉터리 내 하위 디렉터리에 저장된 파일을 나타내며, 파일을 인스턴스의 지정된 위치로 전송합니다. 이 예제에서는 shell 스크립트 `lib-installer.sh`를 인스턴스의 `/tmp` 디렉터리로 전송하고 파일의 모드를 `0755`로 설정합니다. 자세한 정보는 [cookbook\$1file](https://docs.chef.io/chef/resources.html#cookbook-file) 단원을 참조하세요.

`execute` 리소스는 명령을 나타냅니다(예: shell 명령). 이 예제에서는 `lib-installer.sh`를 실행합니다. 자세한 정보는 [실행](https://docs.chef.io/chef/resources.html#execute)을 참조하세요.

또한 스크립트를 레시피에 통합하여 레시피를 실행할 수도 있습니다. 다음 예제는 bash 스크립트를 실행하지만 Chef는 Csh, Perl, Python 및 Ruby도 지원합니다.

```
script "install_something" do
  interpreter "bash"
  user "root"
  cwd "/tmp"
  code <<-EOH
    #insert bash script
  EOH
end
```

`script` 리소스는 스크립트를 나타냅니다. 예제에서는 bash 인터프리터를 지정하고, 사용자를 `"root"`로 설정하고, 작업 디렉터리를 `/tmp`로 설정합니다. 그런 다음 `code` 블록의 bash 스크립트를 실행합니다. 이 스크립트는 필요한 만큼 많은 줄을 포함할 수 있습니다. 자세한 정보는 [script](https://docs.chef.io/chef/resources.html#script)를 참조하세요.

레시피를 사용하여 스크립트를 실행하는 방법에 대한 자세한 정보는 [예제 7: 명령 및 스크립트 실행](cookbooks-101-basics-commands.md) 단원을 참조하세요. Windows 인스턴스에서 PowerShell을 실행하는 방법에 대한 예제는 [Windows PowerShell 스크립트 실행](cookbooks-101-opsworks-opsworks-powershell.md) 단원을 참조하세요.

# Chef 배포 후크 사용
<a name="workingcookbook-extend-hooks"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

필요한 작업을 수행하기 위한 사용자 지정 레시피를 구현하고 적절한 계층의 설정 이벤트에 레시피를 할당하여 배포를 사용자 지정할 수 있습니다. 대안적이고 때로는 더 간단한 접근 방식(특히 다른 목적으로 쿡북을 구현할 필요가 없는 경우)은 Chef 배포 후크를 사용하여 사용자 지정 코드를 실행하는 것입니다. 또한 사용자 지정 Deploy 레시피는 내장 레시피가 배포를 이미 완료한 후에 실행됩니다. 배포 후크를 사용하면 배포 도중(예를 들어 앱의 코드가 리포지토리에서 체크아웃되었지만 Apache가 재시작되기 전) 상호 작용이 가능합니다.

Chef는 앱을 4개 단계로 배포합니다.
+ **체크아웃** - 리포지토리에서 파일을 다운로드합니다.
+ **마이그레이션** -필요에 따라 마이그레이션을 실행합니다.
+ **Symlink** - symlink를 생성합니다.
+ **재시작** - 애플리케이션을 다시 시작합니다.

Chef 배포 후크는 각 단계 완료 후 선택적으로 사용자 제공 Ruby 애플리케이션을 실행하여 배포를 간편하게 사용자 지정할 수 있는 방법을 제공합니다. 배포 후크를 사용하려면 Ruby 애플리케이션을 하나 이상 구현하여 앱의 `/deploy` 디렉터리에 배치합니다. (앱에 `/deploy` 디렉터리가 없으면 `APP_ROOT` 수준에서 디렉터리를 생성하세요.) 애플리케이션은 다음 이름 중 하나를 가져야 합니다. 이 이름은 실행 시점을 결정합니다.
+ `before_migrate.rb`는 체크아웃 단계 완료 후, 마이그레이션 단계 전에 실행됩니다.
+ `before_symlink.rb`는 마이그레이션 단계 완료 후, Symlink 단계 전에 실행됩니다.
+ `before_restart.rb`는 Symlink 단계 완료 후, 재시작 단계 전에 실행됩니다.
+ `after_restart.rb`는 재시작 단계가 완료된 후에 실행됩니다.

Chef 배포 후크는 레시피와 마찬가지로 표준 노드 구문을 사용하여 노드 객체에 액세스할 수 있습니다. 또한 배포 후크는 사용자가 지정한 모든 [앱 환경 변수](workingapps-creating.md#workingapps-creating-environment)의 값에 액세스할 수 있습니다. 그러나 `ENV["VARIABLE_NAME"]` 대신 `new_resource.environment["VARIABLE_NAME"] `을 사용하여 변수 값에 액세스해야 합니다.

# Linux 인스턴스에서 Cron 작업 실행
<a name="workingcookbook-extend-cron"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

Linux cron 작업은 cron 데몬이 지정된 일정으로 하나 이상의 명령을 실행하도록 지시합니다. 예를 들어 스택이 PHP 전자 상거래 애플리케이션을 지원한다고 가정하겠습니다. 서버가 매주 지정된 시간에 판매 보고서를 전송하도록 cron 작업을 설정할 수 있습니다. Cron에 대한 자세한 내용은 Wikipedia에서 [cron](http://en.wikipedia.org/wiki/Cron)을 참조하세요. Linux 기반 컴퓨터 또는 인스턴스에서 cron을 직접 실행하는 방법에 대한 자세한 정보는 Indiana University 지식 기반 웹 사이트에서 [What are cron and crontab, and how do I use them?](https://kb.iu.edu/d/afiz) 단원을 참조하세요.

SSH로 `cron` 작업에 연결하고 `crontab` 항목을 편집하여 개별 Linux 기반 인스턴스에서 cron 작업을 수동으로 설정할 수는 있지만, OpsWorks Stacks의 주된 장점 중 하나는 전체 인스턴스 계층에서 작업을 실행하도록 지시할 수 있다는 점입니다. 다음 절차에서는 PHP 앱 서버 계층의 인스턴스에서 `cron` 작업을 설정하는 방법을 설명하지만, 어떤 계층에서도 동일한 접근 방식을 사용할 수 있습니다.

**계층의 인스턴스에 대한 `cron` 작업을 설정하려면**

1. 이 작업을 설정하는 `cron` 리소스가 포함된 레시피를 사용하여 쿡북을 구현합니다. 이 예제에서는 레시피의 이름이 `cronjob.rb`라고 가정하고, 자세한 구현 정보는 뒤에서 설명합니다. 쿡북 및 레시피에 대한 자세한 내용은 [쿡북과 레시피](workingcookbook.md) 단원을 참조하세요.

1. 스택에 쿡북을 설치합니다. 자세한 내용은 [사용자 지정 쿡북 설치](workingcookbook-installingcustom-enable.md) 단원을 참조하십시오.

1.  OpsWorks Stacks가 다음 수명 주기 이벤트에 할당하여 계층의 인스턴스에서 레시피를 자동으로 실행하도록 합니다. 자세한 내용은 [자동으로 레시피 실행](workingcookbook-assigningcustom.md) 단원을 참조하십시오.
   + **설정** -이 이벤트에 할당`cronjob.rb`하면 OpsWorks Stacks가 모든 새 인스턴스에서 레시피를 실행하도록 지시합니다.
   + **배포** - `cronjob.rb`이 이벤트에 할당하면 앱을 계층에 배포하거나 재배포할 때 OpsWorks Stacks가 모든 온라인 인스턴스에서 레시피를 실행하도록 지시합니다.

   `Execute Recipes` 스택 명령을 사용하여 온라인 인스턴스에서 레시피를 수동으로 실행할 수도 있습니다. 자세한 내용은 [스택 명령 실행](workingstacks-commands.md) 섹션을 참조하세요.

다음은 서버로부터 판매 데이터를 수집하여 보고서를 전송하는 사용자 구현 PHP 애플리케이션을 매주 한 번 실행하도록 cron 작업을 설정하는 `cronjob.rb` 예제입니다. Cron 리소스를 사용하는 방법의 추가 예제는 [cron](https://docs.chef.io/chef/resources.html#cron)을 참조하세요.

```
cron "job_name" do
  hour "1"
  minute "10"
  weekday "6"
  command "cd /srv/www/myapp/current && php .lib/mailing.php"
end
```

`cron`은 `cron` 작업을 나타내는 Chef 리소스입니다. OpsWorks Stacks가 인스턴스에서 레시피를 실행하면 연결된 공급자가 작업 설정의 세부 정보를 처리합니다.
+ `job_name`은 `cron` 작업의 사용자 정의 이름입니다(예: `weekly report`).
+ `hour`/`minute`/`weekday`는 명령을 실행할 시점을 지정합니다. 이 예제는 명령을 매주 토요일 오전 1시 10분에 실행합니다.
+ `command`는 실행할 명령을 지정합니다.

  이 예제는 2개의 명령을 실행합니다. 첫 번째 명령은 `/srv/www/myapp/current` 디렉터리로 이동합니다. 두 번째 명령은 판매 데이터를 수집하고 보고서를 전송하는 사용자 구현 `mailing.php` 애플리케이션을 실행합니다.

**참고**  
`bundle` 명령은 기본적으로 `cron` 작업에 사용되지 않습니다. 그 이유는 OpsWorks Stacks가 `/usr/local/bin` 디렉터리에 번들러를 설치하기 때문입니다. `bundle` 작업에서 `cron`을 사용하려면 명시적으로 `/usr/local/bin` 경로를 cron 작업에 추가해야 합니다. 또한 `cron` 작업에서 \$1PATH 환경 변수가 확장되지 않을 수 있으므로, \$1PATH 변수의 확장에 의존하지 않고 필요한 경로 정보를 모두 명시적으로 추가하는 것이 모범 사례입니다. 다음 예제는 `cron` 작업에서 `bundle`을 사용하는 두 가지 방법을 보여줍니다.  

```
cron "my first task" do
  path "/usr/local/bin"
  minute "*/10"
  command "cd /srv/www/myapp/current && bundle exec my_command"
end
```

```
cron_env = {"PATH" => "/usr/local/bin"}
cron "my second task" do
  environment cron_env
  minute "*/10"
  command "cd /srv/www/myapp/current && /usr/local/bin/bundle exec my_command"
end
```

스택에 여러 애플리케이션 서버가 있는 경우 PHP 앱 서버 계층의 수명 주기 이벤트에 `cronjob.rb`를 할당하는 접근 방식은 이상적이지 않을 수 있습니다. 예를 들어 레시피가 계층의 모든 인스턴스에서 실행되므로 여러 보고서가 전송됩니다. 이보다 나은 접근 방식은 사용자 지정 계층을 사용하여 한 서버만 보고서를 전송하도록 하는 것입니다.

**계층의 인스턴스 중 하나에서만 레시피를 실행하려면**

1. 예를 들어, PHPAdmin이라는 사용자 지정 계층을 만들고 이 계층의 설정 및 Deploy 이벤트에 `cronjob.rb`를 할당합니다. 사용자 지정 계층에서 반드시 많은 레시피를 실행할 필요는 없습니다. 이 경우, PHPAdmin은 인스턴스에서 사용자 지정 레시피 하나를 실행하기만 하면 됩니다.

1. PHP 앱 서버 인스턴스 중 하나를 AdminLayer에 할당합니다. 인스턴스가 둘 이상의 계층에 속하는 경우 OpsWorks Stacks는 각 계층의 내장 및 사용자 지정 레시피를 실행합니다.

인스턴스 하나만 PHP 앱 서버 및 PHPAdmin 계층에 속하므로 `cronjob.rb`는 해당 인스턴스에서만 실행되고, 따라서 하나의 보고서만 전송됩니다.

# Linux 인스턴스에서 패키지 설치 및 구성
<a name="workingcookbook-extend-package"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

내장 계층은 특정 패키지만 지원합니다. 자세한 내용은 [계층](workinglayers.md) 섹션을 참조하세요. 연결된 설정, 구성 및 배포 작업을 처리할 사용자 지정 레시피를 구현하여 Redis 서버와 같은 다른 패키지를 설치할 수 있습니다. 경우에 따라서는 내장 계층을 확장하여 패키지를 계층의 표준 패키지와 함께 인스턴스에 설치하도록 하는 것이 최선의 접근 방식입니다. 예를 들어 PHP 애플리케이션을 지원하는 스택이 있고 Redis 서버를 포함시키기를 원할 경우 PHP 앱 서버 계층을 확장하고 계층의 인스턴스에서 PHP 애플리케이션 서버 이외에 Redis 서버를 구성할 수 있습니다.

일반적으로 패키지 설치 레시피는 다음과 같은 작업을 수행합니다.
+ 하나 이상의 디렉터리를 생성하고 각각 모드를 설정
+ 템플릿에서 구성 파일을 생성
+ 설치 관리자를 실행하여 인스턴스에 패키지를 설치
+ 하나 이상의 서비스를 시작

Tomcat 서버를 설치하는 방법의 예제는 [사용자 지정 Tomcat 서버 계층 생성](create-custom.md) 단원을 참조하세요. 이 항목에서는 사용자 지정 Redis 계층을 설정하는 방법을 설명하지만, 동일한 코드를 사용하여 내장 계층에서 Redis를 설치하고 구성할 수 있습니다. 다른 패키지를 설치하는 방법에 대한 예는 내장된 쿡북 [(https://github.com/aws/opsworks-cookbooks)](https://github.com/aws/opsworks-cookbooks)을 참조하세요.

# 사용자 지정 Tomcat 서버 계층 생성
<a name="create-custom"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

**참고**  
이 항목에서는 Linux 스택용 사용자 지정 계층을 구성하는 방법을 설명합니다. 하지만 기본 원칙 및 일부 코드(특히 앱 배포 섹션)를 수정하면 Windows 스택용 사용자 지정 계층도 구현할 수 있습니다.

 OpsWorks Stacks 인스턴스에서 비표준 패키지를 사용하는 가장 간단한 방법은 [기존 계층을 확장하는 것입니다](workingcookbook-extend-package.md). 하지만 이 접근 방식은 계층이 인스턴스에 표준 및 비표준 패키지를 모두 설치하고 실행하므로 항상 바람직한 것은 아닙니다. 약간 까다롭지만 더 강력한 접근 방식은 사용자 지정 계층을 구현하는 것입니다. 이는 다음을 비롯해 계층의 인스턴스에 대해 거의 완벽한 제어를 제공합니다.
+ 설치될 패키지
+ 패키지가 구성되는 방법
+ 리포지토리에서 인스턴스로 앱을 배포하는 방법

콘솔 또는 API를 사용하여 [사용자 지정 계층](workinglayers-custom.md) 섹션에 설명된 대로 다른 계층과 거의 똑같이 사용자 지정 계층을 생성하고 관리합니다. 하지만 사용자 지정 계층의 내장 레시피는 Ganglia 클라이언트를 설치하여 Ganglia 마스터로 측정치를 보고하는 것과 같은 매우 기본적인 일부 작업만 수행합니다. 사용자 지정 계층의 인스턴스가 최소 기능 이상을 발휘하게 하려면 패키지 설치와 구성, 앱 배포 등의 작업을 처리하도록 Chef 레시피 및 관련 파일을 포함하는 하나 이상의 사용자 지정 쿡북을 구현해야 합니다. 하지만 모든 것을 처음부터 구현해야 하는 것은 아닙니다. 예를 들어 애플리케이션을 표준 리포지토리 중 하나에 저장하는 경우 내장 deploy 레시피를 사용하여 계층의 인스턴스에 애플리케이션을 설치하는 작업을 대부분 처리할 수 있습니다.

**참고**  
Chef를 처음 사용하는 경우 먼저 다양한 일반적인 작업을 수행하기 위한 쿡북을 구현하는 기본적인 방법을 소개하는 [쿡북 101](cookbooks-101.md) 섹션을 읽어야 합니다.

다음 안내서에서는 Tomcat 애플리케이션 서버를 지원하는 사용자 지정 계층을 구현하는 방법을 설명합니다. 이 계층은 Tomcat이라는 사용자 지정 쿡북을 기반으로 하며, 패키지 설치, 배포 등을 처리하는 레시피를 포함합니다. 이 안내서는 Tomcat 쿡북에서 발췌된 코드를 포함하고 있습니다. 전체 쿡북은 [GitHub 리포지토리](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)에서 다운로드할 수 있습니다. [Opscode Chef](http://www.opscode.com/chef/)에 대해 잘 알지 못하는 경우 먼저 [쿡북과 레시피](workingcookbook.md) 섹션을 읽어야 합니다.

**참고**  
OpsWorks Stacks에는 프로덕션용 전체 기능을 갖춘 [Java 앱 서버 계층](layers-java.md)이 포함되어 있습니다. Tomcat 쿡북은 사용자 지정 계층을 구현하는 방법을 예시하는 것이 목적이므로 SSL과 같은 기능을 포함하지 않는 제한적 버전의 Tomcat만 지원합니다. 전체 기능을 제공하는 구현의 예는 내장 [opsworks\$1java](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.10/opsworks_java) 쿡북 단원을 참조하세요.

Tomcat 쿡북은 인스턴스가 다음과 같은 특성을 갖는 사용자 지정 계층을 지원합니다.
+ Apache 프런트 엔드를 포함하는 Tomcat Java 애플리케이션 서버를 지원함
+ 애플리케이션이 JDBC `DataSource` 객체를 사용하여 백 엔드 데이터 스토어로 사용되는 별도의 MySQL 인스턴스에 연결하는 것을 허용하도록 Tomcat이 구성됨

이 프로젝트의 쿡북에는 다수의 주요 구성 요소가 포함됩니다.
+ [속성 파일](create-custom-attributes.md)은 다양한 레시피가 사용하는 구성 파일을 포함하고 있습니다.
+ [설정 레시피](create-custom-setup.md)는 계층의 설정 [수명 주기 이벤트](workingcookbook-events.md)에 할당됩니다. 이 레시피는 인스턴스 부팅 후 실행되며 패키지 설치, 구성 파일 생성과 같은 작업을 수행합니다.
+ [Configure 레시피](create-custom-configure.md)는 계층의 Configure 수명 주기 이벤트에 할당됩니다. 스택의 구성이 변경된 후(주로 인스턴스가 온라인 상태가 되거나 오프라인 상태가 될 때) 실행되며 필요한 구성 변경을 모두 처리합니다.
+ [Deploy 레시피](create-custom-deploy.md)는 계층의 Deploy 수명 주기 이벤트에 할당됩니다. 이 레시피는 설정 레시피 이후 또한 사용자가 수동으로 앱을 배포하여 코드 및 관련 파일을 계층의 인스턴스에 설치할 때 실행되며, 서비스 재시작과 같은 관련 작업을 처리합니다.

마지막 섹션 [스택 생성 및 애플리케이션 실행](create-custom-stack.md)에서는 Tomcat 쿡북을 기반으로 한 사용자 지정 계층을 포함하는 스택을 생성하는 방법과 별도의 MySQL 계층에 속하는 인스턴스에서 실행되는 MySQL 데이터베이스로부터 데이터를 표시하는 간단한 JSP 애플리케이션을 배포하고 실행하는 방법을 설명합니다.

**참고**  
Tomcat 쿡북 레시피는 일부 OpsWorks Stacks 내장 레시피에 따라 달라집니다. 각 레시피의 출처를 명확히 하기 위해 이 항목에서는 Chef *cookbookname*::*recipename* 규칙을 사용하여 레시피를 식별합니다.

**Topics**
+ [속성 파일](create-custom-attributes.md)
+ [설정 레시피](create-custom-setup.md)
+ [Configure 레시피](create-custom-configure.md)
+ [Deploy 레시피](create-custom-deploy.md)
+ [스택 생성 및 애플리케이션 실행](create-custom-stack.md)

# 속성 파일
<a name="create-custom-attributes"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

레시피에 대해 알아보기 전에 먼저 Tomcat 쿡북의 속성 파일을 살펴보는 것이 유용합니다. 이 파일에는 레시피가 사용하는 다양한 구성 설정이 들어 있습니다. 속성은 필수는 아닙니다. 레시피 또는 템플릿에서 이들 값을 하드코딩할 수도 있습니다. 그러나 속성을 사용하여 구성 설정을 정의하는 경우 OpsWorks Stacks 콘솔 또는 API를 사용하여 설정을 변경할 때마다 레시피 또는 템플릿 코드를 다시 작성하는 것보다 더 간단하고 유연한 사용자 지정 JSON 속성을 정의하여 값을 수정할 수 있습니다. 이 접근 방식을 사용하면 예를 들어 여러 스택에 동일한 쿡북을 사용하되 각 스택마다 Tomcat 서버를 다르게 구성할 수 있습니다. 속성과 속성 재정의 방법에 대한 자세한 정보는 [속성 재정의](workingcookbook-attributes.md) 단원을 참조하세요.

다음 예제는 Tomcat 쿡북의 `default.rb` 디렉터리에 위치하는 전체 속성 파일 `attributes`입니다.

```
default['tomcat']['base_version'] = 6
default['tomcat']['port'] = 8080
default['tomcat']['secure_port'] = 8443
default['tomcat']['ajp_port'] = 8009
default['tomcat']['shutdown_port'] = 8005
default['tomcat']['uri_encoding'] = 'UTF-8'
default['tomcat']['unpack_wars'] = true
default['tomcat']['auto_deploy'] = true
case node[:platform]
when 'centos', 'redhat', 'fedora', 'amazon'
  default['tomcat']['java_opts'] = ''
when 'debian', 'ubuntu'
  default['tomcat']['java_opts'] = '-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC'
end
default['tomcat']['catalina_base_dir'] = "/etc/tomcat#{node['tomcat']['base_version']}"
default['tomcat']['webapps_base_dir'] = "/var/lib/tomcat#{node['tomcat']['base_version']}/webapps"
default['tomcat']['lib_dir'] = "/usr/share/tomcat#{node['tomcat']['base_version']}/lib"
default['tomcat']['java_dir'] = '/usr/share/java'
default['tomcat']['mysql_connector_jar'] = 'mysql-connector-java.jar'
default['tomcat']['apache_tomcat_bind_mod'] = 'proxy_http' # or: 'proxy_ajp'
default['tomcat']['apache_tomcat_bind_config'] = 'tomcat_bind.conf'
default['tomcat']['apache_tomcat_bind_path'] = '/tc/'
default['tomcat']['webapps_dir_entries_to_delete'] = %w(config log public tmp)
case node[:platform]
when 'centos', 'redhat', 'fedora', 'amazon'
  default['tomcat']['user'] = 'tomcat'
  default['tomcat']['group'] = 'tomcat'
  default['tomcat']['system_env_dir'] = '/etc/sysconfig'
when 'debian', 'ubuntu'
  default['tomcat']['user'] = "tomcat#{node['tomcat']['base_version']}"
  default['tomcat']['group'] = "tomcat#{node['tomcat']['base_version']}"
  default['tomcat']['system_env_dir'] = '/etc/default'
end
```

설정 자체에 대해서는 나중에 관련 섹션에서 설명합니다. 다음 참고 사항은 전반적으로 적용됩니다.
+ 노드 정의는 모두 `default` 유형이므로 [사용자 지정 JSON 속성](workingcookbook-json-override.md)으로 재정의할 수 있습니다.
+ 파일은 `case` 문을 사용하여 인스턴스의 운영 체제에 따라 일부 속성 값을 조건적으로 설정합니다.

  `platform` 노드는 Chef의 Ohai 도구에 의해 생성되며 인스턴스의 운영 체제를 표시합니다.

# 설정 레시피
<a name="create-custom-setup"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

설정 레시피는 계층의 설정 [수명 주기](workingcookbook-events.md) 이벤트에 할당되고 인스턴스 부팅 후 실행됩니다. 이 레시피는 패키지 설치, 구성 파일 생성, 서비스 시작과 같은 작업을 수행합니다. Setup 레시피 실행이 완료되면 OpsWorks Stacks는 [Deploy 레시피](create-custom-deploy.md)를 실행하여 앱을 새 인스턴스에 배포합니다.

**Topics**
+ [tomcat::설정](#create-custom-setup-setup)
+ [tomcat::install](#create-custom-setup-install)
+ [tomcat::service](#create-custom-setup-service)
+ [tomcat::container\$1config](#create-custom-setup-config)
+ [tomcat::apache\$1tomcat\$1bind](#create-custom-setup-bind)

## tomcat::설정
<a name="create-custom-setup-setup"></a>

`tomcat::setup` 레시피는 계층의 설정 수명 주기 이벤트에 할당됩니다.

```
include_recipe 'tomcat::install'
include_recipe 'tomcat::service'

service 'tomcat' do
  action :enable
end

# for EBS-backed instances we rely on autofs
bash '(re-)start autofs earlier' do
  user 'root'
  code <<-EOC
    service autofs restart
  EOC
  notifies :restart, resources(:service => 'tomcat')
end

include_recipe 'tomcat::container_config'
include_recipe 'apache2'
include_recipe 'tomcat::apache_tomcat_bind'
```

`tomcat::setup` 레시피는 대체로 메타 레시피입니다. Tomcat 및 관련 패키지를 설치하고 구성하는 세부 작업을 대부분 처리하는 일련의 종속 레시피가 포함됩니다. `tomcat::setup`의 첫 번째 부분은 다음 레시피를 실행합니다(각 레시피에 대해서는 나중에 설명).
+ [tomcat::install](#create-custom-setup-install) 레시피는 Tomcat 서버 패키지를 설치합니다.
+ [tomcat::service](#create-custom-setup-service) 레시피는 Tomcat 서비스를 설정합니다.

`tomcat::setup`의 중간 부분은 Tomcat 서비스를 활성화하고 시작합니다.
+ Chef [서비스 리소스](https://docs.chef.io/chef/resources.html#service)는 부팅 시 Tomcat 서비스를 활성화합니다.
+ Chef [bash 리소스](https://docs.chef.io/chef/resources.html#bash)는 Bash 스크립트를 실행하여 Amazon EBS 지원 인스턴스에 필요한 autofs 대몬(daemon)을 시작합니다. 그런 다음 이 리소스는 `service` 리소스에 Tomcat 서비스를 재시작하라고 알립니다.

  자세한 정보는 [autofs](https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/s2-nfs-config-autofs.html)(Amazon Linux) 또는 [Autofs](https://help.ubuntu.com/community/Autofs)(Ubuntu)를 참조하세요.

`tomcat::setup`의 마지막 부분은 구성 파일을 생성하고 프런트 엔드 Apache 서버를 설치하고 구성합니다.
+ [tomcat::container\$1config](#create-custom-setup-config) 레시피는 구성 파일을 생성합니다.
+ `apache2` 레시피(의 약어`apache2::default`)는 Apache 서버를 설치하고 구성하는 OpsWorks Stacks 기본 제공 레시피입니다.
+ [tomcat::apache\$1tomcat\$1bind](#create-custom-setup-bind) 레시피는 Apache 서버가 Tomcat 서버의 프런트 엔드로 기능하도록 구성합니다.

**참고**  
내장 레시피를 사용하여 일부 필요한 작업을 수행하면 시간과 노력을 아낄 수 있는 경우가 자주 있습니다. 이 레시피는 처음부터 Apache를 구현하는 것이 아니라 내장 `apache2::default` 레시피를 사용하여 Apache를 설치합니다. 내장 레시피를 사용하는 방법의 또 하나의 예는 [Deploy 레시피](create-custom-deploy.md) 단원을 참조하세요.

다음 섹션에서는 Tomcat 쿡북의 설정 레시피에 대해 보다 자세히 설명합니다. `apache2` 레시피에 대한 자세한 정보는 [opsworks-cookbooks/apache2](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.4/apache2)를 참조하세요.

## tomcat::install
<a name="create-custom-setup-install"></a>

`tomcat::install `레시피는 Tomcat 서버, OpenJDK, 그리고 MySQL 서버 연결을 처리하는 Java 커넥터 라이브러리를 설치합니다.

```
tomcat_pkgs = value_for_platform(
  ['debian', 'ubuntu'] => {
    'default' => ["tomcat#{node['tomcat']['base_version']}", 'libtcnative-1', 'libmysql-java']
  },
  ['centos', 'redhat', 'fedora', 'amazon'] => {
    'default' => ["tomcat#{node['tomcat']['base_version']}", 'tomcat-native', 'mysql-connector-java']
  },
  'default' => ["tomcat#{node['tomcat']['base_version']}"]
)

tomcat_pkgs.each do |pkg|
  package pkg do
    action :install
  end
end

link ::File.join(node['tomcat']['lib_dir'], node['tomcat']['mysql_connector_jar']) do
  to ::File.join(node['tomcat']['java_dir'], node['tomcat']['mysql_connector_jar'])
  action :create
end

# remove the ROOT webapp, if it got installed by default
include_recipe 'tomcat::remove_root_webapp'
```

이 레시피가 수행하는 작업은 다음과 같습니다.

1. 인스턴스의 운영 체제에 따라 설치할 패키지의 목록을 생성합니다.

1. 목록의 각 패키지를 설치합니다.

   Chef [패키지 리소스](https://docs.chef.io/chef/resources.html#id146)는 Amazon Linux의 경우 `yum`와 Ubuntu의 경우 `apt-get`인 적절한 공급자를 사용하여 설치를 처리합니다. 패키지 공급자가 OpenJDK를 Tomcat 종속성으로 설치하지만, MySQL 커넥터 라이브러리는 명시적으로 설치되어야 합니다.

1. Chef [링크 리소스](https://docs.chef.io/chef/resources.html#link)를 사용하여 Tomcat 서버의 라이브러리 디렉터리에서 JDK 내 MySQL 커넥터 라이브러리에 대한 symlink를 생성합니다.

   기본 속성 값을 사용할 경우 Tomcat 라이브러리 디렉터리는 `/usr/share/tomcat6/lib`이고, MySQL 커넥터 라이브러리(`mysql-connector-java.jar`)는 `/usr/share/java/`에 위치합니다.

`tomcat::remove_root_webapp` 레시피는 ROOT 웹 애플리케이션(기본적으로 `/var/lib/tomcat6/webapps/ROOT`)을 제거하여 일부 보안 문제를 방지합니다.

```
ruby_block 'remove the ROOT webapp' do
  block do
    ::FileUtils.rm_rf(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT'), :secure => true)
  end
  only_if { ::File.exists?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) && !::File.symlink?(::File.join(node['tomcat']['webapps_base_dir'], 'ROOT')) }
end
```

`only_if` 문은 파일이 존재하는 경우에만 레시피가 파일을 제거하도록 합니다.

**참고**  
Tomcat 버전은 `['tomcat']['base_version']` 속성에 의해 지정되는데, 속성 파일에서 6으로 설정되어 있습니다. Tomcat 7을 설치하려면 사용자 지정 JSON 속성을 사용하여 속성을 재정의할 수 있습니다. [스택 설정을 편집](workingstacks-edit.md)하고 다음 JSON을 [**사용자 지정 Chef JSON**] 상자에 입력하거나 기존의 사용자 지정 JSON에 추가하면 됩니다.  

```
{
  'tomcat' : {
    'base_version' : 7
  }
}
```
사용자 지정 JSON 속성은 기본 속성을 재정의하고 Tomcat 버전을 7로 설정합니다. 속성 재정의에 대한 자세한 정보는 [속성 재정의](workingcookbook-attributes.md) 단원을 참조하세요.

## tomcat::service
<a name="create-custom-setup-service"></a>

`tomcat::service` 레시피는 Tomcat 서비스 정의를 생성합니다.

```
service 'tomcat' do
  service_name "tomcat#{node['tomcat']['base_version']}"

  case node[:platform]
  when 'centos', 'redhat', 'fedora', 'amazon'
    supports :restart => true, :reload => true, :status => true
  when 'debian', 'ubuntu'
    supports :restart => true, :reload => false, :status => true
  end

  action :nothing
end
```

이 레시피는 Chef [서비스 리소스](https://docs.chef.io/chef/resources.html#service)를 사용하여 Tomcat 서비스 이름(기본적으로 tomcat6)을 지정하고 `supports` 속성을 설정하여 Chef가 운영 체제별로 서비스의 restart, reload 및 status 명령을 관리하는 방법을 정의합니다.
+ `true`는 Chef가 init 스크립트 또는 그 밖의 서비스 공급자를 사용하여 명령을 실행할 수 있음을 나타냅니다.
+ `false`는 Chef가 다른 수단을 사용하여 명령을 실행하려 시도해야 함을 나타냅니다.

`action`은 `:nothing`로 설정됩니다. 각 수명 주기 이벤트에 대해 OpsWorks Stacks는 [Chef 실행](https://docs.chef.io/chef_client_overview.html#the-chef-client-run)을 시작하여 적절한 레시피 세트를 실행합니다. Tomcat 쿡북은 레시피가 서비스 정의를 생성하지만 서비스를 재시작하지는 않는 일반 패턴을 따릅니다. Chef 실행의 다른 레시피가 일반적으로 구성 파일을 생성하는 데 사용된 `notifies` 리소스에 `template` 명령을 포함시켜 재시작을 처리합니다. 알림은 서비스를 재시작하는 편리한 방법입니다. 구성이 변경된 경우에만 서비스를 재시작하기 때문입니다. 또한 Chef 실행에 특정 서비스에 대한 재시작 알림이 여러 개일 경우 Chef는 서비스를 한 번만 재시작합니다. 이 방법은 완전히 작동하지 않는 서비스를 재시작하려고 시도할 때 발생할 수 있는 문제를 방지하기 위한 것으로, 이 문제는 Tomcat 오류의 일반적인 원인입니다.

 Tomcat 서비스는 재시작 알림을 사용하는 모든 Chef 실행에 대해 정의되어야 합니다. `tomcat::service`는 여러 레시피에 포함되어 서비스가 모든 Chef 실행에 대해 정의되도록 합니다. Chef 실행에 `tomcat::service` 인스턴스가 여러 번 포함되더라도 Chef는 포함 횟수와 상관없이 Chef 실행당 한 번만 레시피를 실행하므로 페널티는 없습니다.

## tomcat::container\$1config
<a name="create-custom-setup-config"></a>

`tomcat::container_config` 레시피는 쿡북 템플릿 파일에서 구성 파일을 생성합니다.

```
include_recipe 'tomcat::service'

template 'tomcat environment configuration' do
  path ::File.join(node['tomcat']['system_env_dir'], "tomcat#{node['tomcat']['base_version']}")
  source 'tomcat_env_config.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'tomcat')
end

template 'tomcat server configuration' do
  path ::File.join(node['tomcat']['catalina_base_dir'], 'server.xml')
  source 'server.xml.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'tomcat')
end
```

이 레시피는 먼저 `tomcat::service`를 호출합니다. 필요할 경우 이 레시피가 서비스를 정의합니다. 레시피의 대부분은 2개의 [템플릿 리소스](https://docs.chef.io/chef/resources.html#template)로 구성되는데, 각각 쿡북의 템플릿 파일 중 하나에서 구성 파일을 생성하고, 파일 속성을 설정하고, Chef에 서비스를 재시작하라고 알립니다.

### Tomcat 환경 구성 파일
<a name="create-custom-setup-config-env"></a>

첫 번째 `template` 리소스는 `tomcat_env_config.erb` 템플릿 파일을 사용하여 Tomcat 환경 구성 파일을 생성합니다. 이 파일은 `JAVA_HOME`과 같은 환경 변수를 설정하는 데 사용됩니다. 기본 파일 이름은 `template` 리소스의 인수입니다. `tomcat::container_config`는 `path` 속성을 사용하여 기본값을 재정의하고 구성 파일을 `/etc/sysconfig/tomcat6`(Amazon Linux) 또는 `/etc/default/tomcat6` (Ubuntu)로 명명합니다. 또한 `template` 리소스는 파일의 소유자, 그룹 및 모드 설정을 지정하고 Chef에게 백업 파일을 생성하지 않도록 지시합니다.

소스 코드를 보면 실제로 세 버전의 `tomcat_env_config.erb`가 각각 `templates` 디렉터리의 서로 다른 하위 디렉터리에 위치합니다. `ubuntu` 및 `amazon` 디렉터리에는 해당 운영 체제용 템플릿이 들어 있습니다. `default` 폴더에는 명령줄 하나로 구성된 더미 템플릿이 들어 있습니다. 이 템플릿은 지원되지 않는 운영 체제를 사용하는 인스턴스에서 이 레시피를 실행하려고 시도할 경우에만 사용됩니다. `tomcat::container_config` 레시피는 사용할 `tomcat_env_config.erb`를 지정할 필요가 없습니다. Chef가 [File Specificity](http://docs.chef.io/templates.html#file-specificity)에 기술된 규칙에 따라 인스턴스의 운영 체제에 적합한 디렉터리를 선택합니다.

이 예제의 `tomcat_env_config.erb` 파일은 대부분 주석으로 구성되어 있습니다. 추가 환경 변수를 설정하려면 해당 줄의 주석 처리를 해제하고 원하는 값을 제공하면 됩니다.

**참고**  
변경될 수 있는 구성 설정은 템플릿에서 하드코딩하는 것보다는 속성으로 정의해야 합니다. 그러면 설정을 변경하기 위해 템플릿을 재작성할 필요 없이 속성을 재정의하기만 하면 됩니다.

Amazon Linux 템플릿은 다음 코드에 나와 있듯이 하나의 환경 변수만 설정합니다.

```
...
# Use JAVA_OPTS to set java.library.path for libtcnative.so
#JAVA_OPTS="-Djava.library.path=/usr/lib"

JAVA_OPTS="${JAVA_OPTS} <%= node['tomcat']['java_opts'] %>"

# What user should run tomcat
#TOMCAT_USER="tomcat"
...
```

JAVA\$1OPTS를 사용하여 라이브러리 경로와 같은 Java 옵션을 지정할 수 있습니다. 기본 속성 값을 사용할 경우 템플릿은 Amazon Linux에 대해 어떤 Java 옵션도 설정하지 않습니다. `['tomcat']['java_opts']` 속성을 재정의하여(예를 들어 사용자 지정 JSON 속성을 사용하여) 자체 Java 옵션을 설정할 수 있습니다. 예제는 [스택 생성](create-custom-stack.md#create-custom-stack-stack) 섹션을 참조하세요.

Ubuntu 템플릿은 다음 템플릿 코드에 나와 있듯이 여러 환경 변수를 설정합니다.

```
# Run Tomcat as this user ID. Not setting this or leaving it blank will use the
# default of tomcat<%= node['tomcat']['base_version'] %>.
TOMCAT<%= node['tomcat']['base_version'] %>_USER=tomcat<%= node['tomcat']['base_version'] %>
...
# Run Tomcat as this group ID. Not setting this or leaving it blank will use
# the default of tomcat<%= node['tomcat']['base_version'] %>.
TOMCAT<%= node['tomcat']['base_version'] %>_GROUP=tomcat<%= node['tomcat']['base_version'] %>
...
JAVA_OPTS="<%= node['tomcat']['java_opts'] %>"

<% if node['tomcat']['base_version'].to_i < 7 -%>
# Unset LC_ALL to prevent user environment executing the init script from
# influencing servlet behavior.  See Debian bug #645221
unset LC_ALL
<% end -%>
```

기본 속성 값을 사용하면 템플릿은 다음과 같이 Ubuntu 환경 변수를 설정합니다.
+ `TOMCAT6_USER` 및 `TOMCAT6_GROUP`(Tomcat 사용자 및 그룹을 표시)이 모두 `tomcat6`으로 설정됩니다.

  ['tomcat']['base\$1version']을 `tomcat7`로 설정할 경우 변수 이름이 `TOMCAT7_USER` 및 `TOMCAT7_GROUP`로 확인되고, 모두 `tomcat7`로 설정됩니다.
+ `JAVA_OPTS`가 `-Djava.awt.headless=true -Xmx128m -XX:+UseConcMarkSweepGC`로 설정됩니다.
  + `-Djava.awt.headless`를 `true`로 설정하면 그래픽 엔진에게 인스턴스가 헤드리스이고 콘솔이 없음을 알려줍니다. 이는 일부 그래픽 애플리케이션의 동작 오류를 해결합니다.
  + `-Xmx128m`은 JVM이 적절한 메모리 리소스를 사용하도록 지정합니다(이 예제에서는 128MB).
  + `-XX:+UseConcMarkSweepGC`는 동시 마크 스윕 가비지 수집을 지정합니다. 이는 가비지 수집으로 유발되는 일시 중지를 제한하는 데 도움이 됩니다.

    자세한 정보는 [Concurrent Mark Sweep Collector Enhancements](http://docs.oracle.com/javase/6/docs/technotes/guides/vm/cms-6.html)를 참조하세요.
+ Tomcat 버전이 7 미만일 경우 템플릿이 `LC_ALL`을 설정 해제합니다. 이는 Ubuntu 버그를 해결합니다.

**참고**  
기본 속성을 사용할 경우 이러한 환경 변수 중 일부가 기본값으로 설정됩니다. 하지만 명시적으로 환경 변수를 속성으로 설정하면 사용자 지정 JSON 속성을 정의하여 기본 속성을 재정의하고 사용자 지정 값을 제공할 수 있습니다. 속성 재정의에 대한 자세한 정보는 [속성 재정의](workingcookbook-attributes.md) 단원을 참조하세요.

전체 템플릿 파일은 [source code](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)를 참조하세요.

### Server.xml 구성 파일
<a name="create-custom-setup-config-server"></a>

두 번째 `template` 리소스는 `server.xml.erb`를 사용하여 서블릿/JSP 컨테이너를 구성하는 [`system.xml` 구성 파일](http://tomcat.apache.org/tomcat-7.0-doc/config/)을 생성합니다. `server.xml.erb`에는 운영 체제별 설정이 없으므로 `template` 디렉터리의 `default` 하위 디렉터리에 위치합니다.

템플릿은 표준 설정을 사용하지만 Tomcat 6 또는 Tomcat 7에 대해 `system.xml` 파일을 생성할 수 있습니다. 예를 들어 템플릿의 서버 섹션에서 발췌된 다음 코드는 리스너를 지정된 버전에 따라 적절하게 구성합니다.

```
<% if node['tomcat']['base_version'].to_i > 6 -%>
  <!-- Security listener. Documentation at /docs/config/listeners.html
  <Listener className="org.apache.catalina.security.SecurityListener" />
  -->
<% end -%>
  <!--APR library loader. Documentation at /docs/apr.html -->
  <Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
  <!--Initialize Jasper prior to webapps are loaded. Documentation at /docs/jasper-howto.html -->
  <Listener className="org.apache.catalina.core.JasperListener" />
  <!-- Prevent memory leaks due to use of particular java/javax APIs-->
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<% if node['tomcat']['base_version'].to_i < 7 -%>
  <!-- JMX Support for the Tomcat server. Documentation at /docs/non-existent.html -->
  <Listener className="org.apache.catalina.mbeans.ServerLifecycleListener" />
<% end -%>
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<% if node['tomcat']['base_version'].to_i > 6 -%>
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<% end -%>
```

템플릿은 하드코딩된 설정 대신 속성을 사용합니다. 따라서 사용자 지정 JSON 속성을 정의하여 간편하게 설정을 변경할 수 있습니다. 예제:

```
<Connector port="<%= node['tomcat']['port'] %>" protocol="HTTP/1.1"
           connectionTimeout="20000"
           URIEncoding="<%= node['tomcat']['uri_encoding'] %>"
           redirectPort="<%= node['tomcat']['secure_port'] %>" />
```

자세한 정보는 [source code](https://github.com/amazonwebservices/opsworks-example-cookbooks/tree/master/tomcat)를 참조하세요.

## tomcat::apache\$1tomcat\$1bind
<a name="create-custom-setup-bind"></a>

`tomcat::apache_tomcat_bind` 레시피는 Apache 서버가 Tomcat의 프런트 엔드로 동작하여 수신 요청을 수신하고, 요청을 Tomcat으로 전달하고, 응답을 클라이언트로 반환하도록 설정합니다. 이 예제에서는 [mod\$1proxy](https://httpd.apache.org/docs/2.2/mod/mod_proxy.html)를 Apache 프록시/게이트웨이로 사용합니다.

```
execute 'enable mod_proxy for apache-tomcat binding' do
  command '/usr/sbin/a2enmod proxy'
  not_if do
    ::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', 'proxy.load')) || node['tomcat']['apache_tomcat_bind_mod'] !~ /\Aproxy/
  end
end

execute 'enable module for apache-tomcat binding' do
  command "/usr/sbin/a2enmod #{node['tomcat']['apache_tomcat_bind_mod']}"
  not_if {::File.symlink?(::File.join(node['apache']['dir'], 'mods-enabled', "#{node['tomcat']['apache_tomcat_bind_mod']}.load"))}
end

include_recipe 'apache2::service'

template 'tomcat thru apache binding' do
  path ::File.join(node['apache']['dir'], 'conf.d', node['tomcat']['apache_tomcat_bind_config'])
  source 'apache_tomcat_bind.conf.erb'
  owner 'root'
  group 'root'
  mode 0644
  backup false
  notifies :restart, resources(:service => 'apache2')
end
```

`mod_proxy`를 활성화하려면 `proxy` 모듈과 프로토콜 기반 모듈을 활성화해야 합니다. 프로토콜 모듈에는 두 가지 옵션을 사용할 수 있습니다.
+ HTTP: `proxy_http`
+ [Apache JServ Protocol](http://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html)(AJP): `proxy_ajp`

  AJP는 내부 Tomcat 프로토콜입니다.

레시피의 두 [실행 리소스](https://docs.chef.io/chef/resources.html#execute)가 모두 `a2enmod` 명령을 실행합니다. 따라서 필요한 symlink를 생성하여 지정된 모듈을 활성화할 수 있습니다.
+ 첫 번째 `execute` 리소스는 `proxy` 모듈을 활성화합니다.
+ 두 번째 `execute` 리소스는 프로토콜 모듈을 활성화합니다. 이 모듈은 기본적으로 `proxy_http`로 설정됩니다.

  AJP를 사용할 경우 사용자 지정 JSON을 정의하여 `apache_tomcat_bind_mod` 속성을 재정의하고 `proxy_ajp`로 설정할 수 있습니다.

`apache2::service` 레시피는 Apache 서비스를 정의하는 OpsWorks Stacks 기본 제공 레시피입니다. 자세한 내용은 OpsWorks Stacks GitHub 리포지토리의 [레시피](https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.4/apache2/recipes/service.rb)를 참조하세요.

`template` 리소스는 `apache_tomcat_bind.conf.erb`를 사용하여 구성 파일을 생성하며, 이 파일의 기본 이름은 `tomcat_bind.conf`입니다. 그리고 리소스는 이 구성 파일을 `['apache']['dir']/.conf.d` 디렉터리에 저장합니다. `['apache']['dir']` 속성은 내장된 `apache2` 속성 파일에 정의되어 있으며, 기본적으로 `/etc/httpd`(Amazon Linux) 또는 `/etc/apache2`(Ubuntu)로 설정됩니다. `template` 리소스가 구성 파일을 생성하거나 변경할 경우 `notifies` 명령이 Apache 서비스 재시작을 예약합니다.

```
<% if node['tomcat']['apache_tomcat_bind_mod'] == 'proxy_ajp' -%>
ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/
ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> ajp://localhost:<%= node['tomcat']['ajp_port'] %>/
<% else %>
ProxyPass <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/
ProxyPassReverse <%= node['tomcat']['apache_tomcat_bind_path'] %> http://localhost:<%= node['tomcat']['port'] %>/
<% end -%>
```

템플릿은 [ProxyPass](https://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypass) 및 [ProxyPassReverse](https://httpd.apache.org/docs/2.0/mod/mod_proxy.html#proxypassreverse) 명령을 사용하여 Apache와 Tomcat 간에 트래픽을 전달하는 데 사용되는 포트를 구성합니다. 두 서버는 동일한 인스턴스에서 실행되므로 localhost URL을 사용할 수 있으며 모두 기본적으로 `http://localhost:8080`으로 설정됩니다.

# Configure 레시피
<a name="create-custom-configure"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 서비스 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

Configure 레시피는 계층의 Configure [수명 주기](workingcookbook-events.md) 이벤트에 할당됩니다. 이 이벤트는 특정 인스턴스가 온라인 상태로 전환되거나 해제될 때마다 스택의 모든 인스턴스에서 발생합니다. 변경 사항에 대응하여 적절히 인스턴스의 구성을 조정하려면 Configure 레시피를 사용합니다. Configure 레시피를 구현할 때 스택 구성 변경이 이 계층과 관계가 없는 인스턴스도 포함할 수 있다는 점을 염두에 두어야 합니다. 이 레시피는 적절히 대응할 수 있어야 합니다. 이는 경우에 따라 아무 작업도 하지 않음을 의미하기도 합니다.

## tomcat::configure
<a name="create-custom-configure-configure"></a>

`tomcat::configure` 레시피는 계층의 Configure 수명 주기 이벤트를 위한 것입니다.

```
include_recipe 'tomcat::context'
# Optional: Trigger a Tomcat restart in case of a configure event, if relevant
# settings in custom JSON have changed (e.g. java_opts/JAVA_OPTS):
#include_recipe 'tomcat::container_config'
```

`tomcat::configure` 레시피는 기본적으로 두 개의 종속 레시피를 실행하는 메타 레시피입니다.

1. `tomcat::context` 레시피는 웹 앱 컨텍스트 구성 파일을 생성합니다.

   이 파일은 애플리케이션이 MySQL 인스턴스와 통신하는 데 사용하는 JDBC 리소스를 구성합니다. 이에 대해서는 다음 섹션에서 설명합니다. Configure 이벤트에 대응하여 이 레시피를 실행할 경우 데이터베이스 계층이 변경되었을 때 웹 앱 컨텍스트 구성 파일을 업데이트할 수 있습니다.

1. `tomcat::container_config` 설정 레시피가 다시 실행되어 컨테이너 구성 변경 사항을 캡처합니다.

이 예제에서는 `include`의 `tomcat::container_config`가 코멘트 아웃됩니다. 사용자 지정 JSON을 사용하여 Tomcat 설정을 수정하려는 경우 이 주석을 제거할 수 있습니다. 그런 다음 Configure 수명 주기 이벤트가 `tomcat::container_config`를 실행합니다. 이는 Tomcat 관련 구성 파일을 업데이트하고([tomcat::container\$1config](create-custom-setup.md#create-custom-setup-config) 섹션 참조) Tomcat 서비스를 재시작합니다.

## tomcat::context
<a name="create-custom-configure-context"></a>

Tomcat 쿡북은 애플리케이션이 [J2EE DataSource](http://docs.oracle.com/javase/tutorial/jdbc/basics/sqldatasources.html) 객체를 사용하여 별도의 인스턴스에서 실행될 수 있는 MySQL 데이터베이스 서버에 액세스하도록 설정합니다. Tomcat에서는 각 애플리케이션에 대해 웹 엡 컨텍스트 구성 파일을 생성 및 설치하여 연결을 활성화할 수 있습니다. 이 파일은 애플리케이션과 애플리케이션이 데이터베이스와 통신하는 데 사용할 JDBC 리소스 간의 관계를 정의합니다. 자세한 정보는 [The Context Container](http://tomcat.apache.org/tomcat-7.0-doc/config/context.html)를 참조하세요.

`tomcat::context` 레시피의 주된 목적은 이 구성 파일을 생성하는 것입니다.

```
include_recipe 'tomcat::service'

node[:deploy].each do |application, deploy|
  context_name = deploy[:document_root].blank? ? application : deploy[:document_root]

  template "context file for #{application} (context name: #{context_name})" do
    path ::File.join(node['tomcat']['catalina_base_dir'], 'Catalina', 'localhost', "#{context_name}.xml")
    source 'webapp_context.xml.erb'
    owner node['tomcat']['user']
    group node['tomcat']['group']
    mode 0640
    backup false
    only_if { node['datasources'][context_name] }
    variables(:resource_name => node['datasources'][context_name], :webapp_name => application)
    notifies :restart, resources(:service => 'tomcat')
  end
end
```

Tomcat OpsWorks 쿡북 속성 외에도이 레시피는 [Stacks가 구성 이벤트와 함께 설치하는 스택 구성 및 배포 속성을](workingcookbook-json.md) 사용합니다. OpsWorks Stacks 서비스는 레시피가 일반적으로 데이터 백을 사용하거나 각 인스턴스에 속성을 검색하여 얻는 정보를 포함하는 속성을 각 인스턴스의 노드 객체에 추가합니다. 이러한 속성에는 스택 구성, 배포된 앱, 사용자가 포함시키기 원하는 사용자 지정 데이터에 대한 세부 정보가 포함됩니다. 레시피는 표준 Chef 노드 구문을 사용하여 스택 구성 및 배포 속성에서 데이터를 가져옵니다. 자세한 내용은 [스택 구성 및 배포 속성](workingcookbook-json.md) 섹션을 참조하세요. Chef 11.10 스택에서는 Chef 검색을 사용하여 스택 구성 및 배포 데이터를 가져올 수도 있습니다. 자세한 내용은 [Chef 검색 사용](workingcookbook-chef11-10.md#workingcookbook-chef11-10-search) 단원을 참조하십시오.

`deploy` 속성은 콘솔 또는 API를 통해 정의되거나 OpsWorks Stacks 서비스에 의해 생성되는 배포 관련 속성을 포함하는 `[:deploy]` 네임스페이스를 나타냅니다. `deploy` 속성에는 배포된 각 앱마다 앱의 짧은 이름으로 명명된 속성이 하나씩 포함됩니다. 각각의 앱 속성에는 문서 루트(`[:deploy][:appname][:document_root]`)와 같이 앱의 특성을 정의하는 속성 세트가 포함됩니다.

`context` 레시피는 먼저 [tomcat::service](create-custom-setup.md#create-custom-setup-service)를 호출하여 서비스가 이 Chef 실행에 대해 정의되도록 합니다. 그런 다음 구성 파일의 이름(`context_name` 확장명 제외)을 표시하는 `.xml` 변수를 정의합니다. 기본 문서 루트를 사용하는 경우, `context_name`이 앱의 짧은 이름으로 설정됩니다. 그렇지 않은 경우 지정된 문서 루트로 설정됩니다. [스택 생성 및 애플리케이션 실행](create-custom-stack.md) 섹션에 설명된 예제는 문서 루트를 `"ROOT"`로 설정합니다. 따라서 컨텍스트는 ROOT이고 구성 파일 이름은 `ROOT.xml`입니다.

이 레시피는 배포된 앱의 목록이 많은 부분을 차지하며, 각 앱에 대해 `webapp_context.xml.erb` 템플릿을 사용하여 컨텍스트 구성 파일을 생성합니다. 예제는 앱을 하나만 배포하지만 `deploy` 속성의 정의는 앱 수와 상관없이 이를 앱 목록으로 처리하도록 요구합니다.

`webapp_context.xml.erb` 템플릿은 운영 체제를 구별하지 않으므로 `templates` 디렉터리의 `default` 하위 디렉터리에 위치합니다.

이 레시피는 다음과 같이 구성 파일을 생성합니다.
+ 기본 속성 값을 사용할 경우 구성 파일 이름은 `context_name.xml`로 설정되고 `/etc/tomcat6/Catalina/localhost/` 디렉터리에 설치됩니다.

  스택 구성 속성의 `['datasources']` 노드에는 각각 연결된 애플리케이션이 데이터베이스와 통신하는 데 사용할 JDBC 데이터 리소스에 컨텍스트 이름을 매핑하는 속성이 하나 이상 포함됩니다. 노드 및 그 콘텐츠는 [스택 생성 및 애플리케이션 실행](create-custom-stack.md) 섹션에 설명된 대로 스택을 생성할 때 사용자 지정 JSON을 통해 정의됩니다. 예제에는 ROOT 컨텍스트 이름을 jdbc/mydb라는 JDBC 리소스와 연결하는 속성 하나가 있습니다.
+ 기본 속성 값을 사용하면 파일의 사용자 및 그룹 모두 Tomcat 패키지에 의해 설정됩니다. `tomcat`(Amazon Linux) 또는 `tomcat6`(Ubuntu).
+ `template` 리소스는 `['datasources']` 노드가 존재하고 `context_name` 속성을 포함하는 경우에만 구성 파일을 생성합니다.
+ `template` 리소스는 `resource_name` 및 `webapp_name`, 두 개의 변수를 정의합니다.

  `resource_name`은 `context_name`과 연결된 리소스 이름으로 설정되고, `webapp_name`은 앱의 짧은 이름으로 설정됩니다.
+ 템플릿 리소스는 Tomcat 서비스를 재시작하여 변경 사항을 로드하고 활성화합니다.

`webapp_context.xml.erb` 템플릿은 자체 속성 세트를 갖는 `Context` 요소를 포함하는 `Resource` 요소로 구성됩니다.

`Resource` 속성은 컨텍스트 구성의 특성을 정의합니다.
+ **name** - JDBC 리소스 이름. `tomcat::context`에서 정의된 `resource_name` 값으로 설정됩니다.

  예제에서는 리소스 이름이 jdbc/mydb로 설정됩니다.
+ **auth** 및 **type** - 이들은 JDBC `DataSource` 연결의 표준 설정입니다.
+ **maxActive**, **maxIdle** 및 **maxWait** - 최대 활성 연결 수, 최대 유휴 연결 수 및 연결이 반환되기까지 최대 대기 시간.
+ **username** 및 **password** - 데이터베이스의 사용자 이름 및 암호. `deploy` 속성에서 가져옵니다.
+ **driverClassName** - JDBC 드라이버의 클래스 이름. MySQL 드라이버로 설정됩니다.
+ **url** - 연결 URL.

  접두사는 데이터베이스에 따라 다릅니다. MySQL의 경우 `jdbc:mysql`, Postgres의 경우 `jdbc:postgresql`, SQL Server의 경우 `jdbc:sqlserver`로 설정되어야 합니다. 예제에서는 URL을 `jdbc:mysql://host_IP_Address:3306:simplejsp`로 설정합니다. 여기서 *simplejsp*는 앱의 짧은 이름입니다.
+ **factory** - `DataSource` 팩토리. MySQL 데이터베이스의 경우 필수입니다.

이 구성 파일에 대한 자세한 정보는 Tomcat wiki의 [Using DataSources](http://wiki.apache.org/tomcat/UsingDataSources) 항목 단원을 참조하세요.

# Deploy 레시피
<a name="create-custom-deploy"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 서비스 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

Deploy 레시피는 계층의 Deploy [수명 주기](workingcookbook-events.md) 이벤트에 할당됩니다. 이벤트를 지정된 인스턴스로만 선택적으로 제한할 수 있지만 일반적으로 앱을 배포할 때마다 스택의 모든 인스턴스에서 발생합니다. OpsWorks 스택은 Setup 레시피가 완료된 후 새 인스턴스에서 Deploy 레시피도 실행합니다. Deploy 레시피의 주된 목적은 코드와 관련 파일을 리포지토리에서 애플리케이션 서버 계층의 인스턴스에 배포하는 것입니다. 하지만 다른 계층에서도 Deploy 레시피를 실행하는 경우가 종종 있습니다. 그러면 예를 들어 해당 계층의 인스턴스가 구성을 업데이트하여 새로 개발된 앱을 수용할 수 있습니다. Deploy 레시피를 구현할 때 Deploy 이벤트가 반드시 앱이 인스턴스에 배포되는 것을 의미하지는 않음을 염두에 두어야 합니다. 단지 인스턴스가 필요한 업데이트를 할 수 있도록 스택 내 다른 인스턴스에 앱이 배포되고 있다는 알림일 수도 있습니다. 이 레시피는 적절히 대응할 수 있어야 합니다. 이는 아무 작업도 하지 않음을 의미하기도 합니다.

OpsWorks Stacks는 표준 앱 유형의 앱을 해당 내장 애플리케이션 서버 계층에 자동으로 배포합니다. 앱을 사용자 지정 계층에 배포하려면 앱의 파일을 리포지토리에서 인스턴스 내 적절한 위치로 다운로드하는 사용자 지정 Deploy 레시피를 구현해야 합니다. 하지만 내장 [배포 쿡북](https://github.com/aws/opsworks-cookbooks/tree/release-chef-11.4/deploy)을 사용하여 배포의 일부 측면을 처리함으로써 작성할 코드의 양을 줄일 수도 있습니다. 예를 들어 파일을 지원되는 리포지토리 중 하나에 저장할 경우 내장 쿡북이 리포지토리에서 계층의 인스턴스로 파일을 다운로드하는 세부 작업을 처리할 수 있습니다.

`tomcat::deploy` 레시피는 Deploy 수명 주기 이벤트에 할당됩니다.

```
include_recipe 'deploy'

node[:deploy].each do |application, deploy|
  opsworks_deploy_dir do
    user deploy[:user]
    group deploy[:group]
    path deploy[:deploy_to]
  end

  opsworks_deploy do
    deploy_data deploy
    app application
  end
...
```

`tomcat::deploy` 레시피는 애플리케이션에 고유하지 않은 배포에 대해 내장 배포 쿡북을 사용합니다. `deploy` 레시피(내장 `deploy::default` 레시피의 약칭)는 `deploy` 속성의 데이터를 기반으로 사용자, 그룹 등을 설정하는 세부 작업을 처리하는 내장 레시피입니다.

이 레시피는 두 개의 내장 Chef 정의 `opsworks_deploy_dir` 및 `opworks_deploy`를 사용하여 애플리케이션을 설치합니다.

`opsworks_deploy_dir` 정의는 앱의 배포 JSON에 포함된 데이터를 기반으로 디렉터리 구조를 설정합니다. 정의는 기본적으로 리소스 정의를 패키징하는 편리한 방법으로, `definitions` 디렉터리에 위치합니다. 레시피는 사용자 정의를 리소스와 거의 비슷하게 사용할 수 있지만, 정의 자체에는 연결된 공급자가 없고 정의에 포함된 리소스만 있습니다. 레시피에서 변수를 정의할 수 있습니다. 그러면 해당 변수가 기본 리소스 정의로 전달됩니다. `tomcat::deploy` 레시피는 배포 JSON의 데이터를 기반으로 `user`, `group` 및 `path` 변수를 설정합니다. 이들 변수는 정의의 디렉터리를 관리하는 [디렉터리 리소스](https://docs.chef.io/chef/resources.html#directory)로 전달됩니다.

**참고**  
배포된 앱의 사용자 및 그룹은 `[:opsworks][:deploy_user][:user]` 및 `[:opsworks][:deploy_user][:group]` 속성을 통해 결정되며, 각 속성은 [내장 배포 쿡북의 `deploy.rb` 속성 파일](https://github.com/aws/opsworks-cookbooks/blob/release-chef-11.4/deploy/attributes/deploy.rb)에서 정의됩니다. `[:opsworks][:deploy_user][:user]`의 기본값은 `deploy`입니다. `[:opsworks][:deploy_user][:group]`의 기본값은 인스턴스의 운영 체제에 따라 다릅니다.  
Ubuntu 인스턴스의 경우, 기본 그룹은 `www-data`입니다.
Nginx와 Unicorn을 사용하는 Rails 앱 서버 계층에 속하는 Amazon Linux 인스턴스의 경우, 기본 그룹은 `nginx`입니다.
다른 모든 Amazon Linux 인스턴스의 경우, 기본 그룹은 `apache`입니다.
사용자 지정 JSON 또는 사용자 지정 속성 파일을 사용하여 해당 속성을 재정의하면 설정을 변경할 수 있습니다. 자세한 내용은 [속성 재정의](workingcookbook-attributes.md) 섹션을 참조하세요.

다른 정의 `opsworks_deploy`는 `deploy` 속성에 포함된 데이터를 기반으로 앱의 코드와 관련 파일을 리포지토리에서 체크아웃하고 인스턴스에 배포하는 세부 작업을 처리합니다. 모든 앱 유형에서 이 정의를 사용할 수 있습니다. 디렉터리 이름과 같은 배포 세부 정보는 콘솔 또는 API를 통해 지정되며 `deploy` 속성에 포함됩니다. 하지만 `opsworks_deploy`는 Git, 하위 버전, S3 및 HTTP 등 네 개의 [지원되는 리포지토리 유형](workingcookbook-installingcustom-repo.md)에서만 사용할 수 있습니다. 다른 리포지토리 유형을 사용하려면 이 코드를 직접 구현해야 합니다.

앱의 파일은 Tomcat `webapps` 디렉터리에 설치합니다. 일반적인 방법은 파일을 `webapps`에 직접 복사하는 것입니다. 그러나 OpsWorks Stacks 배포는 인스턴스에 최대 5개의 앱 버전을 유지하도록 설계되었으므로 필요한 경우 이전 버전으로 롤백할 수 있습니다. 따라서 OpsWorks Stacks는 다음을 수행합니다.

1. 이름에 타임스탬프가 포함된 고유 디렉터리(예: `/srv/www/my_1st_jsp/releases/20130731141527`)에 앱을 배포합니다.

1. 이 고유 디렉터리에 대한 symlink를 생성하고 `current`로 명명합니다(예: `/srv/www/my_1st_jsp/current`).

1. 이미 존재하지 않으면 `webapps` 디렉터리에서 2단계에서 생성된 `current` symlink까지의 symlink를 생성합니다.

이전 버전으로 롤백해야 할 경우 `current` symlink를 해당하는 타임스탬프가 있는 고유 디렉터리를 가리키도록 수정합니다(예를 들어 `/srv/www/my_1st_jsp/current`의 링크 대상 변경).

`tomcat::deploy`의 중간 부분은 symlink를 설정합니다.

```
  ...
  current_dir = ::File.join(deploy[:deploy_to], 'current')
  webapp_dir = ::File.join(node['tomcat']['webapps_base_dir'], deploy[:document_root].blank? ? application : deploy[:document_root])

  # opsworks_deploy creates some stub dirs, which are not needed for typical webapps
  ruby_block "remove unnecessary directory entries in #{current_dir}" do
    block do
      node['tomcat']['webapps_dir_entries_to_delete'].each do |dir_entry|
        ::FileUtils.rm_rf(::File.join(current_dir, dir_entry), :secure => true)
      end
    end
  end

  link webapp_dir do
    to current_dir
    action :create
  end
  ...
```

이 레시피는 먼저 두 개의 변수 `current_dir` 및 `webapp_dir`을 생성하여 각각 `current` 및 `webapp` 디렉터리를 표시합니다. 그런 다음 `link` 리소스를 사용하여 `webapp_dir`를 `current_dir`에 링크합니다. OpsWorks Stacks `deploy::default` 레시피는이 예제에 필요하지 않은 일부 스텁 디렉터리를 생성하므로 발췌문의 중간 부분이 이를 제거합니다.

`tomcat::deploy`의 마지막 부분은 필요할 경우 Tomcat 서비스를 재시작합니다.

```
  ...
  include_recipe 'tomcat::service'

  execute 'trigger tomcat service restart' do
    command '/bin/true'
    not_if { node['tomcat']['auto_deploy'].to_s == 'true' }
    notifies :restart, resources(:service => 'tomcat')
  end
end

include_recipe 'tomcat::context'
```

이 레시피는 먼저 `tomcat::service`를 실행하여 서비스가 이 Chef 실행에 대해 정의되도록 합니다. 그런 다음 [실행 리소스](https://docs.chef.io/chef/resources.html#execute)를 사용하여 `['tomcat']['auto_deploy']`가 `'true'`로 설정된 경우에만 서비스를 재시작하라고 알립니다. 그렇지 않은 경우에는 Tomcat이 `webapps` 디렉터리의 변경 사항을 수신 대기합니다. 그러므로 명시적 Tomcat 서비스 재시작은 필요하지 않습니다.

**참고**  
`execute` 리소스가 실제로는 아무 것도 실행하지 않습니다. `/bin/true`는 단지 성공 코드를 반환하는 더미 shell 스크립트입니다. 여기서는 단지 재시작 알림을 생성하는 간편한 방법으로 사용됩니다. 앞서 언급한 대로, 알림을 사용하면 서비스가 너무 빈번히 재시작되지 않습니다.

마지막으로, `tomcat::deploy`는 `tomcat::context`를 실행합니다. 이는 백 엔드 데이터베이스가 변경된 경우 웹 앱 컨텍스트 구성 파일을 업데이트합니다.

# 스택 생성 및 애플리케이션 실행
<a name="create-custom-stack"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 서비스 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

이 섹션은 SimpleJSP라는 간단한 Java 서버 페이지(JSP) 애플리케이션을 실행하는 기본적인 스택 설정을 구현하기 위해 Tomcat 쿡북을 사용하는 방법을 보여줍니다. 스택은 TomCustom이라는 Tomcat 기반 사용자 지정 계층과 MySQL 계층으로 구성됩니다. SimpleJSP는 TomCustom에 배포되고 MySQL 데이터베이스로부터 일부 정보를 표시합니다. OpsWorks Stacks 사용 방법의 기본 사항에 익숙하지 않은 경우 먼저를 읽어야 합니다[Chef 11 Linux 스택 시작하기](gettingstarted.md).

## SimpleJSP 애플리케이션
<a name="create-custom-stack-jsp"></a>

SimpleJSP 애플리케이션은 데이터베이스 연결을 설정하고 스택의 MySQL 데이터베이스에서 데이터를 검색하는 방법의 기초를 보여줍니다.

```
<html>
  <head>
    <title>DB Access</title>
  </head>
  <body>
    <%@ page language="java" import="java.sql.*,javax.naming.*,javax.sql.*" %>
    <%
      StringBuffer output = new StringBuffer();
      DataSource ds = null;
      Connection con = null;
      Statement stmt = null;
      ResultSet rs = null;
      try {
        Context initCtx = new InitialContext();
        ds = (DataSource) initCtx.lookup("java:comp/env/jdbc/mydb");
        con = ds.getConnection();
        output.append("Databases found:<br>");
        stmt = con.createStatement();
        rs = stmt.executeQuery("show databases");
        while (rs.next()) {
          output.append(rs.getString(1));
          output.append("<br>");
        }
      }
      catch (Exception e) {
        output.append("Exception: ");
        output.append(e.getMessage());
        output.append("<br>");
      }
      finally {
        try {
          if (rs != null) {
            rs.close();
          }
          if (stmt != null) {
            stmt.close();
          }
          if (con != null) {
            con.close();
          }
        }
        catch (Exception e) {
          output.append("Exception (during close of connection): ");
          output.append(e.getMessage());
          output.append("<br>");
        }
      }
    %>
    <%= output.toString() %>
  </body>
</html>
```

SimpleJSP는 `DataSource` 객체를 사용하여 MySQL 데이터베이스와 통신합니다. Tomcat은 [웹 앱 컨텍스트 구성 파일](create-custom-configure.md#create-custom-configure-context)의 데이터를 사용하여 `DataSource` 객체를 생성 및 초기화하고 논리적 이름에 바인딩합니다. 그런 다음 이 논리적 이름을 Java Naming and Directory Interface(JNDI) 이름 서비스에 등록합니다. `DataSource` 객체의 인스턴스를 가져오려면 `InitialContext` 객체를 생성하고 리소스의 논리적 이름을 객체의 `lookup` 메서드로 전달합니다. 이 메서드가 해당 객체를 검색합니다. SimpleJSP 예제의 논리적 이름 `java:comp/env/jdbc/mydb`는 다음 요소로 구성됩니다.
+ 이름의 나머지 부분과 콜론(:)으로 구분되는 루트 네임스페이스 `java`.
+ 슬래시(/)로 구분되는 추가 네임스페이스.

  Tomcat은 자동으로 리소스를 `comp/env` 네임스페이스에 추가합니다.
+ 웹 앱 컨텍스트 구성 파일에서 정의되고 슬래시로 네임스페이스와 구분되는 리소스 이름.

  이 예제에서는 리소스 이름이 `jdbc/mydb`입니다.

데이터베이스와 연결을 설정하기 위해 SimpleJSP는 다음을 수행합니다.

1. `DataSource` 객체의 `getConnection` 메서드를 호출합니다. 이 메서드는 `Connection` 객체를 반환홥니다.

1. `Connection` 객체의 `createStatement` 메서드를 호출하여 데이터베이스와 통신하는 데 사용할 `Statement` 객체를 생성합니다.

1. `Statement` 메서드를 호출하여 데이터베이스와 통신합니다.

   SimpleJSP는 `executeQuery`를 호출하여 서버의 데이터베이스를 나열하는 SHOW DATABASES 쿼리를 실행합니다.

`executeQuery` 메서드는 쿼리 결과를 포함하는 `ResultSet` 객체를 반환합니다. SimpleJSP는 반환된 `ResultSet` 객체에서 데이터베이스 이름을 가져오고 이들을 연결하여 출력 문자열을 생성합니다. 마지막으로 예제는 `ResultSet`, `Statement` 및 `Connection` 객체를 닫습니다. JSP 및 JDBC에 대한 자세한 정보는 각각 [JavaServer Pages Technology](http://docs.oracle.com/javaee/5/tutorial/doc/bnagx.html) 및 [JDBC Basics](http://docs.oracle.com/javase/tutorial/jdbc/basics/)를 참조하세요.

SimpleJSP를 스택에서 사용하려면 리포지토리에 배치해야 합니다. 지원되는 리포지토리를 모두 사용할 수 있지만, 다음 섹션에서 설명하는 예제 스택에서 SimpleJSP를 사용하려면 퍼블릭 S3 아카이브에 배치해야 합니다. 다른 표준 리포지토리를 사용하는 방법에 대한 자세한 정보는 [쿡북 리포지토리](workingcookbook-installingcustom-repo.md) 단원을 참조하세요.

**S3 아카이브 리포지토리에 SimpleJSP를 저장하려면**

1. 예제 코드를 `simplejsp.jsp` 파일에 복사한 다음 이 파일을 `simplejsp` 디렉터리에 저장합니다.

1. `simplejsp` 디렉터리의 `.zip` 아카이브를 생성합니다.

1. 퍼블릭 Amazon S3 버킷을 만들고, `simplejsp.zip`을 이 버킷에 업로드하고, 이 파일을 퍼블릭으로 설정합니다.

   이 작업을 수행하는 방법에 대한 자세한 설명은 [Amazon Simple Storage Service 시작하기](https://docs.aws.amazon.com/AmazonS3/latest/gsg/GetStartedWithS3.html)를 참조하세요.

## 스택 생성
<a name="create-custom-stack-stack"></a>

SimpleJSP를 실행하려면 다음 계층이 포함된 스택이 필요합니다.
+ 백 엔드 MySQL 서버를 지원하는 MySQL 계층.
+ Tomcat 쿡북을 사용하여 Tomcat 서버 인스턴스를 지원하는 사용자 지정 계층.

**스택을 생성하는 방법**

1.  OpsWorks 스택 대시보드에서 **스택 추가**를 클릭하여 새 스택을 생성하고 **고급 >>**를 클릭하여 모든 옵션을 표시합니다. 다음과 같이 스택을 구성합니다.
   + **이름** - 사용자 정의 스택 이름. 이 예에서는 TomStack을 사용합니다.
   + **사용자 지정 Chef 쿡북 사용** - 토글을 **예**로 설정합니다. 그러면 몇 가지 추가 옵션이 표시됩니다.
   + **리포지토리 유형** - Git
   + **리포지토리 URL** – `git://github.com/amazonwebservices/opsworks-example-cookbooks.git`.
   + **Custom Chef JSON** - 다음 JSON을 추가합니다.

     ```
     {
       "tomcat": {
         "base_version": 7,
         "java_opts": "-Djava.awt.headless=true -Xmx256m"
       },
       "datasources": {
         "ROOT": "jdbc/mydb"
       }
     }
     ```

   나머지 옵션의 경우 기본값을 수락할 수 있습니다.

   사용자 지정 JSON에서는 다음 작업을 수행합니다.
   + Tomcat 쿡북의 `['base_version']` 속성을 재정의해 Tomcat 버전을 7로 설정합니다. 기본값은 6입니다.
   + Tomcat 쿡북의 `['java_opts']` 속성을 재정의해 인스턴스가 헤드리스가 되도록 지정하고 JVM 최대 힙 크기를 256MB로 설정합니다. 기본값은 Amazon Linux를 실행하는 인스턴스에 대해 옵션을 설정하지 않는 것입니다.
   + `['datasources]` 속성 값을 지정합니다. 이 속성 값은 [tomcat::context](create-custom-configure.md#create-custom-configure-context) 단원에서 설명하는 것처럼 JDBC 리소스 이름(jdbc/mydb)을 웹 앱 컨텍스트 이름(ROOT)에 할당합니다.

     이 마지막 속성에는 기본값이 없습니다. 따라서 사용자 지정 JSON을 사용하여 값을 설정해야 합니다.  
![\[Configuration Management interface showing Chef version options and custom JSON input field.\]](http://docs.aws.amazon.com/ko_kr/opsworks/latest/userguide/images/tom_add_stack.png)

1. [**계층 추가**]를 클릭합니다. [**계층 유형**]으로 **MySQL**을 선택합니다. 그런 다음 [**계층 추가**]를 클릭합니다.

1. 탐색 창에서 [**인스턴스**]를 클릭한 다음 [**인스턴스 추가**]를 클릭합니다. **인스턴스 추가**를 클릭하고 기본값을 수락합니다. 인스턴스에 해당하는 라인에서 [**시작**]을 클릭합니다.

1. [**계층**] 페이지로 돌아가 [**\$1 계층**]을 클릭하여 계층을 추가합니다. **Layer type(계층 유형)**으로 **사용자 지정**을 클릭합니다. 이 예제에서는 계층 이름 및 짧은 이름으로 각각 **TomCustom** 및 **tomcustom**을 사용합니다.  
![\[Add Layer form with Custom layer type, Name, and Short name fields for creating a customized layer.\]](http://docs.aws.amazon.com/ko_kr/opsworks/latest/userguide/images/tom_add_custom_layer.png)

1. [**계층**] 페이지에서 사용자 지정 계층으로 [**레시피**]를 클릭하고 [**편집**]을 클릭합니다. [**사용자 지정 Chef 레시피**]에서 다음과 같이 계층의 수명 주기 이벤트에 Tomcat 쿡북 레시피를 할당합니다.
   + **설정**에 **tomcat::setup**을 입력하고 **\$1**를 클릭합니다.
   + **구성**에 **tomcat::configure**을 입력하고 **\$1**를 클릭합니다.
   + **배포**에 **tomcat::deploy**를 입력하고 **\$1**를 클릭합니다. 그런 다음 **저장**을 클릭합니다.

     .  
![\[Custom Chef Recipes interface showing setup, configure, and deploy steps with options.\]](http://docs.aws.amazon.com/ko_kr/opsworks/latest/userguide/images/tom_events.png)

1. 탐색 창에서 [**앱**]을 클릭한 다음 [**앱 추가**]를 클릭합니다. 다음 옵션을 지정하고 [**앱 추가**]를 클릭합니다.
   + **이름** - 앱의 이름입니다. 예제에서는 SimpleJSP를 사용하며 OpsWorks Stacks에서 생성된 짧은 이름은 simplejsp입니다.
   + **앱 유형** - 이 옵션은 **기타**로 설정합니다.

     OpsWorks Stacks는 연결된 서버 인스턴스에 표준 앱 유형을 자동으로 배포합니다. **앱 유형**을 기타로 설정하면 OpsWorks Stacks에서는 Deploy 레시피를 실행하고 이 레시피에 따라 배포가 처리되도록 합니다.
   + [**문서 루트**] - 이 옵션은 **ROOT**으로 설정합니다.

     [**문서 루트**] 값은 컨텍스트 이름을 지정합니다.
   + **리포지토리 유형** - 이 옵션은 **S3 아카이브**로 설정합니다.
   + **리포지토리 URL** - 이 옵션은 앞에서 생성한 앱의 Amazon S3 URL로 설정합니다.

   다른 옵션에는 기본 설정을 사용합니다.  
![\[Application settings form with fields for name, app type, document root, and source details.\]](http://docs.aws.amazon.com/ko_kr/opsworks/latest/userguide/images/tom_app.png)

1. **인스턴스** 페이지를 사용하여 TomCustom 계층에 인스턴스를 추가하고 시작합니다. OpsWorks 스택은 Setup 레시피가 완료된 후 새 인스턴스에서 Deploy 레시피를 자동으로 실행하므로 인스턴스를 시작하면 SimpleJSP도 배포됩니다.

1. TomCustom 인스턴스가 온라인 상태이면 [**인스턴스**] 페이지에서 인스턴스 이름을 클릭하여 세부 정보를 확인합니다. 퍼블릭 IP 주소를 복사합니다. 그런 다음 URL을 http://*publicIP*/tc/*appname.jsp* 형식으로 구성합니다. 예를 들어, 이 URL은 **http://50.218.191.172/tc/simplejsp.jsp**와 같습니다.
**참고**  
Tomcat에 요청을 전달하는 Apache URL은 기본 `['tomcat']['apache_tomcat_bind_path']` 속성이 `/tc/`로 설정되어 있습니다. SimpleJSP 문서 루트는 특수값인 `ROOT`로 설정되어 있으며 `/`로 해석됩니다. 따라서 URL은 ".../tc/simplejsp.jsp"입니다.

1. 이전 단계의 URL을 브라우저에 붙여 넣습니다. 다음과 같은 모양이어야 합니다.

   ```
   Databases found:
   information_schema
   simplejsp
   test
   ```
**참고**  
스택에 MySQL 인스턴스가 있는 경우 OpsWorks Stacks는 앱의 짧은 이름으로 이름이 지정된 각 앱에 대한 데이터베이스를 자동으로 생성합니다.

# 스택 구성 및 배포 속성
<a name="workingcookbook-json"></a>

**중요**  
이 AWS OpsWorks Stacks 서비스는 2024년 5월 26일에 서비스 수명이 종료되었으며 신규 및 기존 고객 모두에서 비활성화되었습니다. 가능한 한 빨리 워크로드를 다른 솔루션으로 마이그레이션하는 것이 좋습니다. 마이그레이션에 대한 질문이 있는 경우 [AWS re:Post](https://repost.aws/) 또는 [AWS Premium Support](https://aws.amazon.com/support)를 통해 AWS Support 팀에 문의하세요.

 OpsWorks Stacks가 인스턴스에서 예를 들어 수명 주기 배포 이벤트에 대한 응답으로 배포 명령과 같은 명령을 실행하면 스택의 현재 구성을 설명하는 속성 집합이 인스턴스의 노드 객체에 추가됩니다. 배포 이벤트 및 [레시피 스택 명령 실행](workingstacks-commands.md)의 경우 OpsWorks Stacks는 몇 가지 추가 배포 정보를 제공하는 배포 속성을 설치합니다. 노드 객체에 대한 자세한 정보는 [속성 재정의](workingcookbook-attributes.md) 단원을 참조하세요. 정규화된 도메인 이름을 포함하여 일반적으로 사용되는 스택 구성 및 배포 속성의 목록은 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 [내장 쿡북 속성](attributes-recipes.md)를 참조하세요.

**참고**  
Linux 스택에서는 에이전트 CLI의 [get\$1json 명령](agent-json.md)을 사용하여 JSON 객체로 형식 지정된 이러한 속성의 완전한 목록을 가져올 수 있습니다.

다음 섹션에서는 다음으로 구성된 간단한 스택의 Configure 이벤트 및 Deploy 이벤트에 연결된 속성을 보여 줍니다.
+ 두 개의 인스턴스가 있는 PHP 앱 서버 계층
+ 1개의 인스턴스가 포함된 HAProxy 계층

예제는 PHP 앱 서버 인스턴스 중 하나인 **php-app1**의 예제입니다. 편의상 속성은 JSON 객체로 형식이 지정되어 있습니다. 객체의 구조는 속성의 정규화된 이름에 매핑됩니다. 예를 들어 `node[:opsworks][:ruby_version]` 속성은 다음과 같이 JSON 표시로 나타납니다.

```
{
  "opsworks": {
    ...
    "ruby_version": "1.8.7",
    ...
  }
}
```

**Topics**
+ [Configure 속성](#workingcookbook-json-configure)
+ [배포 속성](#workingcookbook-json-deploy)

## Configure 속성
<a name="workingcookbook-json-configure"></a>

다음 JSON 객체는 인스턴스가 온라인 상태가 되거나 오프라인 상태가 될 때 스택의 모든 인스턴스에서 발생하는 Configure 이벤트의 속성을 보여 줍니다. 속성에는 내장 스택 구성 속성과 이벤트 전에 스택에 대해 구성된 [사용자 지정 JSON 속성](workingstacks-json.md)(이 예제에는 없음)이 포함됩니다. 속성은 길이를 위해 편집되었습니다. 다양한 속성에 대한 상세한 설명은 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 [내장 쿡북 속성](attributes-recipes.md)를 참조하세요.

```
{
  "opsworks": {
    "layers": {
      "php-app": {
        "id": "4a2a56c8-f909-4b39-81f8-556536d20648",
        "instances": {
          "php-app2": {
            "elastic_ip": null,
            "region": "us-west-2",
            "booted_at": "2013-02-26T20:41:10+00:00",
            "ip": "192.0.2.0",
            "aws_instance_id": "i-34037f06",
            "availability_zone": "us-west-2a",
            "instance_type": "c1.medium",
            "private_dns_name": "ip-10-252-0-203.us-west-2.compute.internal",
            "private_ip": "10.252.0.203",
            "created_at": "2013-02-26T20:39:39+00:00",
            "status": "online",
            "backends": 8,
            "public_dns_name": "ec2-192-0-2-0.us-west-2.compute.amazonaws.com"
          },
          "php-app1": {
            ...
          }
        },
        "name": "PHP Application Server"
      },
      "lb": {
        "id": "15c86142-d836-4191-860f-f4d310440f14",
        "instances": {
          "lb1": {
           ...
          }
        },
        "name": "Load Balancer"
      }
    },
    "agent_version": "104",
    "applications": [

    ],
    "stack": {
      "name": "MyStack"
    },
    "ruby_version": "1.8.7",
    "sent_at": 1361911623,
    "ruby_stack": "ruby_enterprise",
    "instance": {
      "layers": [
        "php-app"
      ],
      "region": "us-west-2",
      "ip": "192.0.2.0",
      "id": "45ef378d-b87c-42be-a1b9-b67c48edafd4",
      "aws_instance_id": "i-32037f00",
      "availability_zone": "us-west-2a",
      "private_dns_name": "ip-10-252-84-253.us-west-2.compute.internal",
      "instance_type": "c1.medium",
      "hostname": "php-app1",
      "private_ip": "10.252.84.253",
      "backends": 8,
      "architecture": "i386",
      "public_dns_name": "ec2-192-0-2-0.us-west-2.compute.amazonaws.com"
    },
    "activity": "configure",
    "rails_stack": {
      "name": null
    },
    "deployment": null,
    "valid_client_activities": [
      "reboot",
      "stop",
      "setup",
      "configure",
      "update_dependencies",
      "install_dependencies",
      "update_custom_cookbooks",
      "execute_recipes"
    ]
  },
  "opsworks_custom_cookbooks": {
    "recipes": [

    ],
    "enabled": false
  },
  "recipes": [
    "opsworks_custom_cookbooks::load",
    "opsworks_ganglia::configure-client",
    "ssh_users",
    "agent_version",
    "mod_php5_apache2::php",
    "php::configure",
    "opsworks_stack_state_sync",
    "opsworks_custom_cookbooks::execute",
    "test_suite",
    "opsworks_cleanup"
  ],
  "opsworks_rubygems": {
    "version": "1.8.24"
  },
  "ssh_users": {
  },
  "opsworks_bundler": {
    "manage_package": null,
    "version": "1.0.10"
  },
  "deploy": {
  }
}
```

대부분의 정보는 흔히 네임스페이스라고 하는 `opsworks` 속성 아래에 있습니다. 다음 목록은 주요 속성을 설명합니다.
+ `layers` 속성 - 각각 스택의 계층 중 하나의 구성을 설명하는 속성의 집합.

  계층은 짧은 이름(이 예제의 경우, `php-app` 및 `lb`)으로 식별됩니다. 기타 계층의 짧은 이름에 대한 자세한 정보는 [OpsWorks Stacks 계층 참조](layers.md)를 참조하세요.
+ `instances` 속성 - 모든 계층에는 인스턴스의 짧은 이름으로 명명된, 계층의 온라인 인스턴스 각각의 속성을 포함하는 `instances` 요소가 있습니다.

  PHP 앱 서버 계층에는 `php-app1`과 `php-app2`라는 2개의 인스턴스가 있습니다. HAProxy 계층에는 1개의 인스턴스(`lb1`)가 있습니다.
**참고**  
`instances` 요소에는 특정 스택 및 배포 속성이 생성될 때 온라인 상태인 인스턴스만이 포함됩니다.
+ 인스턴스 속성 - 각각의 인스턴스 속성에는 인스턴스의 프라이빗 IP 주소와 프라이빗 DNS 이름 등 인스턴스를 특징짓는 속성 집합이 포함됩니다. 간결하게 하기 위해 예제에서는 `php-app2` 속성만 자세히 표시합니다. 나머지 속성에 포함된 정보도 비슷합니다.
+ `applications` – 배포된 앱의 목록(이 예제에서는 사용되지 않음).
+ `stack` - 스택 이름(이 예제에서는 `MyStack`).
+ `instance` - 이 속성들이 설치되는 인스턴스(이 예제에서는 `php-app1`). 레시피는 이 속성을 사용하여 인스턴스의 퍼블릭 IP 주소 등 레시피가 실행되고 있는 인스턴스에 대한 정보를 얻을 수 있습니다.
+ `activity` – 속성을 생성한 활동(이 예제에서는 Configure 이벤트).
+ `rails_stack` – Rails 앱 서버 계층을 포함하는 스택의 Rails 스택.
+ `deployment` – 이 속성들이 배포에 연결되어 있는지 여부. 이 예제에서는 Configure 이벤트에 연결되므로 `null`로 설정되어 있습니다.
+ `valid_client_activities` – 유효한 클라이언트 활동의 목록.

`opsworks` 속성 뒤에는 다음을 포함한 그 밖의 몇몇 최상위 속성이 옵니다.
+ `opsworks_custom_cookbooks` – 사용자 지정 쿡북이 활성화되었는지 여부. 활성화된 경우, 이 속성에는 사용자 지정 레시피 목록이 포함됩니다.
+ `recipes` – 이 활동에 의해 실행된 레시피.
+ `opsworks_rubygems` – 인스턴스의 RubyGems 버전.
+ `ssh_users` – SSH 사용자 목록(이 예제에는 없음).
+ `opsworks_bundler` – bundler 버전 및 활성화 여부.
+ `deploy` – 배포 활동에 대한 정보(이 예제에는 없음).

## 배포 속성
<a name="workingcookbook-json-deploy"></a>

Deploy 이벤트 또는 [레시피 실행 스택 명령](workingstacks-commands.md)의 속성은 내장 스택 구성 및 배포 속성과 사용자 지정 스택 또는 배포 속성(이 예제에는 없음)으로 구성됩니다. 다음 JSON 객체는 SimplePHP 앱을 스택의 PHP 인스턴스에 배포한 배포 이벤트에 연결된 [**php-app1**]의 속성을 보여 줍니다. 객체 대부분은 앞 섹션에서 설명한 Configure 이벤트의 속성과 비슷한 스택 구성 속성으로 구성되므로 예제에서는 주로 배포에 고유한 속성에 집중합니다. 다양한 속성에 대한 상세한 설명은 [스택 구성 및 배포 속성: Linux](attributes-json-linux.md) 및 [내장 쿡북 속성](attributes-recipes.md)를 참조하세요.

```
{
   ...
  "opsworks": {
    ...
    "activity": "deploy",
    "applications": [
      {
        "slug_name": "simplephp",
        "name": "SimplePHP",
        "application_type": "php"
      }
    ],
    "deployment": "5e6242d7-8111-40ee-bddb-00de064ab18f",
    ...
  },
  ...
{
  "ssh_users": {
  },
  "deploy": {
    "simplephpapp": {
      "application": "simplephpapp",
      "application_type": "php",
      "environment_variables": {
        "USER_ID": "168424",
        "USER_KEY": "somepassword"
      },
      "auto_bundle_on_deploy": true,
      "deploy_to": "/srv/www/simplephpapp",
      "deploying_user": "arn:aws:iam::123456789012:user/guysm",
      "document_root": null,
      "domains": [
        "simplephpapp"
      ],
      "migrate": false,
      "mounted_at": null,
      "rails_env": null,
      "restart_command": "echo 'restarting app'",
      "sleep_before_restart": 0,
      "ssl_support": false,
      "ssl_certificate": null,
      "ssl_certificate_key": null,
      "ssl_certificate_ca": null,
      "scm": {
        "scm_type": "git",
        "repository": "git://github.com/amazonwebservices/opsworks-demo-php-simple-app.git",
        "revision": "version1",
        "ssh_key": null,
        "user": null,
        "password": null
      },
      "symlink_before_migrate": {
        "config/opsworks.php": "opsworks.php"
      },
      "symlinks": {
      },
      "database": {
      },
      "memcached": {
        "host": null,
        "port": 11211
      },
      "stack": {
        "needs_reload": false
      }
    }
  },
}
```

`opsworks` 속성은 앞 섹션의 예제와 대체로 동일합니다. 다음 섹션들은 배포와 가장 관련이 깊습니다.
+ `activity` – 이 속성들과 연결된 이벤트(이 예제에서는 Deploy 이벤트).
+ `applications` – 앱의 이름, 슬러그 이름, 유형을 제공하는 각 앱의 속성 집합을 포함합니다.

  슬러그 이름은 OpsWorks Stacks가 앱 이름에서 생성하는 앱의 짧은 이름입니다. SimplePHP의 슬러그 이름은 simplephp입니다.
+ `deployment` – 배포를 고유하게 식별하는 배포 ID.

`deploy` 속성은 배포 중인 앱에 대한 정보를 포함합니다. 예를 들어 내장 Deploy 레시피는 `deploy` 속성의 데이터를 사용하여 적절한 디렉터리에 파일을 설치하고 데이터베이스 연결 파일을 생성합니다. `deploy` 속성에는 배포된 각 앱마다 앱의 짧은 이름으로 명명된 속성이 하나씩 포함됩니다. 각 앱 속성은 다음 속성을 포함합니다.
+ `environment_variables` – 앱에 대해 정의한 환경 변수를 포함합니다. 자세한 내용은 [환경 변수](workingapps-creating.md#workingapps-creating-environment) 섹션을 참조하세요.
+ `domains` – 기본적으로 도메인은 앱의 짧은 이름입니다(이 예제에서는 simplephpapp). 사용자 지정 도메인을 할당한 경우, 여기에 도메인도 표시됩니다. 자세한 내용은 [사용자 지정 도메인 사용](workingapps-domains.md) 섹션을 참조하세요.
+ `application` – 앱의 짧은 이름.
+ `scm` – 이 요소에는 앱의 리포지토리(이 예제에서는 Git 리포지토리)에서 앱의 파일을 다운로드하는 데 필요한 정보가 포함됩니다.
+ `database` – 데이터베이스 정보(스택에 데이터베이스 계층이 포함된 경우)
+ `document_root` - 문서 루트. 이 예제에서는 `null`로 설정되어 루트가 공개되어 있음을 나타냅니다.
+ `ssl_certificate_ca`, `ssl_support`, `ssl_certificate_key` – 앱에 SSL 지원이 있는지 여부를 나타냅니다. SSL 지원이 있는 경우, `ssl_certificate_key` 및 `ssl_certificate_ca` 속성은 해당 인증서로 설정됩니다.
+ `deploy_to` – 앱의 루트 디렉터리.