์ฝ˜ํ…์ธ  ๋Œ€ํ‘œ ์ด๋ฏธ์ง€ - ๐Ÿš€ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์™€ AWS IoT Core ์—ฐ๋™ ์™„๋ฒฝ ๊ฐ€์ด๋“œ - ์‹ค์ „ ์†Œ์Šค์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” IoT ํด๋ผ์šฐ๋“œ ์—ฐ๊ฒฐ

๐Ÿš€ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์™€ AWS IoT Core ์—ฐ๋™ ์™„๋ฒฝ ๊ฐ€์ด๋“œ - ์‹ค์ „ ์†Œ์Šค์ฝ”๋“œ๋กœ ๋ฐฐ์šฐ๋Š” IoT ํด๋ผ์šฐ๋“œ ์—ฐ๊ฒฐ

์ดˆ๋ณด์ž๋„ ๋”ฐ๋ผํ•  ์ˆ˜ ์žˆ๋Š” ๋‹จ๊ณ„๋ณ„ ๊ตฌํ˜„ ๋ฐฉ๋ฒ•

๐ŸŽฏ ์™œ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์™€ AWS IoT Core๋ฅผ ์—ฐ๋™ํ• ๊นŒ?

์•ˆ๋…•! ์˜ค๋Š˜์€ ์ •๋ง ์žฌ๋ฏธ์žˆ๋Š” ์ฃผ์ œ๋ฅผ ๊ฐ€์ง€๊ณ  ์™”์–ด. ๋ฐ”๋กœ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์™€ AWS IoT Core๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์•ผ. ์š”์ฆ˜ IoT(์‚ฌ๋ฌผ์ธํ„ฐ๋„ท) ํ”„๋กœ์ ํŠธ๋ฅผ ํ•˜๋‹ค ๋ณด๋ฉด ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์šฐ๋“œ๋กœ ๋ณด๋‚ด๊ณ , ์›๊ฒฉ์œผ๋กœ ๋””๋ฐ”์ด์Šค๋ฅผ ์ œ์–ดํ•˜๊ณ  ์‹ถ์„ ๋•Œ๊ฐ€ ๋งŽ์ž–์•„? ๐Ÿค”

๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋Š” ์ €๋ ดํ•˜๋ฉด์„œ๋„ ๊ฐ•๋ ฅํ•œ ์‹ฑ๊ธ€๋ณด๋“œ ์ปดํ“จํ„ฐ๊ณ , AWS IoT Core๋Š” ์•„๋งˆ์กด์ด ์ œ๊ณตํ•˜๋Š” ๊ด€๋ฆฌํ˜• ํด๋ผ์šฐ๋“œ ์„œ๋น„์Šค์•ผ. ์ด ๋‘˜์„ ์—ฐ๊ฒฐํ•˜๋ฉด ์ •๋ง ๋ฉ‹์ง„ ์ผ๋“ค์„ ํ•  ์ˆ˜ ์žˆ์–ด:

โœจ ์—ฐ๋™ํ•˜๋ฉด ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค

โ€ข ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํด๋ผ์šฐ๋“œ์— ์ „์†ก
โ€ข ์ „ ์„ธ๊ณ„ ์–ด๋””์„œ๋“  ๋””๋ฐ”์ด์Šค ์›๊ฒฉ ์ œ์–ด
โ€ข ์ˆ˜์ง‘๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•˜๊ณ  ์‹œ๊ฐํ™”
โ€ข ๋‹ค๋ฅธ AWS ์„œ๋น„์Šค(Lambda, DynamoDB ๋“ฑ)์™€ ์ž๋™ ์—ฐ๊ณ„
โ€ข ๋””๋ฐ”์ด์Šค ์ƒํƒœ ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ์•Œ๋ฆผ ์„ค์ •

ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ IoT ๊ด€๋ จ ํ”„๋กœ์ ํŠธ๋ฅผ ์˜๋ขฐ๋ฐ›๊ฑฐ๋‚˜, ์ž์‹ ์˜ IoT ๊ฐœ๋ฐœ ์žฌ๋Šฅ์„ ๊ณต์œ ํ•˜๋ ค๋Š” ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ์ด ๊ธฐ์ˆ ์€ ์ •๋ง ์œ ์šฉํ•ด. ์‹ค์ œ๋กœ ๋งŽ์€ ๊ฐœ๋ฐœ์ž๋“ค์ด ์ด๋Ÿฐ ํด๋ผ์šฐ๋“œ ์—ฐ๋™ ๊ธฐ์ˆ ์„ ๋ฐฐ์šฐ๊ณ  ์‹ถ์–ด ํ•˜๊ฑฐ๋“ ! ๐Ÿ’ช

Raspberry Pi IoT Device AWS IoT Core Cloud Service MQTT Protocol Secure Connection TLS/SSL Encryption Sensor Data Real-time Transfer Cloud Processing

๐Ÿ› ๏ธ ์‚ฌ์ „ ์ค€๋น„์‚ฌํ•ญ

๋ณธ๊ฒฉ์ ์œผ๋กœ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ ์ „์— ํ•„์š”ํ•œ ๊ฒƒ๋“ค์„ ๋จผ์ € ์ค€๋น„ํ•ด๋ณด์ž. ๊ฑฑ์ • ๋งˆ, ํ•˜๋‚˜ํ•˜๋‚˜ ์ฐจ๊ทผ์ฐจ๊ทผ ์„ค๋ช…ํ•ด์ค„๊ฒŒ! ๐Ÿ˜Š

1ํ•˜๋“œ์›จ์–ด ์ค€๋น„

โ€ข ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด (3 Model B ์ด์ƒ ๊ถŒ์žฅ, 4๊ฐ€ ๋” ์ข‹์•„!)
โ€ข MicroSD ์นด๋“œ (์ตœ์†Œ 16GB, Class 10 ์ด์ƒ)
โ€ข ์ „์› ์–ด๋Œ‘ํ„ฐ (5V 2.5A ์ด์ƒ)
โ€ข ์ธํ„ฐ๋„ท ์—ฐ๊ฒฐ (WiFi ๋˜๋Š” ์ด๋”๋„ท)

2์†Œํ”„ํŠธ์›จ์–ด ์ค€๋น„

โ€ข Raspberry Pi OS (Raspbian) ์„ค์น˜
โ€ข Python 3.7 ์ด์ƒ
โ€ข AWS ๊ณ„์ • (ํ”„๋ฆฌํ‹ฐ์–ด๋กœ ์‹œ์ž‘ ๊ฐ€๋Šฅ!)
โ€ข AWS CLI ์„ค์น˜

3ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

โ€ข AWSIoTPythonSDK
โ€ข boto3 (AWS SDK for Python)
โ€ข ๊ธฐํƒ€ ์„ผ์„œ ๊ด€๋ จ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (ํ”„๋กœ์ ํŠธ์— ๋”ฐ๋ผ)

๐Ÿ’ก ํŒ: ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋ฅผ ์ฒ˜์Œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, SSH๋ฅผ ํ™œ์„ฑํ™”ํ•ด์„œ ์›๊ฒฉ์œผ๋กœ ์ ‘์†ํ•˜๋Š” ๊ฒŒ ํŽธํ•ด. ๋ชจ๋‹ˆํ„ฐ ์—†์ด๋„ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ๊ฑฐ๋“ !

โ˜๏ธ AWS IoT Core ์„ค์ •ํ•˜๊ธฐ

์ž, ์ด์ œ AWS ์ฝ˜์†”์—์„œ IoT Core๋ฅผ ์„ค์ •ํ•ด๋ณผ ๊ฑฐ์•ผ. ์ด ๋ถ€๋ถ„์ด ์ข€ ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ฒœ์ฒœํžˆ ๋”ฐ๋ผ์˜ค๋ฉด ๋ฌธ์ œ์—†์–ด! ๐ŸŽ“

๐Ÿ“‹ Step 1: IoT Thing ์ƒ์„ฑ

AWS IoT Core์—์„œ "Thing"์€ ์‹ค์ œ ๋ฌผ๋ฆฌ์  ๋””๋ฐ”์ด์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฐ€์ƒ ๊ฐ์ฒด์•ผ. ์šฐ๋ฆฌ์˜ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋ฅผ ๋“ฑ๋กํ•˜๋Š” ๊ฑฐ์ง€.

AWS ์ฝ˜์†”์—์„œ ์ง„ํ–‰ํ•˜๋Š” ์ˆœ์„œ:

1. AWS Management Console ๋กœ๊ทธ์ธ
2. IoT Core ์„œ๋น„์Šค ๊ฒ€์ƒ‰ ๋ฐ ์„ ํƒ
3. ์™ผ์ชฝ ๋ฉ”๋‰ด์—์„œ "๊ด€๋ฆฌ" โ†’ "์‚ฌ๋ฌผ" ํด๋ฆญ
4. "์‚ฌ๋ฌผ ์ƒ์„ฑ" ๋ฒ„ํŠผ ํด๋ฆญ
5. "๋‹จ์ผ ์‚ฌ๋ฌผ ์ƒ์„ฑ" ์„ ํƒ
6. ์‚ฌ๋ฌผ ์ด๋ฆ„ ์ž…๋ ฅ (์˜ˆ: MyRaspberryPi)
7. ๋‹ค์Œ ๋‹จ๊ณ„๋กœ ์ง„ํ–‰

๐Ÿ” Step 2: ์ธ์ฆ์„œ ์ƒ์„ฑ ๋ฐ ๋‹ค์šด๋กœ๋“œ

๋ณด์•ˆ์ด ์ •๋ง ์ค‘์š”ํ•ด! AWS IoT Core๋Š” X.509 ์ธ์ฆ์„œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋””๋ฐ”์ด์Šค๋ฅผ ์ธ์ฆํ•ด. ์ด ์ธ์ฆ์„œ๋“ค์€ ๋ฐ˜๋“œ์‹œ ์•ˆ์ „ํ•˜๊ฒŒ ๋ณด๊ด€ํ•ด์•ผ ํ•ด.

โš ๏ธ ์ฃผ์˜์‚ฌํ•ญ: ์ธ์ฆ์„œ๋Š” ์ƒ์„ฑ ์‹œ ํ•œ ๋ฒˆ๋งŒ ๋‹ค์šด๋กœ๋“œํ•  ์ˆ˜ ์žˆ์–ด. ๋‚˜์ค‘์— ๋‹ค์‹œ ๋ฐ›์„ ์ˆ˜ ์—†์œผ๋‹ˆ ๊ผญ ๋ฐฑ์—…ํ•ด๋‘ฌ!

๋‹ค์šด๋กœ๋“œํ•ด์•ผ ํ•  ํŒŒ์ผ๋“ค:

โ€ข ๋””๋ฐ”์ด์Šค ์ธ์ฆ์„œ (xxxxx-certificate.pem.crt)
โ€ข ํ”„๋ผ์ด๋น— ํ‚ค (xxxxx-private.pem.key)
โ€ข ํผ๋ธ”๋ฆญ ํ‚ค (xxxxx-public.pem.key)
โ€ข ๋ฃจํŠธ CA ์ธ์ฆ์„œ (AmazonRootCA1.pem)

๐Ÿ“œ Step 3: ์ •์ฑ…(Policy) ์ƒ์„ฑ ๋ฐ ์—ฐ๊ฒฐ

์ •์ฑ…์€ ๋””๋ฐ”์ด์Šค๊ฐ€ AWS IoT Core์—์„œ ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์ •์˜ํ•˜๋Š” ๊ฑฐ์•ผ. JSON ํ˜•์‹์œผ๋กœ ์ž‘์„ฑ๋˜์ง€.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iot:Connect"
      ],
      "Resource": "arn:aws:iot:ap-northeast-2:YOUR_ACCOUNT_ID:client/MyRaspberryPi"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Publish",
        "iot:Receive"
      ],
      "Resource": "arn:aws:iot:ap-northeast-2:YOUR_ACCOUNT_ID:topic/*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "iot:Subscribe"
      ],
      "Resource": "arn:aws:iot:ap-northeast-2:YOUR_ACCOUNT_ID:topicfilter/*"
    }
  ]
}

์ด ์ •์ฑ…์€ ๋””๋ฐ”์ด์Šค๊ฐ€:

โ€ข IoT Core์— ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๊ณ  (Connect)
โ€ข ๋ชจ๋“  ํ† ํ”ฝ์— ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ  (Publish)
โ€ข ๋ชจ๋“  ํ† ํ”ฝ์„ ๊ตฌ๋…ํ•  ์ˆ˜ ์žˆ๊ฒŒ (Subscribe) ํ•ด์ค˜.

๐Ÿ’ก ๋ณด์•ˆ ํŒ: ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ๋Š” ์™€์ผ๋“œ์นด๋“œ(*) ๋Œ€์‹  ๊ตฌ์ฒด์ ์ธ ํ† ํ”ฝ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ๊ฒŒ ์ข‹์•„. ๋ณด์•ˆ์ด ํ›จ์”ฌ ๊ฐ•ํ™”๋˜๊ฑฐ๋“ !

๐Ÿ”— Step 4: ์—”๋“œํฌ์ธํŠธ ํ™•์ธ

AWS IoT Core ์—”๋“œํฌ์ธํŠธ๋Š” ๋””๋ฐ”์ด์Šค๊ฐ€ ์—ฐ๊ฒฐํ•  ์ฃผ์†Œ์•ผ. ์ด๊ฑธ ํ™•์ธํ•˜๋ ค๋ฉด:

1. IoT Core ์ฝ˜์†”์—์„œ "์„ค์ •" ๋ฉ”๋‰ด ํด๋ฆญ
2. "๋””๋ฐ”์ด์Šค ๋ฐ์ดํ„ฐ ์—”๋“œํฌ์ธํŠธ" ํ•ญ๋ชฉ ํ™•์ธ
3. ์ฃผ์†Œ๋ฅผ ๋ณต์‚ฌํ•ด๋‘ฌ (์˜ˆ: xxxxx.iot.ap-northeast-2.amazonaws.com)

๐Ÿ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด ํ™˜๊ฒฝ ์„ค์ •

์ด์ œ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์—์„œ ์ž‘์—…ํ•  ์ฐจ๋ก€์•ผ! SSH๋กœ ์ ‘์†ํ–ˆ๋‹ค๋ฉด ํ„ฐ๋ฏธ๋„์—์„œ ๋‹ค์Œ ๋ช…๋ น์–ด๋“ค์„ ์‹คํ–‰ํ•ด๋ณด์ž. ๐Ÿ–ฅ๏ธ

ํŒจํ‚ค์ง€ ์—…๋ฐ์ดํŠธ ๋ฐ Python ์„ค์น˜

# ์‹œ์Šคํ…œ ํŒจํ‚ค์ง€ ์—…๋ฐ์ดํŠธ
sudo apt-get update
sudo apt-get upgrade -y

# Python3 ๋ฐ pip ์„ค์น˜ ํ™•์ธ
python3 --version
pip3 --version

# ํ•„์š”ํ•œ ๊ฒฝ์šฐ pip ์—…๊ทธ๋ ˆ์ด๋“œ
sudo pip3 install --upgrade pip

AWS IoT SDK ์„ค์น˜

# AWS IoT Python SDK ์„ค์น˜
pip3 install AWSIoTPythonSDK

# ์ถ”๊ฐ€๋กœ ์œ ์šฉํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค
pip3 install boto3
pip3 install paho-mqtt

์ธ์ฆ์„œ ํŒŒ์ผ ๋ฐฐ์น˜

์•ž์„œ ๋‹ค์šด๋กœ๋“œํ•œ ์ธ์ฆ์„œ ํŒŒ์ผ๋“ค์„ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋กœ ์˜ฎ๊ฒจ์•ผ ํ•ด. ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ๋Š”๋ฐ, ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ SCP๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฑฐ์•ผ.

# ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์— certs ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ
mkdir -p ~/aws-iot/certs
cd ~/aws-iot/certs

# ๋กœ์ปฌ PC์—์„œ SCP๋กœ ํŒŒ์ผ ์ „์†ก (๋กœ์ปฌ PC ํ„ฐ๋ฏธ๋„์—์„œ ์‹คํ–‰)
scp /path/to/certificate.pem.crt pi@raspberrypi.local:~/aws-iot/certs/
scp /path/to/private.pem.key pi@raspberrypi.local:~/aws-iot/certs/
scp /path/to/AmazonRootCA1.pem pi@raspberrypi.local:~/aws-iot/certs/

# ํŒŒ์ผ ๊ถŒํ•œ ์„ค์ • (๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์—์„œ)
chmod 644 ~/aws-iot/certs/*.crt
chmod 600 ~/aws-iot/certs/*.key

๐Ÿ’ก ํŒ: ํŒŒ์ผ ๊ถŒํ•œ ์„ค์ •์ด ์ค‘์š”ํ•ด! ํ”„๋ผ์ด๋น— ํ‚ค๋Š” ์†Œ์œ ์ž๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก 600์œผ๋กœ ์„ค์ •ํ•ด์•ผ ๋ณด์•ˆ์ด ์œ ์ง€๋ผ.

๐Ÿ’ป ์‹ค์ „ ์†Œ์Šค์ฝ”๋“œ - ๊ธฐ๋ณธ ์—ฐ๊ฒฐ

๋“œ๋””์–ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์‹œ๊ฐ„์ด์•ผ! ๋จผ์ € ๊ฐ€์žฅ ๊ธฐ๋ณธ์ ์ธ ์—ฐ๊ฒฐ ์ฝ”๋“œ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด๋ณด์ž. ์ด ์ฝ”๋“œ๋Š” ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋ฅผ AWS IoT Core์— ์—ฐ๊ฒฐํ•˜๊ณ , ๊ฐ„๋‹จํ•œ ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๋Š” ์˜ˆ์ œ์•ผ. ๐Ÿš€

๐Ÿ“ basic_connection.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
AWS IoT Core ๊ธฐ๋ณธ ์—ฐ๊ฒฐ ์˜ˆ์ œ
๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์—์„œ AWS IoT Core์— ์—ฐ๊ฒฐํ•˜๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•ฉ๋‹ˆ๋‹ค.
"""

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
import random

# AWS IoT Core ์„ค์ •
IOT_ENDPOINT = "xxxxx.iot.ap-northeast-2.amazonaws.com"  # ์—ฌ๊ธฐ์— ์‹ค์ œ ์—”๋“œํฌ์ธํŠธ ์ž…๋ ฅ
CLIENT_ID = "MyRaspberryPi"
TOPIC = "raspberry/data"

# ์ธ์ฆ์„œ ํŒŒ์ผ ๊ฒฝ๋กœ
ROOT_CA = "/home/pi/aws-iot/certs/AmazonRootCA1.pem"
PRIVATE_KEY = "/home/pi/aws-iot/certs/private.pem.key"
CERTIFICATE = "/home/pi/aws-iot/certs/certificate.pem.crt"

def init_mqtt_client():
    """
    MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ๋ฐ ์„ค์ •
    """
    # MQTT ํด๋ผ์ด์–ธํŠธ ์ƒ์„ฑ
    mqtt_client = AWSIoTMQTTClient(CLIENT_ID)
    mqtt_client.configureEndpoint(IOT_ENDPOINT, 8883)
    
    # ์ธ์ฆ์„œ ์„ค์ •
    mqtt_client.configureCredentials(ROOT_CA, PRIVATE_KEY, CERTIFICATE)
    
    # MQTT ์—ฐ๊ฒฐ ์„ค์ •
    mqtt_client.configureAutoReconnectBackoffTime(1, 32, 20)
    mqtt_client.configureOfflinePublishQueueing(-1)  # ๋ฌด์ œํ•œ ํ์ž‰
    mqtt_client.configureDrainingFrequency(2)  # 2Hz๋กœ ๋“œ๋ ˆ์ด๋‹
    mqtt_client.configureConnectDisconnectTimeout(10)  # 10์ดˆ
    mqtt_client.configureMQTTOperationTimeout(5)  # 5์ดˆ
    
    return mqtt_client

def publish_message(client, topic, message):
    """
    ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ํ•จ์ˆ˜
    """
    try:
        message_json = json.dumps(message)
        client.publish(topic, message_json, 1)
        print(f"โœ… ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์„ฑ๊ณต: {message_json}")
        return True
    except Exception as e:
        print(f"โŒ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์‹คํŒจ: {str(e)}")
        return False

def main():
    """
    ๋ฉ”์ธ ์‹คํ–‰ ํ•จ์ˆ˜
    """
    print("๐Ÿš€ AWS IoT Core ์—ฐ๊ฒฐ ์‹œ์ž‘...")
    
    # MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
    mqtt_client = init_mqtt_client()
    
    # AWS IoT Core์— ์—ฐ๊ฒฐ
    try:
        mqtt_client.connect()
        print("โœ… AWS IoT Core ์—ฐ๊ฒฐ ์„ฑ๊ณต!")
    except Exception as e:
        print(f"โŒ ์—ฐ๊ฒฐ ์‹คํŒจ: {str(e)}")
        return
    
    # ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ๋ฃจํ”„
    message_count = 0
    
    try:
        while True:
            message_count += 1
            
            # ์„ผ์„œ ๋ฐ์ดํ„ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ (์‹ค์ œ๋กœ๋Š” ์„ผ์„œ์—์„œ ์ฝ์–ด์˜ด)
            temperature = round(random.uniform(20.0, 30.0), 2)
            humidity = round(random.uniform(40.0, 70.0), 2)
            
            # ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ
            message = {
                "device_id": CLIENT_ID,
                "timestamp": int(time.time()),
                "message_id": message_count,
                "data": {
                    "temperature": temperature,
                    "humidity": humidity
                }
            }
            
            # ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
            publish_message(mqtt_client, TOPIC, message)
            
            # 5์ดˆ ๋Œ€๊ธฐ
            time.sleep(5)
            
    except KeyboardInterrupt:
        print("\nโน๏ธ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์ค‘...")
    
    finally:
        # ์—ฐ๊ฒฐ ํ•ด์ œ
        mqtt_client.disconnect()
        print("๐Ÿ‘‹ AWS IoT Core ์—ฐ๊ฒฐ ํ•ด์ œ ์™„๋ฃŒ")

if __name__ == "__main__":
    main()

์ด ์ฝ”๋“œ์˜ ํ•ต์‹ฌ ํฌ์ธํŠธ๋ฅผ ์„ค๋ช…ํ•ด์ค„๊ฒŒ:

๐Ÿ”‘ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ

1. ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”: AWSIoTMQTTClient ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์—”๋“œํฌ์ธํŠธ์™€ ์ธ์ฆ์„œ๋ฅผ ์„ค์ •ํ•ด.

2. ์—ฐ๊ฒฐ ์„ค์ •: ์ž๋™ ์žฌ์—ฐ๊ฒฐ, ์˜คํ”„๋ผ์ธ ํ์ž‰ ๋“ฑ ์•ˆ์ •์ ์ธ ์—ฐ๊ฒฐ์„ ์œ„ํ•œ ์„ค์ •๋“ค์ด์•ผ.

3. ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰: JSON ํ˜•์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ตฌ์กฐํ™”ํ•ด์„œ MQTT ํ† ํ”ฝ์œผ๋กœ ๋ฐœํ–‰ํ•ด.

4. ์—๋Ÿฌ ์ฒ˜๋ฆฌ: try-except ๋ธ”๋ก์œผ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์—๋Ÿฌ๋ฅผ ์ฒ˜๋ฆฌํ•ด.

์‹คํ–‰ ๋ฐฉ๋ฒ•

# ํŒŒ์ผ ์‹คํ–‰ ๊ถŒํ•œ ๋ถ€์—ฌ
chmod +x basic_connection.py

# ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰
python3 basic_connection.py

์ •์ƒ์ ์œผ๋กœ ์‹คํ–‰๋˜๋ฉด 5์ดˆ๋งˆ๋‹ค ์˜จ๋„์™€ ์Šต๋„ ๋ฐ์ดํ„ฐ๊ฐ€ AWS IoT Core๋กœ ์ „์†ก๋ผ. AWS ์ฝ˜์†”์˜ "ํ…Œ์ŠคํŠธ" ๋ฉ”๋‰ด์—์„œ ํ† ํ”ฝ์„ ๊ตฌ๋…ํ•˜๋ฉด ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๊ฐ€ ๋“ค์–ด์˜ค๋Š” ๊ฑธ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด! ๐Ÿ˜Š

๐Ÿ“ก ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ - ์–‘๋ฐฉํ–ฅ ํ†ต์‹ 

์ด์ œ ์ข€ ๋” ์žฌ๋ฏธ์žˆ๋Š” ๊ฑธ ํ•ด๋ณผ๊นŒ? ๋‹จ์ˆœํžˆ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณด๋‚ด๊ธฐ๋งŒ ํ•˜๋Š” ๊ฒŒ ์•„๋‹ˆ๋ผ, ํด๋ผ์šฐ๋“œ์—์„œ ๋ช…๋ น์„ ๋ฐ›์•„์„œ ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋ฅผ ์ œ์–ดํ•˜๋Š” ์–‘๋ฐฉํ–ฅ ํ†ต์‹ ์„ ๊ตฌํ˜„ํ•ด๋ณด์ž! ๐Ÿ”„

๐Ÿ“ bidirectional_communication.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
AWS IoT Core ์–‘๋ฐฉํ–ฅ ํ†ต์‹  ์˜ˆ์ œ
๋ฉ”์‹œ์ง€๋ฅผ ๋ฐœํ–‰ํ•˜๊ณ  ๊ตฌ๋…ํ•˜์—ฌ ์›๊ฒฉ ์ œ์–ด๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
"""

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
import random
import threading

# AWS IoT Core ์„ค์ •
IOT_ENDPOINT = "xxxxx.iot.ap-northeast-2.amazonaws.com"
CLIENT_ID = "MyRaspberryPi"
PUBLISH_TOPIC = "raspberry/telemetry"
SUBSCRIBE_TOPIC = "raspberry/command"

# ์ธ์ฆ์„œ ํŒŒ์ผ ๊ฒฝ๋กœ
ROOT_CA = "/home/pi/aws-iot/certs/AmazonRootCA1.pem"
PRIVATE_KEY = "/home/pi/aws-iot/certs/private.pem.key"
CERTIFICATE = "/home/pi/aws-iot/certs/certificate.pem.crt"

# ๋””๋ฐ”์ด์Šค ์ƒํƒœ
device_state = {
    "led_status": "OFF",
    "reporting_interval": 5,
    "active": True
}

def custom_callback(client, userdata, message):
    """
    ๋ฉ”์‹œ์ง€ ์ˆ˜์‹  ์ฝœ๋ฐฑ ํ•จ์ˆ˜
    ํด๋ผ์šฐ๋“œ์—์„œ ๋ช…๋ น์„ ๋ฐ›์œผ๋ฉด ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
    """
    try:
        payload = json.loads(message.payload.decode('utf-8'))
        print(f"\n๐Ÿ“จ ๋ช…๋ น ์ˆ˜์‹ : {json.dumps(payload, indent=2)}")
        
        # ๋ช…๋ น ํƒ€์ž…์— ๋”ฐ๋ผ ์ฒ˜๋ฆฌ
        command_type = payload.get("command")
        
        if command_type == "LED_CONTROL":
            # LED ์ œ์–ด ๋ช…๋ น
            led_action = payload.get("action")
            if led_action in ["ON", "OFF"]:
                device_state["led_status"] = led_action
                print(f"๐Ÿ’ก LED ์ƒํƒœ ๋ณ€๊ฒฝ: {led_action}")
                
                # ์‹ค์ œ๋กœ๋Š” GPIO๋ฅผ ์ œ์–ดํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋“ค์–ด๊ฐ
                # import RPi.GPIO as GPIO
                # GPIO.output(LED_PIN, GPIO.HIGH if led_action == "ON" else GPIO.LOW)
                
        elif command_type == "SET_INTERVAL":
            # ๋ณด๊ณ  ์ฃผ๊ธฐ ๋ณ€๊ฒฝ ๋ช…๋ น
            new_interval = payload.get("interval", 5)
            if 1 <= new_interval <= 60:
                device_state["reporting_interval"] = new_interval
                print(f"โฑ๏ธ ๋ณด๊ณ  ์ฃผ๊ธฐ ๋ณ€๊ฒฝ: {new_interval}์ดˆ")
                
        elif command_type == "GET_STATUS":
            # ์ƒํƒœ ์กฐํšŒ ๋ช…๋ น
            print("๐Ÿ“Š ํ˜„์žฌ ์ƒํƒœ ์ „์†ก ์š”์ฒญ")
            publish_status(client)
            
        elif command_type == "REBOOT":
            # ์žฌ๋ถ€ํŒ… ๋ช…๋ น
            print("๐Ÿ”„ ์žฌ๋ถ€ํŒ… ๋ช…๋ น ์ˆ˜์‹ ")
            device_state["active"] = False
            
        else:
            print(f"โš ๏ธ ์•Œ ์ˆ˜ ์—†๋Š” ๋ช…๋ น: {command_type}")
            
    except Exception as e:
        print(f"โŒ ์ฝœ๋ฐฑ ์ฒ˜๋ฆฌ ์˜ค๋ฅ˜: {str(e)}")

def init_mqtt_client():
    """
    MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
    """
    mqtt_client = AWSIoTMQTTClient(CLIENT_ID)
    mqtt_client.configureEndpoint(IOT_ENDPOINT, 8883)
    mqtt_client.configureCredentials(ROOT_CA, PRIVATE_KEY, CERTIFICATE)
    
    # ์—ฐ๊ฒฐ ์„ค์ •
    mqtt_client.configureAutoReconnectBackoffTime(1, 32, 20)
    mqtt_client.configureOfflinePublishQueueing(-1)
    mqtt_client.configureDrainingFrequency(2)
    mqtt_client.configureConnectDisconnectTimeout(10)
    mqtt_client.configureMQTTOperationTimeout(5)
    
    return mqtt_client

def publish_telemetry(client):
    """
    ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ๋ฐ์ดํ„ฐ ๋ฐœํ–‰
    """
    # ์„ผ์„œ ๋ฐ์ดํ„ฐ ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    temperature = round(random.uniform(20.0, 30.0), 2)
    humidity = round(random.uniform(40.0, 70.0), 2)
    cpu_temp = round(random.uniform(40.0, 60.0), 2)
    
    message = {
        "device_id": CLIENT_ID,
        "timestamp": int(time.time()),
        "telemetry": {
            "temperature": temperature,
            "humidity": humidity,
            "cpu_temperature": cpu_temp
        },
        "state": {
            "led_status": device_state["led_status"],
            "reporting_interval": device_state["reporting_interval"]
        }
    }
    
    try:
        message_json = json.dumps(message)
        client.publish(PUBLISH_TOPIC, message_json, 1)
        print(f"๐Ÿ“ค ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ์ „์†ก: ์˜จ๋„={temperature}ยฐC, ์Šต๋„={humidity}%")
    except Exception as e:
        print(f"โŒ ์ „์†ก ์‹คํŒจ: {str(e)}")

def publish_status(client):
    """
    ๋””๋ฐ”์ด์Šค ์ƒํƒœ ๋ฐœํ–‰
    """
    status_message = {
        "device_id": CLIENT_ID,
        "timestamp": int(time.time()),
        "type": "status_report",
        "status": device_state
    }
    
    try:
        client.publish(PUBLISH_TOPIC, json.dumps(status_message), 1)
        print("๐Ÿ“Š ์ƒํƒœ ๋ณด๊ณ  ์ „์†ก ์™„๋ฃŒ")
    except Exception as e:
        print(f"โŒ ์ƒํƒœ ์ „์†ก ์‹คํŒจ: {str(e)}")

def main():
    """
    ๋ฉ”์ธ ์‹คํ–‰ ํ•จ์ˆ˜
    """
    print("๐Ÿš€ AWS IoT Core ์–‘๋ฐฉํ–ฅ ํ†ต์‹  ์‹œ์ž‘...")
    
    # MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
    mqtt_client = init_mqtt_client()
    
    # ์—ฐ๊ฒฐ
    try:
        mqtt_client.connect()
        print("โœ… AWS IoT Core ์—ฐ๊ฒฐ ์„ฑ๊ณต!")
    except Exception as e:
        print(f"โŒ ์—ฐ๊ฒฐ ์‹คํŒจ: {str(e)}")
        return
    
    # ๋ช…๋ น ํ† ํ”ฝ ๊ตฌ๋…
    try:
        mqtt_client.subscribe(SUBSCRIBE_TOPIC, 1, custom_callback)
        print(f"โœ… ํ† ํ”ฝ ๊ตฌ๋… ์„ฑ๊ณต: {SUBSCRIBE_TOPIC}")
    except Exception as e:
        print(f"โŒ ๊ตฌ๋… ์‹คํŒจ: {str(e)}")
        return
    
    # ์ดˆ๊ธฐ ์ƒํƒœ ์ „์†ก
    time.sleep(2)
    publish_status(mqtt_client)
    
    # ๋ฉ”์ธ ๋ฃจํ”„
    try:
        while device_state["active"]:
            # ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ๋ฐ์ดํ„ฐ ์ „์†ก
            publish_telemetry(mqtt_client)
            
            # ์„ค์ •๋œ ์ฃผ๊ธฐ๋งŒํผ ๋Œ€๊ธฐ
            time.sleep(device_state["reporting_interval"])
            
    except KeyboardInterrupt:
        print("\nโน๏ธ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์ค‘...")
    
    finally:
        mqtt_client.disconnect()
        print("๐Ÿ‘‹ AWS IoT Core ์—ฐ๊ฒฐ ํ•ด์ œ ์™„๋ฃŒ")

if __name__ == "__main__":
    main()

์ด ์ฝ”๋“œ๋Š” ํ›จ์”ฌ ๋” ๊ฐ•๋ ฅํ•ด! ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณผ๊นŒ? ๐ŸŽฏ

๐ŸŽฎ ๊ตฌํ˜„๋œ ๊ธฐ๋Šฅ๋“ค

โ€ข ํ…”๋ ˆ๋ฉ”ํŠธ๋ฆฌ ์ „์†ก: ์ฃผ๊ธฐ์ ์œผ๋กœ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํด๋ผ์šฐ๋“œ๋กœ ์ „์†ก
โ€ข ๋ช…๋ น ์ˆ˜์‹ : ํด๋ผ์šฐ๋“œ์—์„œ ๋ณด๋‚ธ ๋ช…๋ น์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ›์•„์„œ ์ฒ˜๋ฆฌ
โ€ข LED ์ œ์–ด: ์›๊ฒฉ์œผ๋กœ LED๋ฅผ ์ผœ๊ณ  ๋Œ ์ˆ˜ ์žˆ์Œ
โ€ข ์„ค์ • ๋ณ€๊ฒฝ: ๋ฐ์ดํ„ฐ ์ „์†ก ์ฃผ๊ธฐ๋ฅผ ๋™์ ์œผ๋กœ ์กฐ์ •
โ€ข ์ƒํƒœ ์กฐํšŒ: ํ˜„์žฌ ๋””๋ฐ”์ด์Šค ์ƒํƒœ๋ฅผ ์š”์ฒญํ•˜๋ฉด ์ฆ‰์‹œ ์‘๋‹ต
โ€ข ์žฌ๋ถ€ํŒ…: ์›๊ฒฉ์œผ๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ์ข…๋ฃŒํ•  ์ˆ˜ ์žˆ์Œ

๋ช…๋ น ์ „์†ก ํ…Œ์ŠคํŠธ

AWS IoT Core ์ฝ˜์†”์˜ "ํ…Œ์ŠคํŠธ" ๋ฉ”๋‰ด์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์„ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์–ด:

// LED ์ผœ๊ธฐ
{
  "command": "LED_CONTROL",
  "action": "ON"
}

// ๋ณด๊ณ  ์ฃผ๊ธฐ ๋ณ€๊ฒฝ (10์ดˆ๋กœ)
{
  "command": "SET_INTERVAL",
  "interval": 10
}

// ์ƒํƒœ ์กฐํšŒ
{
  "command": "GET_STATUS"
}

๐Ÿ”ง ์‹ค์ œ ์„ผ์„œ ์—ฐ๋™ ์˜ˆ์ œ

์ด๋ก ๋งŒ์œผ๋กœ๋Š” ์žฌ๋ฏธ์—†์ง€! ์‹ค์ œ ์„ผ์„œ๋ฅผ ์—ฐ๊ฒฐํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ง‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ค์–ด๋ณด์ž. DHT22 ์˜จ์Šต๋„ ์„ผ์„œ๋ฅผ ์˜ˆ๋กœ ๋“ค๊ฒŒ. ๐ŸŒก๏ธ

๐Ÿ“ sensor_integration.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
์‹ค์ œ ์„ผ์„œ ์—ฐ๋™ ์˜ˆ์ œ (DHT22 ์˜จ์Šต๋„ ์„ผ์„œ)
"""

from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient
import json
import time
import sys

# DHT22 ์„ผ์„œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (์„ค์น˜ ํ•„์š”: pip3 install Adafruit_DHT)
try:
    import Adafruit_DHT
    SENSOR_AVAILABLE = True
except ImportError:
    print("โš ๏ธ Adafruit_DHT ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.")
    SENSOR_AVAILABLE = False
    import random

# AWS IoT Core ์„ค์ •
IOT_ENDPOINT = "xxxxx.iot.ap-northeast-2.amazonaws.com"
CLIENT_ID = "RaspberryPi_Sensor"
TOPIC = "home/environment"

# ์ธ์ฆ์„œ ํŒŒ์ผ ๊ฒฝ๋กœ
ROOT_CA = "/home/pi/aws-iot/certs/AmazonRootCA1.pem"
PRIVATE_KEY = "/home/pi/aws-iot/certs/private.pem.key"
CERTIFICATE = "/home/pi/aws-iot/certs/certificate.pem.crt"

# ์„ผ์„œ ์„ค์ •
DHT_SENSOR = Adafruit_DHT.DHT22 if SENSOR_AVAILABLE else None
DHT_PIN = 4  # GPIO 4๋ฒˆ ํ•€

class SensorReader:
    """
    ์„ผ์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ ํด๋ž˜์Šค
    """
    def __init__(self):
        self.last_temperature = None
        self.last_humidity = None
        self.error_count = 0
        
    def read_sensor(self):
        """
        ์„ผ์„œ์—์„œ ๋ฐ์ดํ„ฐ ์ฝ๊ธฐ
        """
        if SENSOR_AVAILABLE:
            try:
                humidity, temperature = Adafruit_DHT.read_retry(DHT_SENSOR, DHT_PIN)
                
                if humidity is not None and temperature is not None:
                    self.last_temperature = round(temperature, 2)
                    self.last_humidity = round(humidity, 2)
                    self.error_count = 0
                    return True
                else:
                    self.error_count += 1
                    print(f"โš ๏ธ ์„ผ์„œ ์ฝ๊ธฐ ์‹คํŒจ (์‹œ๋„ {self.error_count}ํšŒ)")
                    return False
                    
            except Exception as e:
                self.error_count += 1
                print(f"โŒ ์„ผ์„œ ์˜ค๋ฅ˜: {str(e)}")
                return False
        else:
            # ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ
            self.last_temperature = round(random.uniform(20.0, 30.0), 2)
            self.last_humidity = round(random.uniform(40.0, 70.0), 2)
            return True
    
    def get_data(self):
        """
        ๋งˆ์ง€๋ง‰์œผ๋กœ ์ฝ์€ ๋ฐ์ดํ„ฐ ๋ฐ˜ํ™˜
        """
        return {
            "temperature": self.last_temperature,
            "humidity": self.last_humidity
        }
    
    def is_healthy(self):
        """
        ์„ผ์„œ ์ƒํƒœ ํ™•์ธ
        """
        return self.error_count < 5

def calculate_heat_index(temperature, humidity):
    """
    ์ฒด๊ฐ์˜จ๋„(Heat Index) ๊ณ„์‚ฐ
    """
    if temperature < 27:
        return temperature
    
    # ๊ฐ„๋‹จํ•œ ์ฒด๊ฐ์˜จ๋„ ๊ณต์‹
    hi = -8.78469475556 + \
         1.61139411 * temperature + \
         2.33854883889 * humidity + \
         -0.14611605 * temperature * humidity + \
         -0.012308094 * temperature**2 + \
         -0.0164248277778 * humidity**2 + \
         0.002211732 * temperature**2 * humidity + \
         0.00072546 * temperature * humidity**2 + \
         -0.000003582 * temperature**2 * humidity**2
    
    return round(hi, 2)

def init_mqtt_client():
    """
    MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
    """
    mqtt_client = AWSIoTMQTTClient(CLIENT_ID)
    mqtt_client.configureEndpoint(IOT_ENDPOINT, 8883)
    mqtt_client.configureCredentials(ROOT_CA, PRIVATE_KEY, CERTIFICATE)
    
    mqtt_client.configureAutoReconnectBackoffTime(1, 32, 20)
    mqtt_client.configureOfflinePublishQueueing(-1)
    mqtt_client.configureDrainingFrequency(2)
    mqtt_client.configureConnectDisconnectTimeout(10)
    mqtt_client.configureMQTTOperationTimeout(5)
    
    return mqtt_client

def publish_sensor_data(client, sensor_reader):
    """
    ์„ผ์„œ ๋ฐ์ดํ„ฐ ๋ฐœํ–‰
    """
    # ์„ผ์„œ ์ฝ๊ธฐ
    if not sensor_reader.read_sensor():
        print("โš ๏ธ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
        return False
    
    # ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ
    data = sensor_reader.get_data()
    temperature = data["temperature"]
    humidity = data["humidity"]
    
    # ์ฒด๊ฐ์˜จ๋„ ๊ณ„์‚ฐ
    heat_index = calculate_heat_index(temperature, humidity)
    
    # ์พŒ์ ๋„ ํŒ๋‹จ
    comfort_level = "comfortable"
    if temperature > 28 or temperature < 18:
        comfort_level = "uncomfortable"
    elif humidity > 70 or humidity < 30:
        comfort_level = "uncomfortable"
    
    # ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ
    message = {
        "device_id": CLIENT_ID,
        "timestamp": int(time.time()),
        "location": "living_room",
        "sensor_data": {
            "temperature": temperature,
            "humidity": humidity,
            "heat_index": heat_index
        },
        "analysis": {
            "comfort_level": comfort_level,
            "sensor_health": "healthy" if sensor_reader.is_healthy() else "warning"
        },
        "metadata": {
            "sensor_type": "DHT22",
            "gpio_pin": DHT_PIN,
            "simulation_mode": not SENSOR_AVAILABLE
        }
    }
    
    try:
        message_json = json.dumps(message, indent=2)
        client.publish(TOPIC, message_json, 1)
        
        print(f"\n๐Ÿ“Š ์„ผ์„œ ๋ฐ์ดํ„ฐ ์ „์†ก:")
        print(f"   ๐ŸŒก๏ธ  ์˜จ๋„: {temperature}ยฐC")
        print(f"   ๐Ÿ’ง ์Šต๋„: {humidity}%")
        print(f"   ๐Ÿ”ฅ ์ฒด๊ฐ์˜จ๋„: {heat_index}ยฐC")
        print(f"   ๐Ÿ˜Š ์พŒ์ ๋„: {comfort_level}")
        
        return True
        
    except Exception as e:
        print(f"โŒ ๋ฐ์ดํ„ฐ ์ „์†ก ์‹คํŒจ: {str(e)}")
        return False

def main():
    """
    ๋ฉ”์ธ ์‹คํ–‰ ํ•จ์ˆ˜
    """
    print("๐ŸŒก๏ธ ์„ผ์„œ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ์‹œ์ž‘...")
    
    if not SENSOR_AVAILABLE:
        print("โš ๏ธ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.")
    
    # ์„ผ์„œ ๋ฆฌ๋” ์ดˆ๊ธฐํ™”
    sensor_reader = SensorReader()
    
    # MQTT ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
    mqtt_client = init_mqtt_client()
    
    # AWS IoT Core ์—ฐ๊ฒฐ
    try:
        mqtt_client.connect()
        print("โœ… AWS IoT Core ์—ฐ๊ฒฐ ์„ฑ๊ณต!")
    except Exception as e:
        print(f"โŒ ์—ฐ๊ฒฐ ์‹คํŒจ: {str(e)}")
        return
    
    # ๋ฉ”์ธ ๋ฃจํ”„
    consecutive_failures = 0
    
    try:
        while True:
            # ์„ผ์„œ ๋ฐ์ดํ„ฐ ๋ฐœํ–‰
            success = publish_sensor_data(mqtt_client, sensor_reader)
            
            if success:
                consecutive_failures = 0
            else:
                consecutive_failures += 1
                
            # ์—ฐ์† ์‹คํŒจ ์‹œ ๊ฒฝ๊ณ 
            if consecutive_failures >= 3:
                print("โš ๏ธ ์—ฐ์† 3ํšŒ ์‹คํŒจ! ์„ผ์„œ ๋˜๋Š” ์—ฐ๊ฒฐ์„ ํ™•์ธํ•˜์„ธ์š”.")
                
            # 30์ดˆ ๋Œ€๊ธฐ
            time.sleep(30)
            
    except KeyboardInterrupt:
        print("\nโน๏ธ ํ”„๋กœ๊ทธ๋žจ ์ข…๋ฃŒ ์ค‘...")
    
    finally:
        mqtt_client.disconnect()
        print("๐Ÿ‘‹ ๋ชจ๋‹ˆํ„ฐ๋ง ์‹œ์Šคํ…œ ์ข…๋ฃŒ")

if __name__ == "__main__":
    main()

์ด ์ฝ”๋“œ๋Š” ์‹ค์ œ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์„ ์ •๋„๋กœ ์™„์„ฑ๋„๊ฐ€ ๋†’์•„! ํŠน์ง•์„ ์‚ดํŽด๋ณด์ž:

โœจ ์ฃผ์š” ํŠน์ง•

โ€ข ์‹ค์ œ ์„ผ์„œ ์ง€์›: DHT22 ์„ผ์„œ์—์„œ ์‹ค์ œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด์˜ด
โ€ข ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๋ชจ๋“œ: ์„ผ์„œ๊ฐ€ ์—†์–ด๋„ ํ…Œ์ŠคํŠธ ๊ฐ€๋Šฅ
โ€ข ์—๋Ÿฌ ์ฒ˜๋ฆฌ: ์„ผ์„œ ์ฝ๊ธฐ ์‹คํŒจ ์‹œ ์žฌ์‹œ๋„ ๋ฐ ์นด์šดํŒ…
โ€ข ๋ฐ์ดํ„ฐ ๋ถ„์„: ์ฒด๊ฐ์˜จ๋„ ๊ณ„์‚ฐ ๋ฐ ์พŒ์ ๋„ ํŒ๋‹จ
โ€ข ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ: ์„ผ์„œ ํƒ€์ž…, ์œ„์น˜ ๋“ฑ ์ถ”๊ฐ€ ์ •๋ณด ํฌํ•จ
โ€ข ๊ฑด๊ฐ• ์ฒดํฌ: ์„ผ์„œ ์ƒํƒœ๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋ง

๐Ÿ’ก ์‹ค์ „ ํŒ: ์‹ค์ œ ํ™˜๊ฒฝ์—์„œ๋Š” ์„ผ์„œ ์บ˜๋ฆฌ๋ธŒ๋ ˆ์ด์…˜์ด ์ค‘์š”ํ•ด. DHT22๋Š” ยฑ2ยฐC, ยฑ5% ์ •๋„์˜ ์˜ค์ฐจ๊ฐ€ ์žˆ์œผ๋‹ˆ ์ฐธ๊ณ ํ•ด!

๐ŸŽจ AWS IoT Core ๊ทœ์น™(Rules) ํ™œ์šฉ

๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›๊ธฐ๋งŒ ํ•˜๋ฉด ๋ญํ•ด? AWS IoT Core์˜ ๊ทœ์น™ ์—”์ง„์„ ์‚ฌ์šฉํ•˜๋ฉด ๋“ค์–ด์˜ค๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ž๋™์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด! ์˜ˆ๋ฅผ ๋“ค์–ด ์˜จ๋„๊ฐ€ ๋„ˆ๋ฌด ๋†’์œผ๋ฉด ์•Œ๋ฆผ์„ ๋ณด๋‚ด๊ฑฐ๋‚˜, ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์ €์žฅํ•˜๋Š” ๊ฑฐ์ง€. ๐Ÿ”ฅ

๊ทœ์น™ ์ƒ์„ฑ ์˜ˆ์ œ

AWS ์ฝ˜์†”์—์„œ IoT Core โ†’ ์ž‘์—… โ†’ ๊ทœ์น™ โ†’ ์ƒ์„ฑ์œผ๋กœ ๋“ค์–ด๊ฐ€์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์„ค์ •ํ•ด:

๊ทœ์น™ 1: ๊ณ ์˜จ ์•Œ๋ฆผ

์˜จ๋„๊ฐ€ 28๋„๋ฅผ ์ดˆ๊ณผํ•˜๋ฉด SNS๋กœ ์•Œ๋ฆผ ์ „์†ก

-- SQL ์ฟผ๋ฆฌ
SELECT 
    device_id,
    timestamp,
    sensor_data.temperature as temperature,
    sensor_data.humidity as humidity
FROM 'home/environment'
WHERE sensor_data.temperature > 28

์ž‘์—…์œผ๋กœ SNS ์ฃผ์ œ์— ๋ฉ”์‹œ์ง€ ์ „์†ก์„ ์„ ํƒํ•˜๋ฉด ๋ผ.

๊ทœ์น™ 2: ๋ฐ์ดํ„ฐ ์ €์žฅ

๋ชจ๋“  ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ DynamoDB์— ์ €์žฅ

-- SQL ์ฟผ๋ฆฌ
SELECT 
    device_id,
    timestamp,
    sensor_data,
    analysis
FROM 'home/environment'

์ž‘์—…์œผ๋กœ DynamoDB ํ…Œ์ด๋ธ”์— ๋ฉ”์‹œ์ง€ ์‚ฝ์ž…์„ ์„ ํƒํ•˜๋ฉด ๋ผ.

Lambda ํ•จ์ˆ˜ ์—ฐ๋™

๋” ๋ณต์žกํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•˜๋ฉด Lambda ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด. ์˜ˆ๋ฅผ ๋“ค์–ด ๋ฐ์ดํ„ฐ ๋ถ„์„, ์™ธ๋ถ€ API ํ˜ธ์ถœ, ๋ณต์žกํ•œ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง ๋“ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ง€.

# Lambda ํ•จ์ˆ˜ ์˜ˆ์ œ (Python 3.9)
import json
import boto3
from datetime import datetime

dynamodb = boto3.resource('dynamodb')
sns = boto3.client('sns')

def lambda_handler(event, context):
    """
    IoT ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ Lambda ํ•จ์ˆ˜
    """
    print(f"์ˆ˜์‹ ๋œ ์ด๋ฒคํŠธ: {json.dumps(event)}")
    
    # ๋ฐ์ดํ„ฐ ์ถ”์ถœ
    device_id = event.get('device_id')
    sensor_data = event.get('sensor_data', {})
    temperature = sensor_data.get('temperature')
    humidity = sensor_data.get('humidity')
    
    # DynamoDB์— ์ €์žฅ
    table = dynamodb.Table('IoTSensorData')
    
    try:
        table.put_item(
            Item={
                'device_id': device_id,
                'timestamp': int(event.get('timestamp')),
                'temperature': str(temperature),
                'humidity': str(humidity),
                'processed_at': datetime.now().isoformat()
            }
        )
        print("โœ… DynamoDB ์ €์žฅ ์„ฑ๊ณต")
    except Exception as e:
        print(f"โŒ DynamoDB ์ €์žฅ ์‹คํŒจ: {str(e)}")
    
    # ๊ณ ์˜จ ์•Œ๋ฆผ
    if temperature and temperature > 30:
        try:
            sns.publish(
                TopicArn='arn:aws:sns:ap-northeast-2:123456789:HighTemperatureAlert',
                Subject='๐Ÿ”ฅ ๊ณ ์˜จ ๊ฒฝ๊ณ !',
                Message=f'๋””๋ฐ”์ด์Šค {device_id}์˜ ์˜จ๋„๊ฐ€ {temperature}ยฐC์ž…๋‹ˆ๋‹ค!'
            )
            print("โœ… SNS ์•Œ๋ฆผ ์ „์†ก ์„ฑ๊ณต")
        except Exception as e:
            print(f"โŒ SNS ์ „์†ก ์‹คํŒจ: {str(e)}")
    
    return {
        'statusCode': 200,
        'body': json.dumps('์ฒ˜๋ฆฌ ์™„๋ฃŒ')
    }

๐Ÿ”’ ๋ณด์•ˆ ๊ฐ•ํ™” ํŒ

IoT ๋””๋ฐ”์ด์Šค๋Š” ๋ณด์•ˆ์ด ์ •๋ง ์ค‘์š”ํ•ด! ํ•ดํ‚น๋‹นํ•˜๋ฉด ํฐ์ผ๋‚˜๊ฑฐ๋“ . ๋ช‡ ๊ฐ€์ง€ ๋ณด์•ˆ ๊ฐ•ํ™” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค„๊ฒŒ. ๐Ÿ›ก๏ธ

1. ์ธ์ฆ์„œ ๊ด€๋ฆฌ

โš ๏ธ ์ ˆ๋Œ€ ํ•˜์ง€ ๋ง์•„์•ผ ํ•  ๊ฒƒ๋“ค:

โ€ข ์ธ์ฆ์„œ๋ฅผ Git์— ์ปค๋ฐ‹ํ•˜์ง€ ๋งˆ!
โ€ข ํ”„๋ผ์ด๋น— ํ‚ค๋ฅผ ํ‰๋ฌธ์œผ๋กœ ์ €์žฅํ•˜์ง€ ๋งˆ!
โ€ข ์ธ์ฆ์„œ๋ฅผ ์ด๋ฉ”์ผ๋กœ ์ „์†กํ•˜์ง€ ๋งˆ!
โ€ข ๊ธฐ๋ณธ ๊ถŒํ•œ(777)์œผ๋กœ ๋‘์ง€ ๋งˆ!

โœ… ์˜ฌ๋ฐ”๋ฅธ ๋ฐฉ๋ฒ•:

โ€ข ์ธ์ฆ์„œ๋Š” ์•”ํ˜ธํ™”๋œ ์ €์žฅ์†Œ์— ๋ณด๊ด€
โ€ข ํŒŒ์ผ ๊ถŒํ•œ์„ ์ตœ์†Œํ™” (600 ๋˜๋Š” 400)
โ€ข ์ •๊ธฐ์ ์œผ๋กœ ์ธ์ฆ์„œ ๋กœํ…Œ์ด์…˜
โ€ข ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ธ์ฆ์„œ๋Š” ์ฆ‰์‹œ ๋น„ํ™œ์„ฑํ™”

2. ์ •์ฑ… ์ตœ์†Œ ๊ถŒํ•œ ์›์น™

๋””๋ฐ”์ด์Šค์— ํ•„์š”ํ•œ ์ตœ์†Œํ•œ์˜ ๊ถŒํ•œ๋งŒ ๋ถ€์—ฌํ•ด์•ผ ํ•ด. ์˜ˆ๋ฅผ ๋“ค์–ด:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "iot:Connect",
      "Resource": "arn:aws:iot:ap-northeast-2:ACCOUNT_ID:client/${iot:ClientId}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Publish",
      "Resource": [
        "arn:aws:iot:ap-northeast-2:ACCOUNT_ID:topic/home/environment",
        "arn:aws:iot:ap-northeast-2:ACCOUNT_ID:topic/home/status"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "iot:Subscribe",
      "Resource": "arn:aws:iot:ap-northeast-2:ACCOUNT_ID:topicfilter/home/command/${iot:ClientId}"
    },
    {
      "Effect": "Allow",
      "Action": "iot:Receive",
      "Resource": "arn:aws:iot:ap-northeast-2:ACCOUNT_ID:topic/home/command/${iot:ClientId}"
    }
  ]
}

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํŠน์ • ํ† ํ”ฝ์—๋งŒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๊ณ , ์ž์‹ ์˜ ClientId์— ํ•ด๋‹นํ•˜๋Š” ๋ช…๋ น๋งŒ ๋ฐ›์„ ์ˆ˜ ์žˆ์–ด.

3. ๋„คํŠธ์›Œํฌ ๋ณด์•ˆ

๐Ÿ” ๋„คํŠธ์›Œํฌ ๋ณด์•ˆ ์ฒดํฌ๋ฆฌ์ŠคํŠธ

โœ… TLS 1.2 ์ด์ƒ ์‚ฌ์šฉ (AWS IoT Core๋Š” ๊ธฐ๋ณธ ์ง€์›)
โœ… ๋ฐฉํ™”๋ฒฝ์—์„œ ํ•„์š”ํ•œ ํฌํŠธ๋งŒ ์—ด๊ธฐ (8883, 443)
โœ… VPN ๋˜๋Š” ํ”„๋ผ์ด๋น— ๋„คํŠธ์›Œํฌ ์‚ฌ์šฉ ๊ณ ๋ ค
โœ… ์ •๊ธฐ์ ์ธ ๋ณด์•ˆ ์—…๋ฐ์ดํŠธ ์ ์šฉ
โœ… ๋ถˆํ•„์š”ํ•œ ์„œ๋น„์Šค ๋น„ํ™œ์„ฑํ™”

4. ์ฝ”๋“œ ๋ ˆ๋ฒจ ๋ณด์•ˆ

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
๋ณด์•ˆ์ด ๊ฐ•ํ™”๋œ IoT ํด๋ผ์ด์–ธํŠธ
"""

import os
import sys
from pathlib import Path

class SecureConfig:
    """
    ๋ณด์•ˆ ์„ค์ • ๊ด€๋ฆฌ ํด๋ž˜์Šค
    """
    def __init__(self):
        self.config_dir = Path.home() / '.aws-iot'
        self.certs_dir = self.config_dir / 'certs'
        
    def validate_certificates(self):
        """
        ์ธ์ฆ์„œ ํŒŒ์ผ ๊ฒ€์ฆ
        """
        required_files = [
            'certificate.pem.crt',
            'private.pem.key',
            'AmazonRootCA1.pem'
        ]
        
        for filename in required_files:
            filepath = self.certs_dir / filename
            
            # ํŒŒ์ผ ์กด์žฌ ํ™•์ธ
            if not filepath.exists():
                raise FileNotFoundError(f"์ธ์ฆ์„œ ํŒŒ์ผ์ด ์—†์Šต๋‹ˆ๋‹ค: {filename}")
            
            # ๊ถŒํ•œ ํ™•์ธ (Unix ๊ณ„์—ด๋งŒ)
            if sys.platform != 'win32':
                stat_info = filepath.stat()
                mode = oct(stat_info.st_mode)[-3:]
                
                if filename.endswith('.key'):
                    # ํ”„๋ผ์ด๋น— ํ‚ค๋Š” 600 ๋˜๋Š” 400์ด์–ด์•ผ ํ•จ
                    if mode not in ['600', '400']:
                        raise PermissionError(
                            f"ํ”„๋ผ์ด๋น— ํ‚ค ๊ถŒํ•œ์ด ์•ˆ์ „ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค: {mode}\n"
                            f"๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ์‹คํ–‰ํ•˜์„ธ์š”: chmod 600 {filepath}"
                        )
        
        print("โœ… ์ธ์ฆ์„œ ๊ฒ€์ฆ ์™„๋ฃŒ")
        return True
    
    def get_cert_paths(self):
        """
        ์ธ์ฆ์„œ ๊ฒฝ๋กœ ๋ฐ˜ํ™˜
        """
        return {
            'root_ca': str(self.certs_dir / 'AmazonRootCA1.pem'),
            'certificate': str(self.certs_dir / 'certificate.pem.crt'),
            'private_key': str(self.certs_dir / 'private.pem.key')
        }

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    config = SecureConfig()
    
    try:
        config.validate_certificates()
        cert_paths = config.get_cert_paths()
        print("์ธ์ฆ์„œ ๊ฒฝ๋กœ:", cert_paths)
    except Exception as e:
        print(f"โŒ ๋ณด์•ˆ ๊ฒ€์ฆ ์‹คํŒจ: {str(e)}")
        sys.exit(1)

๐Ÿ“Š ๋ชจ๋‹ˆํ„ฐ๋ง ๋ฐ ๋””๋ฒ„๊น…

๊ฐœ๋ฐœํ•˜๋‹ค ๋ณด๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธฐ๊ธฐ ๋งˆ๋ จ์ด์•ผ. ํšจ๊ณผ์ ์œผ๋กœ ๋””๋ฒ„๊น…ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด์ž! ๐Ÿ”

CloudWatch ๋กœ๊ทธ ํ™œ์„ฑํ™”

AWS IoT Core๋Š” CloudWatch Logs์™€ ํ†ตํ•ฉ๋˜์–ด ์žˆ์–ด. ๋กœ๊น…์„ ํ™œ์„ฑํ™”ํ•˜๋ฉด ๋ชจ๋“  ์—ฐ๊ฒฐ, ๋ฐœํ–‰, ๊ตฌ๋… ์ด๋ฒคํŠธ๋ฅผ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์–ด.

๋กœ๊น… ํ™œ์„ฑํ™” ๋ฐฉ๋ฒ•:

1. IoT Core ์ฝ˜์†” โ†’ ์„ค์ •
2. ๋กœ๊ทธ ์„น์…˜์—์„œ "ํŽธ์ง‘" ํด๋ฆญ
3. ๋กœ๊ทธ ์ˆ˜์ค€ ์„ ํƒ (Debug, Info, Warn, Error)
4. IAM ์—ญํ•  ์ƒ์„ฑ ๋˜๋Š” ์„ ํƒ
5. ์—…๋ฐ์ดํŠธ ํด๋ฆญ

๋””๋ฒ„๊น…์šฉ ์ฝ”๋“œ

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
๋””๋ฒ„๊น… ๊ธฐ๋Šฅ์ด ๊ฐ•ํ™”๋œ IoT ํด๋ผ์ด์–ธํŠธ
"""

import logging
import sys
from AWSIoTPythonSDK.MQTTLib import AWSIoTMQTTClient

# ๋กœ๊น… ์„ค์ •
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler('iot_client.log'),
        logging.StreamHandler(sys.stdout)
    ]
)

logger = logging.getLogger(__name__)

class DebugMQTTClient:
    """
    ๋””๋ฒ„๊น… ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋œ MQTT ํด๋ผ์ด์–ธํŠธ
    """
    def __init__(self, client_id, endpoint):
        self.client_id = client_id
        self.endpoint = endpoint
        self.client = None
        self.connection_status = False
        self.publish_count = 0
        self.error_count = 0
        
    def init_client(self, root_ca, private_key, certificate):
        """
        ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™”
        """
        logger.info(f"ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์‹œ์ž‘: {self.client_id}")
        
        try:
            self.client = AWSIoTMQTTClient(self.client_id)
            self.client.configureEndpoint(self.endpoint, 8883)
            self.client.configureCredentials(root_ca, private_key, certificate)
            
            # ๋””๋ฒ„๊ทธ ๋กœ๊น… ํ™œ์„ฑํ™”
            self.client.configureLogging(
                AWSIoTPythonSDK.core.util.loggers.LOG_LEVEL_DEBUG,
                'aws_iot_sdk.log'
            )
            
            logger.info("โœ… ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์™„๋ฃŒ")
            return True
            
        except Exception as e:
            logger.error(f"โŒ ํด๋ผ์ด์–ธํŠธ ์ดˆ๊ธฐํ™” ์‹คํŒจ: {str(e)}", exc_info=True)
            return False
    
    def connect(self):
        """
        ์—ฐ๊ฒฐ ์‹œ๋„
        """
        logger.info(f"์—ฐ๊ฒฐ ์‹œ๋„: {self.endpoint}")
        
        try:
            self.client.connect()
            self.connection_status = True
            logger.info("โœ… ์—ฐ๊ฒฐ ์„ฑ๊ณต")
            return True
            
        except Exception as e:
            self.connection_status = False
            self.error_count += 1
            logger.error(f"โŒ ์—ฐ๊ฒฐ ์‹คํŒจ (์‹œ๋„ {self.error_count}ํšŒ): {str(e)}", exc_info=True)
            return False
    
    def publish(self, topic, payload, qos=1):
        """
        ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
        """
        if not self.connection_status:
            logger.warning("โš ๏ธ ์—ฐ๊ฒฐ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ ๋ฐœํ–‰ ์‹œ๋„")
            return False
        
        try:
            logger.debug(f"๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์‹œ๋„ - ํ† ํ”ฝ: {topic}, QoS: {qos}")
            logger.debug(f"ํŽ˜์ด๋กœ๋“œ: {payload[:100]}...")  # ์ฒ˜์Œ 100์ž๋งŒ ๋กœ๊น…
            
            self.client.publish(topic, payload, qos)
            self.publish_count += 1
            
            logger.info(f"โœ… ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์„ฑ๊ณต (์ด {self.publish_count}๊ฑด)")
            return True
            
        except Exception as e:
            self.error_count += 1
            logger.error(f"โŒ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์‹คํŒจ: {str(e)}", exc_info=True)
            return False
    
    def get_stats(self):
        """
        ํ†ต๊ณ„ ์ •๋ณด ๋ฐ˜ํ™˜
        """
        return {
            'client_id': self.client_id,
            'connected': self.connection_status,
            'publish_count': self.publish_count,
            'error_count': self.error_count
        }

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    client = DebugMQTTClient("TestDevice", "xxxxx.iot.ap-northeast-2.amazonaws.com")
    
    if client.init_client(
        "/path/to/root-ca.pem",
        "/path/to/private.key",
        "/path/to/certificate.crt"
    ):
        if client.connect():
            # ํ…Œ์ŠคํŠธ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
            import json
            test_message = json.dumps({"test": "data"})
            client.publish("test/topic", test_message)
            
            # ํ†ต๊ณ„ ์ถœ๋ ฅ
            stats = client.get_stats()
            logger.info(f"ํ†ต๊ณ„: {stats}")

์ผ๋ฐ˜์ ์ธ ๋ฌธ์ œ ํ•ด๊ฒฐ

๋ฌธ์ œ ์›์ธ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•
์—ฐ๊ฒฐ ์‹คํŒจ ์ธ์ฆ์„œ ์˜ค๋ฅ˜ ์ธ์ฆ์„œ ๊ฒฝ๋กœ ๋ฐ ๊ถŒํ•œ ํ™•์ธ
๋ฐœํ–‰ ์‹คํŒจ ์ •์ฑ… ๊ถŒํ•œ ๋ถ€์กฑ IoT ์ •์ฑ…์—์„œ Publish ๊ถŒํ•œ ํ™•์ธ
๋ฉ”์‹œ์ง€ ๋ฏธ์ˆ˜์‹  ๊ตฌ๋… ์‹คํŒจ ํ† ํ”ฝ ์ด๋ฆ„ ๋ฐ Subscribe ๊ถŒํ•œ ํ™•์ธ
๊ฐ„ํ—์  ๋Š๊น€ ๋„คํŠธ์›Œํฌ ๋ถˆ์•ˆ์ • ์ž๋™ ์žฌ์—ฐ๊ฒฐ ์„ค์ • ํ™•์ธ
๋А๋ฆฐ ์‘๋‹ต QoS ์„ค์ • QoS 0์œผ๋กœ ๋ณ€๊ฒฝ ๊ณ ๋ ค

๐Ÿš€ ์‹ค์ „ ํ”„๋กœ์ ํŠธ ์•„์ด๋””์–ด

์ด์ œ ๊ธฐ๋ณธ์€ ๋‹ค ๋ฐฐ์› ์œผ๋‹ˆ, ์‹ค์ œ๋กœ ๋งŒ๋“ค์–ด๋ณผ ์ˆ˜ ์žˆ๋Š” ํ”„๋กœ์ ํŠธ๋“ค์„ ์†Œ๊ฐœํ• ๊ฒŒ! ์ด๋Ÿฐ ํ”„๋กœ์ ํŠธ๋“ค์€ ํฌํŠธํด๋ฆฌ์˜ค๋กœ๋„ ์ข‹๊ณ , **์žฌ๋Šฅ๋„ท**์—์„œ ์„œ๋น„์Šค๋กœ ์ œ๊ณตํ•  ์ˆ˜๋„ ์žˆ์–ด. ๐Ÿ’ก

1์Šค๋งˆํŠธ ํ™ˆ ํ™˜๊ฒฝ ๋ชจ๋‹ˆํ„ฐ๋ง

โ€ข ์—ฌ๋Ÿฌ ๋ฐฉ์˜ ์˜จ์Šต๋„๋ฅผ ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง
โ€ข ๋ถˆ์พŒ์ง€์ˆ˜๊ฐ€ ๋†’์œผ๋ฉด ์ž๋™์œผ๋กœ ์•Œ๋ฆผ
โ€ข ์›น ๋Œ€์‹œ๋ณด๋“œ๋กœ ์‹œ๊ฐํ™”
โ€ข ์—์–ด์ปจ/๊ฐ€์Šต๊ธฐ ์ž๋™ ์ œ์–ด

2์‹๋ฌผ ์ž๋™ ๊ด€๋ฆฌ ์‹œ์Šคํ…œ

โ€ข ํ† ์–‘ ์Šต๋„ ์„ผ์„œ๋กœ ๋ฌผ ํ•„์š” ์—ฌ๋ถ€ ๊ฐ์ง€
โ€ข ์กฐ๋„ ์„ผ์„œ๋กœ ํ–‡๋น› ๋…ธ์ถœ ์‹œ๊ฐ„ ์ธก์ •
โ€ข ์ž๋™ ๋ฌผ์ฃผ๊ธฐ ์‹œ์Šคํ…œ
โ€ข ์„ฑ์žฅ ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ ๋ฆฌํฌํŠธ

3์—๋„ˆ์ง€ ์‚ฌ์šฉ๋Ÿ‰ ๋ชจ๋‹ˆํ„ฐ๋ง

โ€ข ์ „๋ ฅ ์‚ฌ์šฉ๋Ÿ‰ ์‹ค์‹œ๊ฐ„ ์ธก์ •
โ€ข ์‹œ๊ฐ„๋Œ€๋ณ„ ์‚ฌ์šฉ ํŒจํ„ด ๋ถ„์„
โ€ข ๋น„์šฉ ์˜ˆ์ธก ๋ฐ ์ ˆ์•ฝ ํŒ ์ œ๊ณต
โ€ข ์ด์ƒ ์‚ฌ์šฉ ํŒจํ„ด ๊ฐ์ง€ ๋ฐ ์•Œ๋ฆผ

4๋ณด์•ˆ ์นด๋ฉ”๋ผ ์‹œ์Šคํ…œ

โ€ข ๋™์ž‘ ๊ฐ์ง€ ์‹œ ์‚ฌ์ง„ ์ดฌ์˜
โ€ข S3์— ์ž๋™ ์—…๋กœ๋“œ
โ€ข Rekognition์œผ๋กœ ์–ผ๊ตด ์ธ์‹
โ€ข ์‹ค์‹œ๊ฐ„ ์•Œ๋ฆผ ์ „์†ก

5๋ฐ˜๋ ค๋™๋ฌผ ๋ชจ๋‹ˆํ„ฐ๋ง

โ€ข ๊ธ‰์‹๊ธฐ ์ž๋™ ์ œ์–ด
โ€ข ํ™œ๋™๋Ÿ‰ ์ถ”์ 
โ€ข ์˜จ๋„/์Šต๋„ ๋ชจ๋‹ˆํ„ฐ๋ง
โ€ข ์›๊ฒฉ ์นด๋ฉ”๋ผ ํ™•์ธ

๐Ÿ’ฐ ๋น„์šฉ ์ตœ์ ํ™” ํŒ

AWS๋Š” ํŽธ๋ฆฌํ•˜์ง€๋งŒ ๋น„์šฉ์ด ๊ฑฑ์ •๋  ์ˆ˜ ์žˆ์–ด. ํ”„๋ฆฌํ‹ฐ์–ด๋ฅผ ์ตœ๋Œ€ํ•œ ํ™œ์šฉํ•˜๊ณ  ๋น„์šฉ์„ ์ ˆ์•ฝํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค„๊ฒŒ! ๐Ÿ’ธ

AWS IoT Core ํ”„๋ฆฌํ‹ฐ์–ด

๐Ÿ“Š ํ”„๋ฆฌํ‹ฐ์–ด ํ•œ๋„ (๋งค์›”)

โ€ข ์—ฐ๊ฒฐ ์‹œ๊ฐ„: 2,250,000๋ถ„ (์•ฝ 1,562 ๋””๋ฐ”์ด์Šค-์ผ)
โ€ข ๋ฉ”์‹œ์ง€: 500,000๊ฑด
โ€ข ๊ทœ์น™ ์—”์ง„ ์‹คํ–‰: 250,000๊ฑด
โ€ข Device Shadow ์ž‘์—…: 225,000๊ฑด

๋น„์šฉ ์ ˆ๊ฐ ์ „๋žต

๐Ÿ’ก ์Šค๋งˆํŠธํ•œ ๋น„์šฉ ์ ˆ๊ฐ ๋ฐฉ๋ฒ•:

1. ๋ฉ”์‹œ์ง€ ๋นˆ๋„ ์กฐ์ ˆ
โ€ข ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋Š” ์ „์†ก ์ฃผ๊ธฐ๋ฅผ ๋Š˜๋ ค
โ€ข ๋ณ€ํ™”๊ฐ€ ์žˆ์„ ๋•Œ๋งŒ ์ „์†ก (๋ธํƒ€ ์ „์†ก)
โ€ข ์—ฌ๋Ÿฌ ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๋ฉ”์‹œ์ง€๋กœ ๋ฌถ์–ด์„œ ์ „์†ก

2. ์••์ถ• ์‚ฌ์šฉ
โ€ข JSON ๋Œ€์‹  ๋ฐ”์ด๋„ˆ๋ฆฌ ํฌ๋งท ๊ณ ๋ ค
โ€ข ๋ถˆํ•„์š”ํ•œ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ ์ œ๊ฑฐ
โ€ข gzip ์••์ถ• ํ™œ์šฉ

3. ๋กœ์ปฌ ์ฒ˜๋ฆฌ
โ€ข ๊ฐ„๋‹จํ•œ ํ•„ํ„ฐ๋ง์€ ๋””๋ฐ”์ด์Šค์—์„œ ์ฒ˜๋ฆฌ
โ€ข ์ด์ƒ๊ฐ’๋งŒ ํด๋ผ์šฐ๋“œ๋กœ ์ „์†ก
โ€ข ๋กœ์ปฌ ์บ์‹ฑ ํ™œ์šฉ

๋น„์šฉ ๋ชจ๋‹ˆํ„ฐ๋ง ์ฝ”๋“œ

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
๋ฉ”์‹œ์ง€ ์ „์†ก ์ตœ์ ํ™” ์˜ˆ์ œ
"""

import json
import time
from collections import deque

class OptimizedPublisher:
    """
    ๋น„์šฉ ์ตœ์ ํ™”๋œ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ํด๋ž˜์Šค
    """
    def __init__(self, client, topic):
        self.client = client
        self.topic = topic
        self.last_values = {}
        self.message_count = 0
        self.bytes_sent = 0
        self.history = deque(maxlen=100)
        
    def should_publish(self, key, value, threshold=0.5):
        """
        ๊ฐ’์ด ์ถฉ๋ถ„ํžˆ ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ (๋ธํƒ€ ์ „์†ก)
        """
        if key not in self.last_values:
            return True
        
        last_value = self.last_values[key]
        change_percent = abs(value - last_value) / last_value * 100
        
        return change_percent >= threshold
    
    def publish_optimized(self, data):
        """
        ์ตœ์ ํ™”๋œ ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰
        """
        # ๋ณ€๊ฒฝ๋œ ๋ฐ์ดํ„ฐ๋งŒ ํ•„ํ„ฐ๋ง
        filtered_data = {}
        
        for key, value in data.items():
            if self.should_publish(key, value):
                filtered_data[key] = value
                self.last_values[key] = value
        
        # ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์—†์œผ๋ฉด ๋ฐœํ–‰ํ•˜์ง€ ์•Š์Œ
        if not filtered_data:
            print("๐Ÿ“Š ๋ณ€๊ฒฝ์‚ฌํ•ญ ์—†์Œ - ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰ ์ƒ๋žต")
            return False
        
        # ๋ฉ”์‹œ์ง€ ์ƒ์„ฑ (์ตœ์†Œํ™”๋œ ํ˜•์‹)
        message = {
            "t": int(time.time()),  # timestamp ์ถ•์•ฝ
            "d": filtered_data       # data ์ถ•์•ฝ
        }
        
        message_json = json.dumps(message, separators=(',', ':'))  # ๊ณต๋ฐฑ ์ œ๊ฑฐ
        message_size = len(message_json.encode('utf-8'))
        
        # ํ†ต๊ณ„ ์—…๋ฐ์ดํŠธ
        self.message_count += 1
        self.bytes_sent += message_size
        self.history.append({
            'timestamp': time.time(),
            'size': message_size,
            'keys': list(filtered_data.keys())
        })
        
        # ๋ฐœํ–‰
        self.client.publish(self.topic, message_json, 1)
        
        print(f"๐Ÿ“ค ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰: {message_size} bytes")
        return True
    
    def get_statistics(self):
        """
        ํ†ต๊ณ„ ์ •๋ณด ๋ฐ˜ํ™˜
        """
        avg_size = self.bytes_sent / self.message_count if self.message_count > 0 else 0
        
        return {
            'total_messages': self.message_count,
            'total_bytes': self.bytes_sent,
            'average_size': round(avg_size, 2),
            'estimated_monthly_messages': self.message_count * 30 * 24,  # 1์‹œ๊ฐ„ ๊ธฐ์ค€
            'within_free_tier': self.message_count * 30 * 24 < 500000
        }

# ์‚ฌ์šฉ ์˜ˆ์ œ
if __name__ == "__main__":
    # ๊ฐ€์ƒ์˜ ํด๋ผ์ด์–ธํŠธ (์‹ค์ œ๋กœ๋Š” MQTT ํด๋ผ์ด์–ธํŠธ ์‚ฌ์šฉ)
    class DummyClient:
        def publish(self, topic, message, qos):
            pass
    
    client = DummyClient()
    publisher = OptimizedPublisher(client, "sensor/data")
    
    # ์‹œ๋ฎฌ๋ ˆ์ด์…˜
    for i in range(10):
        data = {
            "temperature": 25.0 + (i % 3) * 0.1,  # ์ž‘์€ ๋ณ€ํ™”
            "humidity": 60.0 + (i % 5) * 2.0      # ํฐ ๋ณ€ํ™”
        }
        
        publisher.publish_optimized(data)
        time.sleep(1)
    
    # ํ†ต๊ณ„ ์ถœ๋ ฅ
    stats = publisher.get_statistics()
    print(f"\n๐Ÿ“Š ํ†ต๊ณ„:")
    print(f"   ์ด ๋ฉ”์‹œ์ง€: {stats['total_messages']}๊ฑด")
    print(f"   ์ด ๋ฐ์ดํ„ฐ: {stats['total_bytes']} bytes")
    print(f"   ํ‰๊ท  ํฌ๊ธฐ: {stats['average_size']} bytes")
    print(f"   ์›” ์˜ˆ์ƒ: {stats['estimated_monthly_messages']}๊ฑด")
    print(f"   ํ”„๋ฆฌํ‹ฐ์–ด: {'โœ… ๋ฒ”์œ„ ๋‚ด' if stats['within_free_tier'] else 'โŒ ์ดˆ๊ณผ'}")

๐ŸŽ“ ํ•™์Šต ๋ฆฌ์†Œ์Šค ๋ฐ ๋‹ค์Œ ๋‹จ๊ณ„

์—ฌ๊ธฐ๊นŒ์ง€ ์™”๋‹ค๋ฉด ์ •๋ง ๋Œ€๋‹จํ•ด! ํ•˜์ง€๋งŒ ๋ฐฐ์›€์—๋Š” ๋์ด ์—†์ง€. ๋” ๊นŠ์ด ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ด๋Ÿฐ ๊ฒƒ๋“ค์„ ์‚ดํŽด๋ด. ๐Ÿ“š

๊ณต์‹ ๋ฌธ์„œ

โ€ข AWS IoT Core ๊ฐœ๋ฐœ์ž ๊ฐ€์ด๋“œ: ๊ฐ€์žฅ ์ •ํ™•ํ•˜๊ณ  ์ตœ์‹  ์ •๋ณด
โ€ข AWS IoT Python SDK: SDK ์ƒ์„ธ ๋ฌธ์„œ
โ€ข MQTT ํ”„๋กœํ† ์ฝœ ์ŠคํŽ™: MQTT 3.1.1 ํ‘œ์ค€ ๋ฌธ์„œ
โ€ข ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด ๊ณต์‹ ๋ฌธ์„œ: GPIO, ์„ผ์„œ ์—ฐ๋™ ๋“ฑ

์ถ”๊ฐ€๋กœ ๋ฐฐ์šธ ๋งŒํ•œ ๊ฒƒ๋“ค

1AWS IoT Greengrass

์—ฃ์ง€ ์ปดํ“จํŒ…์„ ์œ„ํ•œ ์„œ๋น„์Šค. ์˜คํ”„๋ผ์ธ์—์„œ๋„ ์ž‘๋™ํ•˜๊ณ  ๋กœ์ปฌ์—์„œ Lambda ํ•จ์ˆ˜๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์–ด.

2Device Shadow

๋””๋ฐ”์ด์Šค์˜ ์ƒํƒœ๋ฅผ ํด๋ผ์šฐ๋“œ์— ์ €์žฅํ•˜๊ณ  ๋™๊ธฐํ™”ํ•˜๋Š” ๊ธฐ๋Šฅ. ์˜คํ”„๋ผ์ธ ๋””๋ฐ”์ด์Šค ๊ด€๋ฆฌ์— ์œ ์šฉํ•ด.

3Fleet Provisioning

๋Œ€๋Ÿ‰์˜ ๋””๋ฐ”์ด์Šค๋ฅผ ์ž๋™์œผ๋กœ ๋“ฑ๋กํ•˜๊ณ  ์ธ์ฆ์„œ๋ฅผ ๋ฐœ๊ธ‰ํ•˜๋Š” ๊ธฐ๋Šฅ.

4Jobs

์—ฌ๋Ÿฌ ๋””๋ฐ”์ด์Šค์— ํŽŒ์›จ์–ด ์—…๋ฐ์ดํŠธ๋‚˜ ์„ค์ • ๋ณ€๊ฒฝ์„ ๋ฐฐํฌํ•˜๋Š” ๊ธฐ๋Šฅ.

์‹ค์ „ ๊ฒฝํ—˜ ์Œ“๊ธฐ

์ด๋ก ๋งŒ์œผ๋กœ๋Š” ๋ถ€์กฑํ•ด! ์‹ค์ œ๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋Š” ๊ฒŒ ์ตœ๊ณ ์˜ ํ•™์Šต ๋ฐฉ๋ฒ•์ด์•ผ. ์ž‘์€ ๊ฒƒ๋ถ€ํ„ฐ ์‹œ์ž‘ํ•ด์„œ ์ ์  ๋ณต์žกํ•œ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค์–ด๋ด. ๊ทธ๋ฆฌ๊ณ  ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๋ฅผ GitHub์— ์˜ฌ๋ฆฌ๊ณ , ๋ธ”๋กœ๊ทธ์— ์ •๋ฆฌํ•˜๋ฉด ํฌํŠธํด๋ฆฌ์˜ค๋กœ๋„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด! ๐ŸŽฏ

๐Ÿ’ก ์ปค๋ฆฌ์–ด ํŒ: IoT์™€ ํด๋ผ์šฐ๋“œ ๊ธฐ์ˆ ์€ ์š”์ฆ˜ ์ •๋ง ํ•ซํ•ด. ์ด๋Ÿฐ ๊ธฐ์ˆ ์„ ์ตํ˜€๋‘๋ฉด ์ทจ์—…์ด๋‚˜ ํ”„๋ฆฌ๋žœ์„œ ํ™œ๋™์— ํฐ ๋„์›€์ด ๋ผ. ํŠนํžˆ ์žฌ๋Šฅ๋„ท ๊ฐ™์€ ํ”Œ๋žซํผ์—์„œ IoT ์ปจ์„คํŒ…์ด๋‚˜ ๊ฐœ๋ฐœ ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•˜๋ฉด ์ข‹์€ ์ˆ˜์ž…์›์ด ๋  ์ˆ˜ ์žˆ์–ด!

๐ŸŽฌ ๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

์™€! ์ •๋ง ๊ธด ์—ฌ์ •์ด์—ˆ์ง€? ๐Ÿ˜… ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด์™€ AWS IoT Core๋ฅผ ์—ฐ๋™ํ•˜๋Š” ๋ฐฉ๋ฒ•๋ถ€ํ„ฐ ์‹ค์ „ ์ฝ”๋“œ, ๋ณด์•ˆ, ์ตœ์ ํ™”๊นŒ์ง€ ์ •๋ง ๋งŽ์€ ๊ฑธ ๋‹ค๋ค˜์–ด.

ํ•ต์‹ฌ์„ ์ •๋ฆฌํ•˜์ž๋ฉด:

โœจ ํ•ต์‹ฌ ์š”์•ฝ

โ€ข ์„ค์ •: AWS IoT Core์—์„œ Thing, ์ธ์ฆ์„œ, ์ •์ฑ… ์ƒ์„ฑ
โ€ข ์—ฐ๊ฒฐ: MQTT ํ”„๋กœํ† ์ฝœ๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์—ฐ๊ฒฐ
โ€ข ํ†ต์‹ : ๋ฉ”์‹œ์ง€ ๋ฐœํ–‰(Publish)๊ณผ ๊ตฌ๋…(Subscribe)์œผ๋กœ ์–‘๋ฐฉํ–ฅ ํ†ต์‹ 
โ€ข ๋ณด์•ˆ: ์ธ์ฆ์„œ ๊ด€๋ฆฌ์™€ ์ตœ์†Œ ๊ถŒํ•œ ์›์น™ ์ค€์ˆ˜
โ€ข ์ตœ์ ํ™”: ๋น„์šฉ ์ ˆ๊ฐ์„ ์œ„ํ•œ ์Šค๋งˆํŠธํ•œ ๋ฉ”์‹œ์ง€ ์ „์†ก
โ€ข ํ™•์žฅ: ๊ทœ์น™, Lambda, ๋‹ค๋ฅธ AWS ์„œ๋น„์Šค์™€ ์—ฐ๋™

์ฒ˜์Œ์—๋Š” ๋ณต์žกํ•ด ๋ณด์ผ ์ˆ˜ ์žˆ์ง€๋งŒ, ํ•˜๋‚˜์”ฉ ๋”ฐ๋ผํ•˜๋‹ค ๋ณด๋ฉด ์–ด๋А์ƒˆ ๋ฉ‹์ง„ IoT ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๊ฑฐ์•ผ. ์ค‘์š”ํ•œ ๊ฑด ์ง์ ‘ ํ•ด๋ณด๋Š” ๊ฒƒ์ด์•ผ! ์ฝ”๋“œ๋ฅผ ๋ณต์‚ฌํ•ด์„œ ์‹คํ–‰ํ•ด๋ณด๊ณ , ์—๋Ÿฌ๊ฐ€ ๋‚˜๋ฉด ๋””๋ฒ„๊น…ํ•˜๊ณ , ์กฐ๊ธˆ์”ฉ ์ˆ˜์ •ํ•ด๊ฐ€๋ฉด์„œ ์ž์‹ ๋งŒ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ด. ๐Ÿš€

ํ˜น์‹œ ๋ง‰ํžˆ๋Š” ๋ถ€๋ถ„์ด ์žˆ๊ฑฐ๋‚˜ ๋” ๊ถ๊ธˆํ•œ ๊ฒŒ ์žˆ๋‹ค๋ฉด, AWS ๊ณต์‹ ๋ฌธ์„œ๋‚˜ ์ปค๋ฎค๋‹ˆํ‹ฐ๋ฅผ ํ™œ์šฉํ•ด๋ด. ๊ทธ๋ฆฌ๊ณ  ์ž์‹ ์ด ๋งŒ๋“  ํ”„๋กœ์ ํŠธ๋ฅผ ๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค๊ณผ ๊ณต์œ ํ•˜๋Š” ๊ฒƒ๋„ ์žŠ์ง€ ๋งˆ! ๊ฐ€๋ฅด์น˜๋Š” ๊ฒƒ์ด ์ตœ๊ณ ์˜ ํ•™์Šต ๋ฐฉ๋ฒ•์ด๊ฑฐ๋“ . ๐Ÿ˜Š

์ž, ์ด์ œ ๋‹น์‹  ์ฐจ๋ก€์•ผ! ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด๋ฅผ ๊บผ๋‚ด์„œ ๋ฉ‹์ง„ IoT ํ”„๋กœ์ ํŠธ๋ฅผ ์‹œ์ž‘ํ•ด๋ณด์ž. ํ™”์ดํŒ…! ๐Ÿ’ชโœจ

๋Œ“๊ธ€ ์ž‘์„ฑ

์ด ๊ธ€์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ๋ถ„์˜ ์ƒ๊ฐ์„ ๋“ค๋ ค์ฃผ์„ธ์š”

๋Œ“๊ธ€ 0
๋Œ“๊ธ€์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ์ค‘์ž…๋‹ˆ๋‹ค.

์•„์ง ๋Œ“๊ธ€์ด ์—†์Šต๋‹ˆ๋‹ค.