[AWS] IoT Core 개념과 사용법

yong·2025년 8월 29일

프로젝트에서 IoT 기기와의 통신을 재현할 일이 생겨 IoTCore를 사용하기 이전에 개념을 정리하고 간단한 실습을 해보았다.

IoT Core는 IoT 기기간, 혹은 기기와 애플리케이션 간의 통신을 위해 IoT 기기와 AWS 클라우드를 연결하는 AWS의 메시지 브로커 리소스이다.

먼저 메시지 브로커에 대해서 간단히 알아보고자 한다.

Message Broker

통신을 할 때 송신자로부터 전달받은 메시지를 수신자로 전달해주는 중간 역할로, 응용 소프트웨어 간에 메시지를 교환하는 중계자 역할

통신 모델에 따라 크게 Point-to-Point 방식과 Publish/Subscribe 방식의 메시지 브로커로 분류할 수 있다.

  • Point-to-Point 방식 (Queue 기반)
    생산자가 메시지를 큐에 넣고 소비자가 꺼내가는 방식으로 메시지는 1회만 소비된다는 특징이 있다. 대표적으로 RabbitMQ, ActiveMQ가 있다.

  • Publish/Subscribe 방식 (Topic 기반)
    생산자가 특정 Topic에 대한 메시지를 발행(publish)하면 해당 토픽을 구독(subscribe)한 모든 소비자가 메시지를 받게 된다. 대표적으로 Apache Kafka, AWS IoT Core가 있다.

이번 포스팅에서는 Pub/Sub 기반의 AWS IoT Core에 대해서 다루고자 한다.
(메시지 브로커에 대한 자세한 설명은 이 글을 참고.. "이 글"은 곧 작성 예정 🤓)

MQTT Broker

메시지 브로커는 프로토콜에 따라서도 분류할 수 있는데 MQTT Broker는 그중에서도 MQTT 프로토콜을 통해 통신하기 위한 메시지 브로커이다.

MQTT(Message Queuing Telemetry Transport)
사물 인터넷(IoT) 기기처럼 리소스가 제한적인 환경에서 기기 간(M2M) 통신을 위해 사용되는 가벼운 게시-구독 메시징 프로토콜

  • 클라우드 기반 MQTT Broker
    • AWS IoT Core
    • Azure IoT Hub
    • EMQX Cloud
  • 오픈소스 MQTT Broker
    • Eclipse Mosquitto
    • EMQX(EMQ)
    • RabbitMQ(MQTT Plugin 지원)

여기서 RabbitMQ가 MQTT Plugin을 지원한다는 것을 알고서는 MQTT 통신을 위해서 IoT Core를 사용하는 것이라면 "플러그인과 함께 RabbitMQ를 사용하여 MQTT 통신도 하고 다양한 스토리지와의 중계도 할 수 있는 것 아닌가?"라는 의문이 들었다.
하지만 플러그인만으로는 IoT에 특화된 메시지 중계가 어렵고 메시지를 한 번만 소비할 수 있기 때문에 저장과 재처리, 다슈 컨슈머 그룹을 구현하기 어렵다. Device Shadown, 대규모 인증서와 정책, Rules Engine 등을 제공하는 IoT Core와는 달리 직접 IoT 특화 기능을 구현해야 하고, 같은 메시지를 여러 시스템이 수신하기 위해서는 큐를 여러 개 만들어 바인딩해야 한다는 단점이 있다. 따라서 우리 프로젝트에는 IoT Core와 Kafka를 통해 데이터 스트리밍 파이프라인을 구축하는 게 적합하다는 결론을 내리게 되었다.

AWS IoT Core

IoT 디바이스를 다른 디바이스 및 AWS 서비스에 연결하는 클라우드 기반 메시지 브로커

구성

  • Device(Thing) : IoT 장치의 논리적 표현
  • 인증서 : 보안 자격을 증명하기 위한 인증서(X.509 인증서)
  • 정책 : 인증서의 권한 범위 설정
  • Message Broker : 다양한 프로토콜을 기반으로 디바이스와 클라우드 간의 메시지 전달
  • Rules Engine : IoT 데이터의 분석 및 AWS 서비스와의 연계를 위한 규칙 기반 엔진
  • Device Shadow : 디바이스의 상태를 저장하고 최신 상태를 유지하기 위해 클라우드에 저장된 JSON 문서

기능

  1. 디바이스 연결 및 관리
    다양한 프로토콜을 통해 IoT 디바이스가 AWS 클라우드에 쉽게 연결될 수 있도록 한다. (MQTT, MQTT over WSS, HTTPS, LoRaWAN 프로토콜 지원)

  2. 보안 및 인증
    X.509 인증서, AWS IAM, 정책을 기반으로 디바이스를 인증하고 디바이스와 사용자의 권한을 제어한다.

  3. 메시지 브로커 및 데이터 처리

  4. AWS 서비스 연동
    AWS의 다른 서비스와 긴밀하게 통합되어 강력한 데이터 분석 및 시각화 기능을 제공한다. (Lambda, S3, DynamoDB, Kinesis, QuickSight 등)

실습

1. 사물 생성 (인증서 생성)

물리적인 IoT 기기를 AWS IoT 안에서 사용할 수 있도록 논리적인 개체로 표현하는 작업

사물은 인증서, 정책, Shadow를 통해서 표현된다.

  1. AWS IoT 서비스/관리/사물 생성 메뉴에서 사물 생성

  2. 단일 사물 생성

  3. 사물 속성 및 디바이스 섀도우 사용 여부 지정
    추가 구성 항목이 많지만 일단 필수 속성인 이름만을 지정하고 넘어간다.

    통신이 되는지만 확인해볼 것이므로 디바이스 섀도우는 생성하지 않고 넘어간다.

  4. 디바이스 인증서 구성
    4-1. 디바이스를 AWS IoT에 연결하기 위해서는 인증서가 필요하므로 새로운 인증서를 생성하자.

    4-2. 인증서에 부여할 정책 설정
    AWS IoT 리소스에 대한 액세스를 허용하거나 거부하는 정책을 설정하는 단계로, 선택한 정책은 현재 생성하는 사물에 적용된다. 정책은 크게 도메인 제한, 정책 연결, 게시 및 구독, 보존된 메시지 관련, 인증서 관련으로 나뉜다.

    새로운 정책을 생성해보자.

  • 정책 효과 : 허용 또는 거부

  • 정책 작업
    MQTT 정책 작업, 디바이스 섀도우 정책 작업, 작업, 작업 증명 공급자 작업으로 나뉘는데 통신 연결을 테스트하기 위한 목적이므로 모든 작업을 허용하는 *을 선택한다.

  • 정책 리소스
    IoT Core 안에서 디바이스가 접근할 수 있는 대상(브로커 자원)을 의미한다.
    연결 대상인 클라이언트(디바이스), 토픽, 토픽 필터, Thing Shadow 등의 ARN(Amazon Resource Name)을 넣는다.

    mydevice1이라는 이름으로 디바이스를 연결하고, sensors/data/# 토픽에 메시지를 퍼블리시/구독하는 정책을 코드로 작성하면 다음과 같다.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-2:123456789012:client/mydevice1"
    },
    {
      "Effect": "Allow",
      "Action": ["iot:Publish", "iot:Receive"],
      "Resource": "arn:aws:iot:ap-northeast-2:123456789012:topic/sensors/data/#"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:ap-northeast-2:123456789012:topicfilter/sensors/data/#"
    }
  ]
}

하지만 실습에서는 *를 입력하여 모든 리소스에 접근할 수 있도록 했다.

생성한 인증서를 선택하고 사물을 생성하면 다음과 같이 인증서와 키를 다운로드 할 수 있다.

인증서와 각각의 키는 다음과 같은 역할을 한다.

1. 디바이스 인증서 (X.509 Certificate)
IoT 디바이스에 설치해서 디바이스가 자신을 증명하기 위해 사용하는 신분증 같은 것으로, 디바이스가 AWS IoT Core에 연결할 때 TLS(SSL) 핸드셰이크 과정에서 이 인증서를 사용해 자신을 증명한다.

파일 확장자: .pem.crt

2. 퍼블릭 키 파일 (Public Key)
공개 키 암호화의 공개 부분으로 인증서 안에도 포함돼 있기 때문에 직접 쓰일 일은 많지 않다. (주로 확인용이나 서명 검증에 활용)

파일 확장자: .pem.key

3. 프라이빗 키 파일 (Private Key)
공개 키와 짝을 이루는 비밀 키로 디바이스가 메시지에 서명하거나 AWS IoT Core와 TLS 연결을 맺을 때 사용한다. (외부 유출에 주의)

파일 확장자: .pem.key

4. 루트 CA 인증서 (Amazon Root CA)
AWS IoT Core가 진짜 AWS 서버임을 증명해 주는 인증서로 디바이스가 AWS IoT Core 브로커의 서버 인증서를 검증할 때 이 루트 CA를 기반으로 한다.

파일 확장자 : AmazonRootCA1.pem, AmazonRootCA3.pem


즉, 정리하자면 다음과 같다.

  • IoT 디바이스 ↔ AWS IoT Core 연결 시:
    AWS IoT Core는 서버 인증서를 디바이스에 제시
    → 디바이스는 루트 CA로 이것이 진짜 AWS임을 확인

  • 디바이스는 자신의 인증서 + 프라이빗 키로 신원을 증명
    → AWS IoT Core는 이 인증서가 등록된 인증서인지 확인

2. IoT 디바이스 준비 (가상의 Python 시뮬레이터 앱)

생성한 인증서를 실제 디바이스에 연결해야 하지만 IoT 디바이스가 없으므로 주기적으로 데이터를 생성해주는 시뮬레이터 앱으로 대체하고자 한다.

파이썬 3.13.2 버전으로 다음과 같이 시뮬레이터를 만들었다.

1. 가상 환경 생성
python3 -m venv venv
해당 프로젝트에 위에서 다운받은 인증서와 키 파일들을 위치시킨다.

2. 시뮬레이터 코드 작성
IoT Core를 연결하기 위해 필요한 엔드포인트는 IoT Core 메뉴의 설정에서 확인할 수 있다.

import time
import json
import random
import ssl
import paho.mqtt.client as mqtt

# AWS IoT Core 엔드포인트
ENDPOINT = "a1b2c3d4e5f6-ats.iot.ap-northeast-2.amazonaws.com"

# 인증서 및 키 파일 경로
CA_PATH = "./AmazonRootCA1.pem"
CERT_PATH = "./device-cym-cert.pem.crt"
KEY_PATH = "./private.pem.key"

# MQTT 설정
CLIENT_ID = "carDeviceSimulator"
TOPIC = "device-cym/data"

# 연결 콜백
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("✅ 연결 성공")
    else:
        print(f"❌ 연결 실패: {rc}")

def on_publish(client, userdata, mid):
    print(f"메시지 전송 완료 (mid: {mid})")

# MQTT 클라이언트 생성
client = mqtt.Client(client_id=CLIENT_ID)
client.tls_set(
    ca_certs=CA_PATH,
    certfile=CERT_PATH,
    keyfile=KEY_PATH,
    tls_version=ssl.PROTOCOL_TLSv1_2,
)
client.on_connect = on_connect
client.on_publish = on_publish

# AWS IoT Core 연결
client.connect(ENDPOINT, 8883, keepalive=60)
client.loop_start()

# 주기적으로 자동차 데이터 전송
try:
    latitude, longitude = 37.5665, 126.9780  # 서울 시청 근처 (기본 좌표)

    while True:
        # 속도는 0~120km/h 사이 무작위 값
        speed = round(random.uniform(0, 120), 2)

        # 위치는 약간씩 이동
        latitude += random.uniform(-0.0005, 0.0005)
        longitude += random.uniform(-0.0005, 0.0005)

        payload = {
            "vehicleId": "car001",
            "speed": speed,
            "location": {
                "lat": round(latitude, 6),
                "lon": round(longitude, 6)
            },
            "timestamp": int(time.time())
        }

        client.publish(TOPIC, json.dumps(payload), qos=1)
        print(f"📤 전송: {payload}")
        time.sleep(3)

except KeyboardInterrupt:
    print("⏹️ 종료")
    client.loop_stop()
    client.disconnect()

3. 연결 및 통신 확인

위에서 생성한 파이썬 앱을 실행시키고 IoT Core와 연결이 되는지 확인해보자.
IoT Core 메뉴에서 테스트/MQTT 테스트 클라이언트에서 확인할 수 있다.

앱에서 설정한 토픽을 구독하면 하단에 사진과 같이 IoT Core로 메시지가 들어오는 것을 확인할 수 있다.

profile
꿈틀꿈틀

0개의 댓글