

# Java에 대한 Lambda SnapStart 런타임 후크
<a name="snapstart-runtime-hooks-java"></a>

Lambda가 스냅샷을 생성하기 전이나 Lambda가 스냅샷에서 함수를 재개한 후에 런타임 후크를 사용하여 코드를 구현할 수 있습니다. 런타임 후크는 오픈 소스 체크포인트 Coordinated Restore at Checkpoint(CRaC) 프로젝트의 일부로 제공됩니다. [Open Java Development Kit(OpenJDK)](https://wiki.openjdk.org/display/crac)용 CRaC는 개발 중입니다. 참조 애플리케이션에 CRaC를 사용하는 방법의 예는 GitHub에서 [CRaC](https://github.com/CRaC/docs/blob/master/STEP-BY-STEP.md) 리포지토리를 참조하세요. CRaC는 세 가지 주요 요소를 사용합니다.
+ `Resource` - `beforeCheckpoint()`와 `afterRestore()`라는 두 가지 메서드가 있는 인터페이스입니다. 이러한 메서드를 사용하여 스냅샷 생성 전과 복원 후에 실행할 코드를 구현합니다.
+ `Context <R extends Resource>` - 체크포인트 및 복원에 대한 알림을 받으려면 `Resource`를 `Context`에 등록해야 합니다.
+ `Core` - 정적 메서드 `Core.getGlobalContext()`를 통해 기본 글로벌 `Context`를 제공하는 조정 서비스입니다.

`Context` 및 `Resource`에 대한 자세한 내용은 CRaC 설명서에서 [org.crac 패키징](https://javadoc.io/doc/io.github.crac/org-crac/latest/index.html)을 참조하세요.

다음 단계에 따라 [org.crac 패키지](https://github.com/CRaC/org.crac)를 사용하여 런타임 후크를 구현합니다. Lambda 런타임에는 체크포인트를 생성하기 전과 복원 후에 런타임 후크를 호출하는 사용자 지정 CRaC 컨텍스트 구현이 포함되어 있습니다.

## 런타임 후크 등록 및 실행
<a name="runtime-hooks-registration-java"></a>

Lambda에서 런타임 후크를 실행하는 순서는 등록 순서에 따라 결정됩니다. 등록 순서는 코드의 가져오기, 정의 또는 실행 순서를 따릅니다.
+ `beforeCheckpoint()`: 등록의 역순으로 실행됨
+ `afterRestore()`: 등록 순서대로 실행됨

등록된 모든 후크를 올바르게 가져와서 함수 코드에 포함했는지 확인합니다. 별도의 파일 또는 모듈에 런타임 후크를 등록하는 경우 모듈을 함수의 핸들러 파일에 직접 가져오거나 더 큰 패키지의 일부로 가져와야 합니다. 함수 핸들러에 파일 또는 모듈을 가져오지 않으면 Lambda는 런타임 후크를 무시합니다.

**참고**  
Lambda가 스냅샷을 생성할 때 초기화 코드를 최대 15분 동안 실행할 수 있습니다. 시간 제한은 130초 또는 [구성된 함수 제한 시간](configuration-timeout.md)(최대 900초) 중 더 높은 값입니다. `beforeCheckpoint()` 런타임 후크는 초기화 코드 시간 제한에 포함됩니다. Lambda에서 스냅샷을 복원하는 경우 런타임이 로드되고 `afterRestore()` 런타임 후크가 제한 시간(10초) 내에 완료되어야 합니다. 그렇지 않으면 SnapStartTimeoutException이 발생합니다.

## 1단계: 빌드 구성 업데이트
<a name="runtime-hooks-java-update-build"></a>

빌드 구성에 `org.crac` 종속성을 추가합니다. 다음 예에서는 Gradle을 사용합니다. 다른 빌드 시스템의 예제는 [Apache Maven 설명서](https://search.maven.org/artifact/io.github.crac/org-crac/0.1.3/jar)를 참조하세요.

```
dependencies {
    compile group: 'com.amazonaws', name: 'aws-lambda-java-core', version: '1.2.1'
    # All other project dependecies go here:
    # ...
    # Then, add the org.crac dependency:
 implementation group: 'org.crac', name: 'crac', version: '1.4.0'
}
```

## 2단계: Lambda 핸들러 업데이트
<a name="runtime-hooks-java-update-handler"></a>

Lambda 함수의 *핸들러*는 이벤트를 처리하는 함수 코드의 메서드입니다. 함수가 간접 호출되면 Lambda는 핸들러 메서드를 실행합니다. 함수는 핸들러가 응답을 반환하거나 종료하거나 제한 시간이 초과될 때까지 실행됩니다.

자세한 내용은 [Java에서 Lambda 함수 핸들러 정의](java-handler.md) 섹션을 참조하세요.

다음 예제 핸들러는 체크포인트 생성 전(`beforeCheckpoint()`)과 복원 후(`afterRestore()`)에 코드를 실행하는 방법을 보여줍니다. 또한 이 핸들러는 런타임 관리 글로벌 `Resource`에 `Context`를 등록합니다.

**참고**  
Lambda가 스냅샷을 생성할 때 초기화 코드를 최대 15분 동안 실행할 수 있습니다. 시간 제한은 130초 또는 [구성된 함수 제한 시간](configuration-timeout.md)(최대 900초) 중 더 높은 값입니다. `beforeCheckpoint()` 런타임 후크는 초기화 코드 시간 제한에 포함됩니다. Lambda가 스냅샷을 복원할 때, 런타임(JVM)이 로드되고 `afterRestore()` 런타임 후크가 제한 시간(10초) 내에 완료되어야 합니다. 그렇지 않으면 SnapStartTimeoutException이 발생합니다.

```
...
  import org.crac.Resource;
  import org.crac.Core;
  ... 
public class CRaCDemo implements RequestStreamHandler, Resource {
    public CRaCDemo() {
      Core.getGlobalContext().register(this);
    }
    public String handleRequest(String name, Context context) throws IOException {
      System.out.println("Handler execution");
      return "Hello " + name;
    }
    @Override
    public void beforeCheckpoint(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("Before checkpoint");
    }
    @Override
    public void afterRestore(org.crac.Context<? extends Resource> context)
        throws Exception {
      System.out.println("After restore");
```

`Context`는 등록된 객체에 대해서만 [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ref/WeakReference.html)를 유지합니다. [https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html](https://javadoc.io/static/io.github.crac/org-crac/0.1.3/org/crac/Resource.html)가 가비지 수집된 경우 런타임 후크가 실행되지 않습니다. 런타임 후크가 실행되도록 하려면 코드에서 `Resource`에 대한 강력한 참조를 유지해야 합니다.

다음은 피해야 할 두 가지 패턴의 예입니다.

**Example - 강력한 참조가 없는 객체**  

```
Core.getGlobalContext().register( new MyResource() );
```

**Example - 익명 클래스의 객체**  

```
Core.getGlobalContext().register( new Resource() {
   
   @Override
   public void afterRestore(Context<? extends Resource> context) throws Exception {
    // ...
   }
   
   @Override
   public void beforeCheckpoint(Context<? extends Resource> context) throws Exception {
    // ...
   }

} );
```

대신 강력한 참조를 유지하세요. 다음 예제에서 등록된 리소스는 가비지 수집되지 않았으며 런타임 후크가 일관되게 실행됩니다.

**Example - 강력한 참조가 있는 객체**  

```
Resource myResource = new MyResource(); // This reference must be maintained to prevent the registered resource from being garbage collected
Core.getGlobalContext().register( myResource );
```