

# API Gateway에서 WebSocket API에 대한 라우팅 생성
<a name="websocket-api-develop-routes"></a>

WebSocket API에서 수신되는 JSON 메시지는 사용자가 구성한 라우팅을 기반으로 백엔드 통합으로 전달됩니다. (비 JSON 메시지는 사용자가 구성한 `$default` 라우팅으로 전달됩니다.)

*라우팅*에는 *라우팅 선택 표현식*을 평가할 경우 예상되는 값인 *라우팅 키*가 포함되어 있습니다. `routeSelectionExpression`은 API 수준에서 정의되는 속성입니다. 메시지 페이로드에 존재할 것으로 예상되는 JSON 속성을 지정합니다. 라우팅 선택 표현식에 대한 자세한 내용은 [라우팅 선택 표현식](#apigateway-websocket-api-route-selection-expressions) 단원을 참조하십시오.

예를 들어 JSON 메시지에 `action` 속성이 있고 이 속성을 기반으로 다른 작업을 수행하려는 경우, 라우팅 선택 표현식은 `${request.body.action}`일 수 있습니다. 라우팅 테이블은 사용자가 테이블에 정의한 사용자 지정 라우팅 키 값에 따라 `action` 속성 값을 일치시켜 어떤 작업을 수행할 것인지 지정할 것입니다.

`$connect`, `$disconnect`, `$default` 등 세 가지 사전 정의된 라우팅을 사용할 수 있습니다. 또한 사용자 지정 라우팅을 생성할 수 있습니다.
+ API Gateway는 클라이언트와 WebSocket API 간 지속적인 연결이 시작될 때 `$connect` 라우팅을 호출합니다.
+ API Gateway는 클라이언트 또는 서버가 API와의 연결을 끊을 때 `$disconnect` 라우팅을 호출합니다.
+ 일치하는 라우팅이 발견되면 메시지를 기준으로 라우팅 선택 표현식이 평가된 후 API Gateway가 사용자 지정 라우팅을 호출합니다. 일치 여부에 따라 어떤 통합이 호출될지 결정됩니다.
+ 일치하는 라우팅이 없거나 메시지를 기준으로 라우팅 선택 표현식을 평가할 수 없는 경우 API Gateway가 `$default` 라우팅을 호출합니다.

## 라우팅 선택 표현식
<a name="apigateway-websocket-api-route-selection-expressions"></a>

서비스가 수신 메시지에 대해 따라야 할 라우팅을 선택할 때 *라우팅 선택 표현식*이 평가됩니다. 서비스는 `routeKey`가 평가된 값과 정확하게 일치하는 라우팅을 사용합니다. 일치하는 값이 없고 라우팅 키가 `$default`인 라우팅이 존재하는 경우, 그 값이 선택됩니다. 평가된 값과 일치하는 라우팅이 없고 `$default` 라우팅이 없는 경우 서비스는 오류를 반환합니다. WebSocket 기반 API의 경우 표현식은 `$request.body.{path_to_body_element}` 형식이어야 합니다.

예를 들어 다음과 같은 JSON 메시지를 보낸다고 가정하겠습니다.

```
{
    "service" : "chat",
    "action" : "join",
    "data" : {
        "room" : "room1234"
   }
}
```

`action` 속성을 기반으로 API의 동작을 선택할 수 있습니다. 이 경우 다음 라우팅 선택 표현식을 정의할 수 있습니다.

```
$request.body.action
```

이 예에서 `request.body`는 메시지의 JSON 페이로드를 나타내며 `.action`은 [JSONPath](https://goessner.net/articles/JsonPath/) 표현식입니다. `request.body` 뒤에 모든 JSON 경로 표현식을 사용할 수 있지만 결과는 문자열로 변환됩니다. 예를 들어, JSONPath 표현식이 두 요소의 배열을 반환하면 `"[item1, item2]"` 문자열로 표시됩니다. 따라서 표현식을 배열이나 객체가 아닌 값으로 평가하는 것이 좋습니다.

단순히 정적 값을 사용하거나 여러 변수를 사용할 수 있습니다. 다음 표는 이전의 페이로드에 대한 예제와 평가된 결과를 보여줍니다.


| 표현식 | 평가된 결과 | 설명 | 
| --- | --- | --- | 
| \$1request.body.action | join | 언래핑된 변수 | 
| \$1\$1request.body.action\$1 | join | 래핑된 변수 | 
| \$1\$1request.body.service\$1/\$1\$1request.body.action\$1 | chat/join | 정적 값이 있는 여러 변수 | 
| \$1\$1request.body.action\$1-\$1\$1request.body.invalidPath\$1  | join- | JSONPath를 찾지 못하면 변수는 ""로 해석됩니다. | 
| action | action | 정적 값 | 
| \$1\$1default | \$1default | 정적 값 | 

평가된 결과는 라우팅을 찾는 데 사용됩니다. 일치하는 라우팅 키를 가진 라우팅이 있는 경우, 해당 라우팅이 선택되어 메시지를 처리합니다. 일치하는 라우팅이 없으면 API Gateway가 사용 가능한 `$default` 라우팅을 찾습니다. `$default` 라우팅이 정의되지 않은 경우, API Gateway는 오류를 반환합니다.

## API Gateway에서 WebSocket API에 대한 라우팅 설정
<a name="apigateway-websocket-api-routes"></a>

처음 새 WebSocket API를 생성할 때 `$connect`, `$disconnect`, `$default` 등 세 가지 사전 정의된 라우팅이 있습니다. 콘솔, API 또는 AWS CLI를 사용하여 생성할 수 있습니다. 필요에 따라 사용자 지정 라우팅을 생성할 수 있습니다. 자세한 내용은 [API Gateway의 WebSocket API 개요](apigateway-websocket-api-overview.md) 단원을 참조하세요.

**참고**  
CLI에서는 통합을 생성하기 이전 또는 이후에 라우팅을 생성할 수 있으며 여러 라우팅에 대해 동일한 통합을 재사용할 수 있습니다.

### API Gateway 콘솔을 사용하여 라우팅 생성
<a name="apigateway-websocket-api-route-using-console"></a>

**API Gateway 콘솔을 사용하여 라우팅을 생성하려면**

1. API Gateway 콘솔에 로그인하고 API를 선택한 다음 **라우팅**을 선택하세요.

1. **경로 생성**을 선택합니다.

1. **라우팅 키**에 라우팅 키 이름을 입력합니다. 사전 정의된 경로(`$connect`, `$disconnect` 및 `$default`) 또는 사용자 지정 경로를 생성할 수 있습니다.
**참고**  
사용자 지정 라우팅을 생성할 때 라우팅 키 이름에 `$` 접두사를 사용하지 마십시오. 이 접두사는 미리 정의된 라우팅에 예약되어 있습니다.

1. 경로의 통합 유형을 선택하고 구성합니다. 자세한 내용은 [API Gateway 콘솔을 사용하여 WebSocket API 통합 요청을 설정](apigateway-websocket-api-integration-requests.md#apigateway-websocket-api-integration-request-using-console) 섹션을 참조하세요.

### AWS CLI를 사용하여 라우팅 생성
<a name="apigateway-websocket-api-route-using-awscli"></a>

다음 [create-route](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route.html) 명령은 라우팅을 생성합니다.

```
aws apigatewayv2 --region us-east-1 create-route --api-id aabbccddee --route-key $default
```

출력은 다음과 같습니다.

```
{
    "ApiKeyRequired": false,
    "AuthorizationType": "NONE",
    "RouteKey": "$default",
    "RouteId": "1122334"
}
```

### `$connect`에 대한 라우팅 요청 설정 지정
<a name="apigateway-websocket-api-route-request-connect"></a>

API에 대해 `$connect` 라우팅을 설정하면 다음 선택적 설정을 사용하여 API에 대한 권한 부여를 활성화할 수 있습니다. 자세한 내용은 [`$connect` 라우팅](apigateway-websocket-api-route-keys-connect-disconnect.md#apigateway-websocket-api-routes-about-connect) 단원을 참조하세요.
+ **권한 부여**: 권한 부여가 필요하지 않으면 `NONE`을 지정할 수 있습니다. 또는 다음을 지정할 수 있습니다.
  + `AWS_IAM`: 표준 AWS IAM 정책을 사용하여 API에 대한 액세스를 제어합니다.
  + `CUSTOM`: 이전에 생성한 Lambda 권한 부여자 함수를 지정하여 API에 대한 권한 부여를 구현합니다. 권한 부여자는 자신의 AWS 계정이나 다른 AWS 계정에 상주할 수 있습니다. Lambda 권한 부여자에 대한 자세한 내용은 [API Gateway Lambda 권한 부여자 사용](apigateway-use-lambda-authorizer.md) 단원을 참조하세요.
**참고**  
API Gateway 콘솔에서 `CUSTOM` 설정은 [Lambda 권한 부여자 구성(콘솔)](configure-api-gateway-lambda-authorization.md#configure-api-gateway-lambda-authorization-with-console)에서 설명한 대로 권한 부여자 함수를 설정한 후에만 볼 수 있습니다.
**중요**  
**권한 부여** 설정은 `$connect` 라우팅뿐만 아니라 전체 API에 적용됩니다. `$connect` 라우팅은 모든 연결에서 호출되기 때문에 다른 라우팅을 보호합니다.
+ **API Key Required(API 키 필요)**: 선택적으로, API의 `$connect` 라우팅에 대한 API 키가 필요할 수 있습니다. API 키와 사용량 계획을 함께 사용하여 API 액세스를 제어하고 추적할 수 있습니다. 자세한 내용은 [API Gateway의 REST API 사용량 계획 및 API 키](api-gateway-api-usage-plans.md) 단원을 참조하세요.

### API Gateway 콘솔을 사용하여 `$connect` 라우팅 요청 설정
<a name="apigateway-websocket-api-connect-route-request-using-console"></a>

API Gateway 콘솔을 사용하여 WebSocket API에 대한 `$connect` 라우팅 요청을 설정하려면 다음을 수행하세요.

1. API Gateway 콘솔에 로그인하고 API를 선택한 다음 **라우팅**을 선택하세요.

1. **경로**에서 [API Gateway 콘솔을 사용하여 라우팅 생성](#apigateway-websocket-api-route-using-console)을 따라 `$connect`를 선택하거나 `$connect` 경로를 생성합니다.

1. **경로 요청 설정** 섹션에서 **편집**을 선택합니다.

1. **권한 부여**에서 권한 부여 유형을 선택합니다.

1. `$connect` 경로용 API를 요구하려면 **API 키 필요**를 선택합니다.

1. **변경 사항 저장**을 선택합니다.

# API Gateway에서 WebSocket API에 대한 라우팅 응답 설정
<a name="apigateway-websocket-api-route-response"></a>

WebSocket 라우팅은 양방향 또는 단방향 통신으로 구성할 수 있습니다. 경로 응답을 설정하지 않으면 API Gateway가 경로 응답을 통해 백엔드 응답을 전달하지 않습니다.

**참고**  
WebSocket API에 대한 `$default` 경로 응답만 정의할 수 있습니다. 통합 응답을 사용하여 백엔드 서비스의 응답을 조작할 수 있습니다. 자세한 내용은 [통합 응답 개요](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-overview) 섹션을 참조하세요.

API Gateway 콘솔이나 AWS CLI 또는 AWS SDK를 사용하여 경로 응답 및 응답 선택 표현식을 구성할 수 있습니다.

라우팅 응답 선택 표현식에 대한 자세한 내용은 [라우팅 응답 선택 표현식](apigateway-websocket-api-selection-expressions.md#apigateway-websocket-api-route-response-selection-expressions) 단원을 참조하십시오.

**Topics**
+ [API Gateway 콘솔을 사용하여 라우팅 응답 설정](#apigateway-websocket-api-route-response-using-console)
+ [AWS CLI를 사용하여 라우팅 응답 설정](#apigateway-websocket-api-route-response-using-awscli)

## API Gateway 콘솔을 사용하여 라우팅 응답 설정
<a name="apigateway-websocket-api-route-response-using-console"></a>

WebSocket API를 생성하고 프록시 Lambda 함수를 기본 경로에 연결한 후, API Gateway 콘솔을 사용하여 경로 응답을 설정할 수 있습니다.

1. API Gateway 콘솔에 로그인하고 `$default` 경로에 프록시 Lambda 함수가 통합된 WebSocket API를 선택합니다.

1. **Routes**(경로)에서 `$default` 경로를 선택합니다.

1. **양방향 통신 활성화**를 선택합니다.

1. **Deploy API(API 배포)**를 선택합니다.

1. API를 스테이지에 배포합니다.

 API에 연결하려면 다음 [ wscat](https://www.npmjs.com/package/wscat) 명령을 사용합니다. 에 대한 자세한 내용은 `wscat` 단원을 참조하세요.[`wscat`를 사용하여 WebSocket API에 연결하고 메시지 보내기](apigateway-how-to-call-websocket-api-wscat.md).

```
wscat -c wss://api-id.execute-api.us-east-2.amazonaws.com/test
```

 기본 경로를 호출하려면 enter(엔터) 버튼을 누릅니다. Lambda 함수 본문이 반환될 것입니다.

## AWS CLI를 사용하여 라우팅 응답 설정
<a name="apigateway-websocket-api-route-response-using-awscli"></a>

다음 [create-route-response](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/create-route-response.html) 명령은 `$default` 라우팅에 대한 라우팅 응답을 생성합니다. [get-apis](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-apis.html) 및 [get-routes](https://docs.aws.amazon.com/cli/latest/reference/apigatewayv2/get-routes.html) 명령을 사용하여 API ID와 라우팅 ID를 식별할 수 있습니다.

```
aws apigatewayv2 create-route-response \
    --api-id aabbccddee \
    --route-id 1122334  \
    --route-response-key '$default'
```

출력은 다음과 같습니다.

```
{
    "RouteResponseId": "abcdef",
    "RouteResponseKey": "$default"
}
```

# WebSocket 하위 프로토콜이 필요한 `$connect` 라우팅 설정
<a name="websocket-connect-route-subprotocol"></a>

클라이언트는 WebSocket API에 연결하는 동안 [WebSocket 서브프로토콜](https://datatracker.ietf.org/doc/html/rfc6455#page-12)을 요청하기 위해 `Sec-WebSocket-Protocol` 필드를 사용할 수 있습니다. 클라이언트가 API가 지원하는 서브프로토콜을 요청하는 경우에만 연결을 허용하도록 `$connect` 라우팅에 대한 통합을 설정할 수 있습니다.

다음 예제 Lambda 함수는 `Sec-WebSocket-Protocol` 헤더를 클라이언트에 반환합니다. 이 함수는 클라이언트가 `myprotocol` 서브프로토콜을 지정하는 경우에만 API에 대한 연결을 설정합니다.

이 예제 API 및 Lambda 프록시 통합을 생성하는 CloudFormation 템플릿에 대해서는 [samples/ws-subprotocol.zip](samples/ws-subprotocol.zip) 단원을 참조하세요.

```
export const handler = async (event) => {
    if (event.headers != undefined) {
        const headers = toLowerCaseProperties(event.headers);
        
        if (headers['sec-websocket-protocol'] != undefined) {
            const subprotocolHeader = headers['sec-websocket-protocol'];
            const subprotocols = subprotocolHeader.split(',');
            
            if (subprotocols.indexOf('myprotocol') >= 0) {
                const response = {
                    statusCode: 200,
                    headers: {
                        "Sec-WebSocket-Protocol" : "myprotocol"
                    }
                };
                return response;
            }
        }
    }
    
    const response = {
        statusCode: 400
    };
        
    return response;
};

function toLowerCaseProperties(obj) {
    var wrapper = {};
    for (var key in obj) {
        wrapper[key.toLowerCase()] = obj[key];
    }
    return wrapper;
}
```

[https://www.npmjs.com/package/wscat](https://www.npmjs.com/package/wscat)를 사용하면 클라이언트가 API가 지원하는 서브프로토콜을 요청하는 경우에만 API가 연결을 허용하는지 테스트할 수 있습니다. 다음 명령은 `-s` 플래그를 사용하여 연결 중에 서브프로토콜을 지정합니다.

다음 명령은 지원되지 않는 서브프로토콜을 사용하여 연결을 시도합니다. 클라이언트가 `chat1` 서브프로토콜을 지정했기 때문에 Lambda 통합에서 400 오류를 반환하고 연결이 실패합니다.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1
error: Unexpected server response: 400
```

다음 명령은 연결 요청에 지원되는 서브프로토콜을 포함합니다. Lambda 통합은 연결을 허용합니다.

```
wscat -c wss://api-id.execute-api.region.amazonaws.com/beta -s chat1,myprotocol
connected (press CTRL+C to quit)
```

WebSocket API 호출에 대한 자세한 내용은 [WebSocket API 간접 호출](apigateway-how-to-call-websocket-api.md) 단원을 참조하세요.