[AWS] API Gateway 이용해서Websocket 애플리케이션 구성 (1부)

Kyeongyeon Oh
6 min readNov 24, 2019

--

Summary

웹소켓 구현 및 연결 관리를 AWS 에 맡기고 전통적인 HTTP API의 조합으로 Web browser -Server 간 양방향 통신을 구현할 수 있습니다.

준비물

HOW TO

  1. AWS 콘솔에서 API Gateway > WebSocket 선택, API 이름과 Route Expression 입력합니다. 단, 이 상태로는 배포가 안됩니다.
API 이름, Route Selection Expression 입력
Route를 하나도 설정하지 않은 상태에서는 배포를 할수 없습니다.

2. 배포를 해 보려면, $default Route를 등록합니다. Mock을 선택하고 Save를 누릅니다. 이번엔 API 배포가 성공합니다.

3. 배포 되면, Websocket URL 과 connection URL 이 안내됩니다. wscat 을 설치하고, 아래 CLI 명령을 입력해서 웹소켓 접속 테스트를 해봅니다.

wscat -c wss://{api-id}.execute-api.ap-northeast-2.amazonaws.com/dev
어떤 메시지를 보냈을 때에나, Internal Error 가 발생하지만, 어쨌든 연결은 성공했습니다. 연결시 연결 하나하나마다 하나씩 발급되는 connectionId 에 주목하세요.

4. 소켓 연결은 성공하는데, 무엇을 입력해도 Internal Server Error를 응답합니다. 아래 4–1과 4–2은 사실은 필요없는 삽질이니 참고하세요.

4–1. 에러가 안 나게 하는 방법 (통합 요청 템플릿 만들기)

Mock의 Request Template 을 확장하고, $request.body.message 를 Template Selection Expression 에 입력하고, Template Key $default 의 Template을 아래 내용을 포함한 json 형식으로 등록합니다.

{“statusCode”: 200 }
이제는 뭘 전달해도 에러를 안 내네요.

4–2. 소켓 메시지 전송시 응답도 하게 하는 방법 (통합 응답 템플릿 만들기)

오른쪽 위의 “Add Integration response” 를 클릭하면 아래처럼 Mock Endpoint 의 응답을 를 받아서 처리하는 Integration Response 단계가 보이게 됩니다.
Integration Response에 진입합니다.
statuscode 가 200 일 때의 default template 를 지정합니다.

템플릿 형식에는 무엇을 넣어도 되는데(JSON형식이 아니어도 됨!), $context.connectionId를 입력하면 현재 connection의 connectionId 를 보내주니 이걸 사용해 보죠.. ( 위 3번 단계에서 Internel Server Error가 함께 응답해준 그것입니다)

{
"statusCode": 200,
"connectionId": $context.connectionId
}
템플릿 형식에 맞춰서 메시지가 돌아옵니다. (newline과 whitespace 도 유지됩니다)

그러나.. Mock Integration 으로는 특별한 로직이나 프로그램을 작성할 수가 없습니다. 템플릿에서 응답을 적절하게 포매팅 해줄 수는 있는 것 같습니다.

5. 우선, Integrate된 Mock Request Template 은 그대로 두고, 저의 목적은 서버에서 푸시를 보내고 싶은 거니까, 뭐라도 푸시를 보내보겠습니다.

과정 3에서 배포 staging 화면에서 알려주는 Connection URL 와, wscat로 웹소켓 API에 연결해 메시지를 보내면 에러와 함께 응답해주는 connectionId와 함께 아래 URL 을 만듭시다.

https://{api-id}.execute-api.ap-northeast-2.amazonaws.com/dev/@connections/{connectionId}

awscurl 를 이용해 만들어낸 URL을 아래와 같이 확인해 봅니다. (‘@’ 문자가 ‘%40’ 으로 인코딩된 부분을 유의하세요)

awscurl — service execute-api -X GET https://{api-id}.execute-api.ap-northeast-2.amazonaws.com/dev/%40connections/{connectionId} — region=ap-northeast-2
GET API는 현재 연결에 대한 정보를 돌려줍니다.

5–1 awscurl 커맨드를 조금 변경해서, 연결된 connectionId 에 POST 메시지를 전달해 봅시다. (-d argument 추가)

awscurl — service execute-api -X POST https://{api-id}.execute-api.ap-northeast-2.amazonaws.com/dev/%40connections/{connectionId} — region=ap-northeast-2 -d “test”
메시지 전달됨!

여기까지만 해도 별도 웹소켓 서버 구현 및 실행 없이 wss://프로토콜로 접속한 사용자에게 PUSH 메시지를 전송할 수 있습니다. 다음 편에서 $connect, $disconnect Integration 을 이용해 기존 레거시 시스템의 로그인 사용자 sessionId 으로 인증하고 연결들을 관리하는 방법을 찾아보려고 합니다.

— 2부에서 계속

--

--