AWS IoT Core
고친 사람 github-actions[bot]
AWS IoT Core 는 인터넷 너머에 흩어진 기기들이 붙어 오는 것을 아마존이 대신 받아 줍니다. 기기는 내 서버가 아니라 이 서비스에 붙습니다. 내 서버는 그 뒤에서 넘어온 메시지만 받습니다. 기기가 수시로 끊기고 다시 붙는 사정도 이 서비스가 감당합니다.
쉽고 빠른 이해
기기가 아무리 많아도 그 연결을 대신 받아 주는 서비스입니다. 매장마다 놓인 온도계가 십 분마다 온도를 올려 보낸다면, 그 온도계들이 붙는 곳이 내 서버가 아니라 이 서비스입니다.
이것이 없으면 서버가 그 연결을 전부 직접 들고 있어야 합니다. 기기는 대수가 많고 자주 끊깁니다. 온도 값을 모아 보여 주기도 전에 연결부터 감당하게 됩니다.
돌아가는 방식은 이렇습니다.
- 기기마다 신분증을 하나씩 심어 두고, 기기는 그것으로 자기를 밝히며 붙습니다
- 기기는 올리는 메시지마다 이름표를 붙입니다
- 서비스는 그 이름표를 보고 미리 적어 둔 곳으로 메시지를 넘깁니다
대가가 있습니다. 붙는 방식이 정해져 있어서 내가 만든 규약으로는 못 붙입니다. 현장에 깔린 기기가 아마존 쪽 주소와 신분증 체계에 묶입니다. 요금은 붙어 있던 시간과 주고받은 메시지 수를 따릅니다.
상세
이 절은 AWS IoT Core 가 내 서버 대신 무엇을 맡는지 봅니다. 기기 쪽 사정이 왜 서버에 짐이 되는지부터 보고, 그 짐을 넘겼을 때 서버가 무엇을 안 하게 되는지를 따라갑니다. 매장마다 온도계가 하나씩 놓여 있고 그 값을 모아 보는 서비스를 줄곧 예로 씁니다.
AWS IoT Core 는 AWS(Amazon Web Services, 아마존 웹 서비스)가 빌려주는 서비스 가운데 하나입니다. 이름의 IoT 는 Internet of Things, 곧 사물인터넷을 줄인 말입니다. 사람이 앞에 앉아 쓰는 컴퓨터가 아니라 기계에 붙은 컴퓨터가 네트워크로 데이터를 주고받는 것을 가리킵니다. 내려받아 설치하는 프로그램이 아니라 아마존이 운영하는 서버에 붙어서 쓰는 관리형 서비스입니다.
기기 쪽의 사정
기기 쪽은 서버끼리 주고받을 때와 사정이 다릅니다. 한 대가 보내는 양은 적은데 대수가 많습니다. 온도계 한 대는 십 분에 숫자 하나를 올릴 뿐이지만, 매장이 늘면 그런 기기가 따라서 늘어납니다.
전원과 네트워크도 서버만큼 안정적이지 않습니다. 기기는 꺼졌다 켜지고 이동 통신은 끊겼다 붙습니다. 끊긴 줄 모르고 보낸 값은 아무 데도 닿지 않습니다.
그러면서도 연결은 오래 붙어 있어야 합니다. 서버가 기기에 명령을 내려야 할 때가 있기 때문입니다. 기기는 대개 공유기 안쪽에 있어서 바깥에서 먼저 두드릴 수 없습니다. 그래서 기기 쪽에서 통로를 열어 두고 기다리는 모양이 됩니다.
서버가 직접 떠안는 부담
이 사정을 내 서버가 직접 감당한다고 해 봅시다. 연결 하나마다 파일 디스크립터와 메모리가 붙습니다. 파일 디스크립터는 열어 둔 연결 하나에 운영체제가 매기는 번호이고, 한 프로세스가 가질 수 있는 개수에 한도가 있습니다. 기기가 늘면 서버를 늘려야 하고, 서버를 늘리면 어느 기기가 어느 서버에 붙어 있는지 따로 적어 둬야 그 기기에 명령을 보낼 수 있습니다.
끊긴 연결도 서버가 알아차려야 합니다. 상대가 조용한 것이 할 말이 없어서인지 죽어서인지 구별하려고 주기적으로 신호를 주고받습니다. 이 신호가 하트비트입니다. 타임아웃을 짧게 잡으면 멀쩡한 기기를 끊고, 길게 잡으면 죽은 연결을 오래 들고 있습니다.
정전이 복구되면 그 지역 기기가 한꺼번에 다시 붙습니다. 몰린 재접속에 서버가 넘어지면 기기는 또 한꺼번에 다시 붙습니다. 이렇게 한 사건에 요청이 쏠리는 것을 썬더링 허드라고 부르고, 막으려면 기기 쪽이 재접속 간격을 조금씩 늘려 가며 흩어져야 합니다(지수 백오프).
기기마다 신원을 확인할 열쇠를 발급하고, 잃어버린 기기의 열쇠를 막는 일도 누군가 굴려야 합니다. 이 일들은 온도 값을 모아 보여 주는 일과 아무 상관이 없습니다.
가운데 서는 메시지 브로커
AWS IoT Core 는 그 연결을 받는 쪽을 통째로 맡습니다. 기기는 이 서비스에 붙고, 내 서버도 이 서비스에 붙습니다. 두 쪽은 서로 직접 만나지 않습니다.
가운데에서 메시지를 받아 필요한 쪽에 나눠 주는 프로그램을 메시지 브로커라고 부릅니다. 보내는 쪽은 받을 상대를 지정하지 않고 이름표를 붙여 올립니다. 그 이름표가 토픽입니다. 받고 싶은 쪽은 이름표를 미리 걸어 두고 기다립니다. 이렇게 양쪽이 서로를 모르는 채 주고받는 방식을 발행-구독이라고 합니다.
기기와 브로커가 어떤 규칙으로 말을 주고받는지는 MQTT(Message Queuing Telemetry Transport)라는 프로토콜이 정합니다. 전기와 대역폭이 빠듯한 기기를 염두에 두고 만들어진 규칙입니다. AWS IoT Core 가 하는 일은 그 규칙을 새로 정하는 것이 아니라, 그 규칙을 지키는 브로커를 대신 굴려 주는 것입니다.
붙는 길은 하나가 아닙니다. 브라우저에서 붙을 수 있게 웹소켓 위에 얹은 MQTT 도 받고, 값을 올리기만 하는 기기라면 HTTPS(HyperText Transfer Protocol Secure) 요청 한 번으로 올리는 길도 있습니다. 어느 길로 오든 받는 쪽은 같은 브로커입니다.
기기의 신원 확인
연결을 대신 받으려면 붙어 온 것이 내 기기가 맞는지부터 가려야 합니다. 사람이 쓰는 서비스라면 사용자가 비밀번호를 칩니다. 현장에 놓인 온도계 앞에는 칠 사람이 없습니다.
그래서 기기에는 인증서를 하나씩 미리 심어 둡니다. 인증서는 X.509 라는 정해진 형식으로 적힌 신분증이고, 그 안에는 기기의 공개키가 들어 있습니다. 공개키는 남에게 보여 줘도 되는 열쇠이고, 짝이 되는 비밀 열쇠는 기기 안에 남아 밖으로 나가지 않습니다.
붙을 때는 양쪽이 서로 신분증을 내밉니다. 기기가 서비스를 확인하고 서비스도 기기를 확인합니다. 이렇게 양방향으로 확인하는 것을 상호 TLS라고 부르고, 확인이 끝나면 TLS(Transport Layer Security, 전송 계층 보안)로 암호화된 통로가 열립니다.
신분증을 발급하고, 어느 기기의 것을 못 쓰게 막을지 정하고, 붙을 때마다 그 목록을 확인하는 일을 서비스가 맡습니다. 기기 한 대를 도난당하면 그 기기의 인증서만 막습니다. 나머지 기기는 아무 영향을 받지 않습니다.
신원과 별개로 권한도 기기마다 걸어 둡니다. 어떤 이름표에 올려도 되고 어떤 이름표를 받아 봐도 되는지를 적어 두면, 한 매장의 온도계가 남의 매장 값을 들여다보지 못합니다.
꺼져 있는 기기를 대신하는 디바이스 섀도우
기기는 절반쯤 꺼져 있습니다. 명령을 내려야 하는데 상대가 안 붙어 있는 일이 자주 생깁니다. 조명 기기에 밝기를 낮추라고 보냈는데 마침 그 기기가 꺼져 있으면 그 명령은 허공으로 갑니다.
AWS IoT Core 는 기기마다 종이 한 장을 대신 들고 있어 줍니다. 그 종이에는 기기가 마지막으로 알려 온 상태와, 앞으로 이렇게 되어야 한다고 적어 둔 상태가 나란히 적힙니다. 이 종이를 디바이스 섀도우라고 부릅니다.
서버는 기기가 아니라 이 종이에 원하는 상태를 적습니다. 기기는 다시 붙었을 때 자기 종이를 읽고 어긋난 만큼만 따라갑니다. 따라간 뒤에는 바뀐 자기 상태를 다시 적어 둡니다.
sequenceDiagram
participant 서버 as 내 서버
participant 코어 as AWS IoT Core
participant 기기 as 조명 기기
기기->>코어: 마지막 상태를 적어 두고 끊긴다
서버->>코어: 원하는 상태를 적는다 · 밝기 낮춤
기기->>코어: 다시 붙는다
코어->>기기: 어긋난 대목을 알려 준다 · 밝기 낮춤
기기->>코어: 따라간 상태를 적는다
서버는 명령을 보낸 다음 기기가 지금 붙어 있는지 챙기지 않습니다. 붙어 있는지 확인하고, 안 붙어 있으면 어딘가에 적어 두었다가 다시 보내는 일을 서비스가 대신합니다.
받은 메시지를 넘기는 규칙
브로커가 받은 메시지를 내 서버가 계속 꺼내 가야 한다면, 서버는 결국 다시 상시로 떠 있어야 합니다. 그래서 어떤 이름표에 온 메시지를 어디로 넘길지를 서비스 쪽에 규칙으로 적어 둡니다. 온도 값은 저장소에 쌓고, 정해 둔 온도를 넘은 값만 알림으로 보내는 식입니다.
넘기는 곳은 대개 같은 회사의 다른 서비스입니다. 값을 쌓아 두는 Amazon S3(Simple Storage Service) 같은 저장소, 뒤 처리를 줄 세우는 큐, 값 하나마다 짧은 코드를 돌리는 AWS Lambda 같은 것입니다.
flowchart TD
subgraph D["기기 · 매장마다 하나씩"]
T1["온도계 A"]
T2["온도계 B"]
T3["온도계 C"]
end
D --> B["AWS IoT Core · 메시지 브로커"]
B --> S["내 서버"]
B --> ST["저장소"]
B --> Q["큐"]
받는 쪽이 하나가 아니어도 되는 것이 가운데를 둔 값입니다. 온도계는 자기 값을 누가 가져가는지 모른 채 올리고, 가져가는 쪽이 하나 더 늘어도 기기 쪽 코드는 그대로입니다.
보관은 브로커의 몫이 아닙니다. 브로커는 메시지가 지나가게 하는 통로이지 쌓아 두는 창고가 아닙니다. 나중에 다시 꺼내 볼 값이라면 규칙이 넘긴 저장소 쪽에 남습니다.
대신 맡기면서 치르는 대가
붙는 방식이 서비스 쪽에 정해져 있습니다. 기기가 쓰던 규약을 내가 직접 만들었다면 그대로는 못 붙입니다. 기기 쪽 코드를 서비스가 받아 주는 방식에 맞춰 고쳐야 합니다.
현장에 깔린 기기가 한 회사에 묶입니다. 서버 코드는 옮기면 그만이지만 기기는 한번 설치하면 몇 년씩 그 자리에 남습니다. 붙는 주소와 신분증 체계를 나중에 바꾸려면 흩어진 기기를 전부 손봐야 합니다.
요금은 붙어 있던 시간과 주고받은 메시지 수를 따라 붙습니다. 기기가 조용히 있어도 통로를 열어 두고 있는 동안은 계산에 들어갑니다. 기기가 늘면 그만큼 늘어납니다.
무슨 일이 벌어졌는지는 서비스가 내주는 기록으로만 봅니다. 내 서버 안에서 벌어진 일이 아니라 붙잡아 들여다볼 수 없습니다. 연결이 왜 끊겼는지 알아내는 방법이 그 기록 한 갈래로 줄어듭니다.
쓰는 경우와 쓰지 않는 경우
기기가 한 건물 안에 몇 대뿐이고 같은 네트워크에 있다면 브로커를 직접 하나 띄우는 편이 단순합니다. 연결 수가 적으면 서버가 직접 들고 있어도 부담이 되지 않습니다.
기기가 인터넷 너머 여러 곳에 흩어져 있고, 대수가 계속 늘고, 기기마다 따로 신원을 확인해야 한다면 이쪽이 맞습니다. 앞에서 본 부담을 직접 굴리는 값과 맡기는 값을 견주는 것이 판단 기준입니다.
사람이 쓰는 웹 화면이나 앱은 이 서비스로 붙이지 않습니다. 그쪽은 사람이 로그인하고 요청이 짧게 끝나서 보통의 웹 요청으로 충분합니다. 이 서비스가 상대하는 것은 앞에 사람이 없는 기기 쪽입니다.
관련 항목
AWS IoT Core 를 이루는 구성 요소
메시지 브로커 · 토픽 · 디바이스 섀도우 · 사물 레지스트리 · AWS IoT 규칙 · AWS IoT 정책
AWS IoT Core 가 속하는 상위 분류
AWS · 사물인터넷 · 관리형 서비스 · 클라우드 컴퓨팅 · 메시징 서비스
기기가 AWS IoT Core 에 붙을 때 쓰는 프로토콜
MQTT · 웹소켓 · HTTPS · TLS · TCP · LoRaWAN
기기의 신원을 확인하는 수단
인증서 · X.509 · 공개키 · 상호 TLS · 인증 기관 · 프로비저닝 · IAM
AWS IoT Core 가 메시지를 넘기는 서비스
Amazon S3 · Amazon SQS · Amazon SNS · AWS Lambda · Amazon DynamoDB · Amazon CloudWatch
상시 연결을 직접 감당할 때 걸리는 문제
파일 디스크립터 · 하트비트 · 타임아웃 · 지수 백오프 · 썬더링 허드 · 재접속
같은 역할을 두고 겨루는 다른 브로커
Eclipse Mosquitto · EMQX · HiveMQ · RabbitMQ · Azure IoT Hub
AWS IoT Core 에 붙는 기기 쪽 기술
임베디드 · 펌웨어 · 센서 · 엣지 컴퓨팅 · 게이트웨이 · OTA 업데이트
AWS IoT Core 가 따르는 메시지 전달 방식
다른 이름: IoT Core · aws iot core · 아이오티 코어