Ver3.0 ๐ ์๋์ด๋ ธ Wi-Fi ๋ชจ๋๋ก ๋ง๋๋ ๋๋ง์ IoT ์ค๋งํธ ๊ธฐ๊ธฐ ์ฐ๋ ์๋ฒฝ ๊ฐ์ด๋

๐ ์๋์ด๋ ธ Wi-Fi ๋ชจ๋๋ก ๋ง๋๋ ๋๋ง์ IoT ์ค๋งํธ ๊ธฐ๊ธฐ ์ฐ๋ ์๋ฒฝ ๊ฐ์ด๋
์ด๋ณด์๋ ๋ฐ๋ผํ ์ ์๋ ์ค์ ์์ค์ฝ๋์ ํ๋ก์ ํธ ๋ ธํ์ฐ
๐ ์ ์ง๊ธ ์๋์ด๋ ธ Wi-Fi ๋ชจ๋์ธ๊ฐ?
์๋
, ์น๊ตฌ! ๐ ํน์ ์ง์์ ์ค๋งํธํฐ์ผ๋ก ์ ๋ฑ์ ์ผ๊ณ ๋๊ฑฐ๋, ์จ๋๋ฅผ ์ฒดํฌํ๊ณ , ์ฌ์ง์ด ์ปคํผ๋จธ์ ์ ์๊ฒฉ์ผ๋ก ์๋์ํค๋ ์์์ ํด๋ณธ ์ ์์ด? ์ด๊ฒ ๋ฐ๋ก IoT(Internet of Things, ์ฌ๋ฌผ์ธํฐ๋ท)์ ์ธ๊ณ์ผ. ๊ทธ๋ฆฌ๊ณ ์ด ๋ฉ์ง ์ธ๊ณ๋ก ๋ค์ด๊ฐ๋ ๊ฐ์ฅ ์ฝ๊ณ ์ฌ๋ฏธ์๋ ๋ฐฉ๋ฒ์ด ๋ฐ๋ก **์๋์ด๋
ธ Wi-Fi ๋ชจ๋**์ ํ์ฉํ๋ ๊ฑฐ์ง!
์์ฆ์ ์ ๋ง ๋๊ตฌ๋ ํ๋ก๊ทธ๋๋ฐ์ ๋ฐฐ์ฐ๊ณ , ์์ ๋ง์ ์ค๋งํธ ๊ธฐ๊ธฐ๋ฅผ ๋ง๋ค ์ ์๋ ์๋๊ฐ ๋์ด. ํนํ ์๋์ด๋
ธ๋ ํ๋์จ์ด ์
๋ฌธ์๋ค์๊ฒ ์ต๊ณ ์ ์น๊ตฌ ๊ฐ์ ์กด์ฌ์ผ. ๋ณต์กํ ์ ์๊ณตํ ์ง์ ์์ด๋ ์ผ์๋ฅผ ์ฐ๊ฒฐํ๊ณ , ์ฝ๋ ๋ช ์ค๋ก ์ํ๋ ๋์์ ๋ง๋ค์ด๋ผ ์ ์๊ฑฐ๋ . ๐ฏ
๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ ํ ๋จ๊ณ ๋ ๋์๊ฐ๋ฉด? ๋ฐ๋ก **Wi-Fi ๋ชจ๋**์ ์ถ๊ฐํ๋ ๊ฑฐ์ผ. ์ด๊ฑธ ์ฅ์ฐฉํ๋ฉด ์๋์ด๋
ธ๊ฐ ์ธํฐ๋ท์ ์ฐ๊ฒฐ๋๊ณ , ์ ์ธ๊ณ ์ด๋์๋ ๋ด๊ฐ ๋ง๋ ๊ธฐ๊ธฐ๋ฅผ ์ ์ดํ ์ ์๊ฒ ๋ผ. ์ง์ง ๋ง๋ฒ ๊ฐ์ง ์์? โจ
๐ก ์ด ๊ธ์์ ๋ฐฐ์ธ ์ ์๋ ๊ฒ๋ค
๐ ์๋์ด๋
ธ Wi-Fi ๋ชจ๋(ESP8266, ESP32)์ ๊ธฐ๋ณธ ๊ฐ๋
๊ณผ ์ฐจ์ด์
๐ ์ค์ ๋์ํ๋ IoT ๊ธฐ๊ธฐ ์ฐ๋ ์์ค์ฝ๋ (๋ณต์ฌํด์ ๋ฐ๋ก ์ฌ์ฉ ๊ฐ๋ฅ!)
๐ ์ค๋งํธํฐ ์ฑ๊ณผ ์ฐ๋ํ๋ ๋ฐฉ๋ฒ
๐ ์ผ์ ๋ฐ์ดํฐ๋ฅผ ํด๋ผ์ฐ๋๋ก ์ ์กํ๋ ์ค์ ํ๋ก์ ํธ
๐ ๋ฌธ์ ํด๊ฒฐ ํ๊ณผ ๋๋ฒ๊น
๋
ธํ์ฐ
๐ ์๋์ด๋ ธ Wi-Fi ๋ชจ๋, ๋ญ ์ ํํด์ผ ํ ๊น?
์๋์ด๋ ธ์ Wi-Fi ๊ธฐ๋ฅ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ์ฌ๋ฌ ๊ฐ์ง๊ฐ ์์ด. ๊ฐ์ฅ ์ธ๊ธฐ ์๋ ๋ ๊ฐ์ง ๋ชจ๋์ ์๊ฐํ ๊ฒ. ๊ฐ๊ฐ์ ํน์ง์ ์๋ฉด ๋ค ํ๋ก์ ํธ์ ๋ฑ ๋ง๋ ์ ํ์ ํ ์ ์์ ๊ฑฐ์ผ! ๐ค
๐ก ESP8266 - ๊ฐ์ฑ๋น ์ต๊ฐ ์ ๋ฌธ์ฉ
ESP8266์ ์ ๋ง ํ๋ช
์ ์ธ ๋ชจ๋์ด์ผ. ๊ฐ๊ฒฉ์ ๋ช ์ฒ ์ ์์ค์ธ๋ฐ, Wi-Fi ๊ธฐ๋ฅ์ ์๋ฒฝํ๊ฒ ์ ๊ณตํ๊ฑฐ๋ . NodeMCU๋ Wemos D1 Mini ๊ฐ์ ๊ฐ๋ฐ ๋ณด๋ ํํ๋ก ๋ง์ด ์ฌ์ฉ๋ผ.
์ฅ์ :
โ
์ ๋ ดํ ๊ฐ๊ฒฉ (3,000~5,000์ ์์ค)
โ
ํ๋ถํ ์ปค๋ฎค๋ํฐ์ ์์ ์ฝ๋
โ
์๋์ด๋
ธ IDE์์ ๋ฐ๋ก ํ๋ก๊ทธ๋๋ฐ ๊ฐ๋ฅ
โ
80MHz CPU, 4MB ํ๋์ ๋ฉ๋ชจ๋ฆฌ
๋จ์ :
โ ๏ธ GPIO ํ์ด ์ ์ (์ฝ 9~11๊ฐ)
โ ๏ธ ๋ธ๋ฃจํฌ์ค ๋ฏธ์ง์
โ ๏ธ ์ ๋ ฅ ์๋ชจ๊ฐ ๋ค์ ๋์
๐ ESP32 - ํ๋ก๊ธ ์ฑ๋ฅ์ ์ฌ์ธ์
ESP32๋ ESP8266์ ํ์ ๋ชจ๋ธ๋ก, ํจ์ฌ ๊ฐ๋ ฅํ ์ฑ๋ฅ์ ์๋ํด. ๋ณต์กํ ํ๋ก์ ํธ๋ ์ฌ๋ฌ ์ผ์๋ฅผ ๋์์ ๋ค๋ค์ผ ํ ๋ ์ต๊ณ ์ ์ ํ์ด์ง.
์ฅ์ :
โ
๋์ผ ์ฝ์ด 240MHz CPU (์์ฒญ ๋น ๋ฆ!)
โ
Wi-Fi + ๋ธ๋ฃจํฌ์ค ๋์ ์ง์
โ
๋ง์ GPIO ํ (์ฝ 30๊ฐ)
โ
ํฐ์น ์ผ์, DAC, ADC ๋ฑ ๋ค์ํ ๊ธฐ๋ฅ ๋ด์ฅ
โ
์ ์ ๋ ฅ ๋ชจ๋ ์ง์
๋จ์ :
โ ๏ธ ๊ฐ๊ฒฉ์ด ์กฐ๊ธ ๋ ๋น์ (7,000~10,000์)
โ ๏ธ ์ด๋ณด์์๊ฒ๋ ๋ค์ ๋ณต์กํ ์ ์์
๐ ๏ธ ๊ฐ๋ฐ ํ๊ฒฝ ์ธํ ํ๊ธฐ
์, ์ด์ ๋ณธ๊ฒฉ์ ์ผ๋ก ์ฝ๋ฉ์ ์์ํ๊ธฐ ์ ์ ๊ฐ๋ฐ ํ๊ฒฝ์ ์ค๋นํด์ผ ํด. ๊ฑฑ์ ๋ง, ์๊ฐ๋ณด๋ค ํจ์ฌ ๊ฐ๋จํด! ๐
1๋จ๊ณ: ์๋์ด๋ ธ IDE ์ค์น
์๋์ด๋ ธ ๊ณต์ ์น์ฌ์ดํธ(arduino.cc)์์ ์ต์ ๋ฒ์ ์ IDE๋ฅผ ๋ค์ด๋ก๋ํด. Windows, Mac, Linux ๋ชจ๋ ์ง์ํ๋๊น ๋ค ์ด์์ฒด์ ์ ๋ง๋ ๊ฑธ ์ ํํ๋ฉด ๋ผ. ์ค์น๋ ๊ทธ๋ฅ Next ๋ฒํผ๋ง ๋๋ฅด๋ฉด ๋! ๐ฑ๏ธ
2๋จ๊ณ: ESP8266/ESP32 ๋ณด๋ ์ถ๊ฐ
์๋์ด๋
ธ IDE๋ฅผ ์ด๊ณ ๋ค์ ๋จ๊ณ๋ฅผ ๋ฐ๋ผํด๋ด:
ํ์ผ โ ํ๊ฒฝ์ค์ ์ผ๋ก ๋ค์ด๊ฐ์ "์ถ๊ฐ์ ์ธ ๋ณด๋ ๋งค๋์ URLs"์ ์๋ ์ฃผ์๋ฅผ ์
๋ ฅํด:
http://arduino.esp8266.com/stable/package_esp8266com_index.jsonESP32๋ฅผ ์ฌ์ฉํ๋ค๋ฉด ์ด๊ฒ๋ ์ถ๊ฐ:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json๊ทธ ๋ค์ ๋๊ตฌ โ ๋ณด๋ โ ๋ณด๋ ๋งค๋์ ์์ "ESP8266" ๋๋ "ESP32"๋ฅผ ๊ฒ์ํด์ ์ค์นํ๋ฉด ๋! ๐
3๋จ๊ณ: ํ์ํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
IoT ํ๋ก์ ํธ๋ฅผ ์ํด ๋ช ๊ฐ์ง ์ ์ฉํ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ฏธ๋ฆฌ ์ค์นํด๋์:
๐ ESP8266WiFi ๋๋ WiFi.h (๋ณด๋ ์ค์น ์ ์๋ ํฌํจ)
๐ PubSubClient (MQTT ํต์ ์ฉ)
๐ ArduinoJson (JSON ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ฉ)
๐ Blynk (์ค๋งํธํฐ ์ฑ ์ฐ๋์ฉ)
์ค์ผ์น โ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํฌํจํ๊ธฐ โ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๊ด๋ฆฌ์์ ๊ฒ์ํด์ ์ค์นํ๋ฉด ๋ผ!
๐ป ์ฒซ ๋ฒ์งธ ํ๋ก์ ํธ: Wi-Fi ์ฐ๊ฒฐํ๊ธฐ
์, ์ด์ ์ง์ง ์ฝ๋ฉ์ ์์ํด๋ณผ๊น? ๊ฐ์ฅ ๊ธฐ๋ณธ์ด ๋๋ Wi-Fi ์ฐ๊ฒฐ ์ฝ๋๋ถํฐ ์์ํด๋ณด์. ์ด๊ฒ ๋ชจ๋ IoT ํ๋ก์ ํธ์ ์์์ ์ด์ผ! ๐
#include <ESP8266WiFi.h> // ESP32๋ <WiFi.h> ์ฌ์ฉ
// Wi-Fi ์ ๋ณด ์
๋ ฅ
const char* ssid = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
const char* password = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
void setup() {
Serial.begin(115200);
delay(10);
// Wi-Fi ์ฐ๊ฒฐ ์์
Serial.println();
Serial.print("์ฐ๊ฒฐ ์ค: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
// ์ฐ๊ฒฐ๋ ๋๊น์ง ๋๊ธฐ
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Wi-Fi ์ฐ๊ฒฐ ์ฑ๊ณต! ๐");
Serial.print("IP ์ฃผ์: ");
Serial.println(WiFi.localIP());
}
void loop() {
// ์ฐ๊ฒฐ ์ํ ํ์ธ
if (WiFi.status() == WL_CONNECTED) {
Serial.println("์ธํฐ๋ท ์ฐ๊ฒฐ ์ ์ง ์ค...");
} else {
Serial.println("์ฐ๊ฒฐ ๋๊น! ์ฌ์ฐ๊ฒฐ ์๋ ์ค...");
WiFi.begin(ssid, password);
}
delay(5000); // 5์ด๋ง๋ค ์ฒดํฌ
}
WiFi.begin()์ผ๋ก Wi-Fi ์ฐ๊ฒฐ์ ์์ํด2๏ธโฃ
while ๋ฃจํ๋ก ์ฐ๊ฒฐ๋ ๋๊น์ง ๊ธฐ๋ค๋ ค3๏ธโฃ ์ฐ๊ฒฐ๋๋ฉด
WiFi.localIP()๋ก ํ ๋น๋ฐ์ IP ์ฃผ์๋ฅผ ํ์ธํ ์ ์์ด4๏ธโฃ
loop()์์ ์ฃผ๊ธฐ์ ์ผ๋ก ์ฐ๊ฒฐ ์ํ๋ฅผ ์ฒดํฌํด์ ์์ ์ฑ์ ๋์ฌ
๐ ์น ์๋ฒ ๋ง๋ค๊ธฐ: ๋ธ๋ผ์ฐ์ ๋ก LED ์ ์ดํ๊ธฐ
์ด์ ์ข ๋ ์ฌ๋ฏธ์๋ ๊ฑธ ํด๋ณผ๊น? ์๋์ด๋ ธ๋ฅผ ์น ์๋ฒ๋ก ๋ง๋ค์ด์, ์ค๋งํธํฐ์ด๋ ์ปดํจํฐ ๋ธ๋ผ์ฐ์ ๋ก LED๋ฅผ ์ผ๊ณ ๋ ์ ์๊ฒ ๋ง๋ค์ด๋ณด์! ์ด๊ฒ ๋ฐ๋ก ์ง์ง IoT์ ์์์ด์ผ. ๐ก
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
const char* ssid = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
const char* password = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
// ์น ์๋ฒ ๊ฐ์ฒด ์์ฑ (ํฌํธ 80)
ESP8266WebServer server(80);
// LED ํ ์ค์ (NodeMCU์ ๋ด์ฅ LED๋ D4)
const int ledPin = D4;
bool ledState = false;
// ๋ฉ์ธ ํ์ด์ง HTML
String getHTML() {
String html = "<!DOCTYPE html><html>";
html += "<head><meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
html += "<title>LED ์ ์ด ์์คํ
</title>";
html += "<style>.tx-container{max-width:100%;
margin:0 auto;
font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;
line-height:1.8;
color:#333;}
.tx-header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
padding:40px 25px;
border-radius:16px;
text-align:center;
margin-bottom:35px;
box-shadow:0 8px 20px rgba(102,126,234,0.3);}
.tx-section{margin:35px 0;
padding:0;}
.tx-highlight-box{background:linear-gradient(135deg,#f5f7fa 0%,#c3cfe2 100%);
padding:20px;
border-radius:12px;
margin:25px 0;
border-left:5px solid #667eea;}
.tx-tip-box{background:#fff9e6;
padding:18px;
border-radius:10px;
margin:20px 0;
border-left:4px solid #ffd93d;}
.tx-step-box{background:#ffffff;
padding:20px;
border-radius:12px;
margin:20px 0;
box-shadow:0 2px 8px rgba(0,0,0,0.08);
border-top:3px solid #667eea;}
.tx-warning-box{background:#ffe6e6;
padding:18px;
border-radius:10px;
margin:20px 0;
border-left:4px solid #ff6b6b;}
.tx-table{width:100%;
border-collapse:collapse;
margin:20px 0;
font-size:0.95em;}
.tx-table th{background:#667eea;
color:white;
padding:12px;
text-align:left;
font-weight:600;}
.tx-table td{padding:12px;
border-bottom:1px solid #e1e4e8;}
.tx-table tr:nth-child(even){background:#f8f9fa;}
.tx-emoji{font-size:1.3em;
margin:0 3px;}</style></head>";
html += "<body><div class='container'>";
html += "<h1>๐ ์ค๋งํธ LED ์ ์ด</h1>";
html += "<div class='status " + String(ledState ? "on" : "off") + "'>";
html += "ํ์ฌ ์ํ: " + String(ledState ? "์ผ์ง ๐ก" : "๊บผ์ง ๐");
html += "</div>";
html += "<button class='button' onclick=\"location.href='/on'\">์ผ๊ธฐ ๐</button>";
html += "<button class='button' onclick=\"location.href='/off'\">๋๊ธฐ ๐</button>";
html += "</div></body></html>";
return html;
}
// LED ์ผ๊ธฐ ํธ๋ค๋ฌ
void handleOn() {
ledState = true;
digitalWrite(ledPin, LOW); // NodeMCU๋ LOW๊ฐ ์ผ์ง
server.send(200, "text/html", getHTML());
}
// LED ๋๊ธฐ ํธ๋ค๋ฌ
void handleOff() {
ledState = false;
digitalWrite(ledPin, HIGH); // NodeMCU๋ HIGH๊ฐ ๊บผ์ง
server.send(200, "text/html", getHTML());
}
// ๋ฉ์ธ ํ์ด์ง ํธ๋ค๋ฌ
void handleRoot() {
server.send(200, "text/html", getHTML());
}
void setup() {
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH); // ์ด๊ธฐ ์ํ: ๊บผ์ง
// Wi-Fi ์ฐ๊ฒฐ
Serial.print("Wi-Fi ์ฐ๊ฒฐ ์ค...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi ์ฐ๊ฒฐ ์ฑ๊ณต!");
Serial.print("IP ์ฃผ์: ");
Serial.println(WiFi.localIP());
Serial.println("๋ธ๋ผ์ฐ์ ์์ ์ IP ์ฃผ์๋ก ์ ์ํ์ธ์!");
// ์น ์๋ฒ ๋ผ์ฐํ
์ค์
server.on("/", handleRoot);
server.on("/on", handleOn);
server.on("/off", handleOff);
// ์๋ฒ ์์
server.begin();
Serial.println("์น ์๋ฒ ์์๋จ! ๐");
}
void loop() {
server.handleClient(); // ํด๋ผ์ด์ธํธ ์์ฒญ ์ฒ๋ฆฌ
}
๐ฏ ์ด ์ฝ๋์ ํต์ฌ ํฌ์ธํธ
1. ESP8266WebServer ๋ผ์ด๋ธ๋ฌ๋ฆฌ
์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ชจ๋ HTTP ์์ฒญ์ ์ฒ๋ฆฌํด์ค. ๋ณต์กํ ์น ์๋ฒ ๋ก์ง์ ๋ช ์ค๋ก ๊ตฌํํ ์ ์์ง! ๐
2. ๋ผ์ฐํ
์์คํ
server.on("/๊ฒฝ๋ก", ํจ์) ํํ๋ก URL ๊ฒฝ๋ก๋ง๋ค ๋ค๋ฅธ ๋์์ ์ง์ ํ ์ ์์ด. ๋ง์น ์น ํ๋ ์์ํฌ์ฒ๋ผ!
3. ๋ฐ์ํ HTML
viewport ๋ฉํ ํ๊ทธ ๋๋ถ์ ์ค๋งํธํฐ์์๋ ๊น๋ํ๊ฒ ๋ณด์ฌ. ๋ฒํผ๋ ํฐ์นํ๊ธฐ ์ข๊ฒ ํฌ๊ฒ ๋ง๋ค์์ด. ๐ฑ
4. ์ค์๊ฐ ์ํ ํ์
LED ์ํ๊ฐ ๋ฐ๋ ๋๋ง๋ค ํ์ด์ง๊ฐ ์๋ก๊ณ ์นจ๋๋ฉด์ ํ์ฌ ์ํ๋ฅผ ๋ณด์ฌ์ค. ์๊ฐ์ ํผ๋๋ฐฑ์ด ์ค์ํ๊ฑฐ๋ !
2. ์ถ๋ ฅ๋๋ IP ์ฃผ์๋ฅผ ํ์ธํด (์: 192.168.0.15)
3. ๊ฐ์ Wi-Fi์ ์ฐ๊ฒฐ๋ ์ค๋งํธํฐ์ด๋ ์ปดํจํฐ ๋ธ๋ผ์ฐ์ ์์ ๊ทธ IP ์ฃผ์๋ก ์ ์!
4. ๋ฒํผ์ ๋๋ฌ์ LED๋ฅผ ์ ์ดํด๋ด. ์ ๊ธฐํ์ง? ๐
๐ ์ผ์ ๋ฐ์ดํฐ ์ค์๊ฐ ๋ชจ๋ํฐ๋ง
์ด์ ํ ๋จ๊ณ ๋ ๋์๊ฐ๋ณผ๊น? ์จ์ต๋ ์ผ์(DHT11 ๋๋ DHT22)๋ฅผ ์ฐ๊ฒฐํด์ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์น ํ์ด์ง์ ํ์ํด๋ณด์. ์ด๊ฒ ๋ฐ๋ก ์ง์ง IoT ๋ชจ๋ํฐ๋ง ์์คํ ์ด์ผ! ๐ก๏ธ
๐ ํ๋์จ์ด ์ฐ๊ฒฐ
DHT11 ์ผ์๋ฅผ ๋ค์๊ณผ ๊ฐ์ด ์ฐ๊ฒฐํด:
๐ด VCC โ 3.3V (๋๋ 5V)
โซ GND โ GND
๐ก DATA โ D2 (GPIO4)
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <DHT.h>
const char* ssid = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
const char* password = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
// DHT ์ผ์ ์ค์
#define DHTPIN D2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
ESP8266WebServer server(80);
// ์ผ์ ๋ฐ์ดํฐ ์ ์ฅ ๋ณ์
float temperature = 0;
float humidity = 0;
unsigned long lastUpdate = 0;
// ๋ฉ์ธ ํ์ด์ง HTML (์๋ ์๋ก๊ณ ์นจ ํฌํจ)
String getHTML() {
String html = "<!DOCTYPE html><html>";
html += "<head><meta charset='UTF-8'>";
html += "<meta name='viewport' content='width=device-width, initial-scale=1.0'>";
html += "<meta http-equiv='refresh' content='5'>"; // 5์ด๋ง๋ค ์๋ ์๋ก๊ณ ์นจ
html += "<title>ํ๊ฒฝ ๋ชจ๋ํฐ๋ง ์์คํ
</title>";
html += "<style>.tx-container{max-width:100%;
margin:0 auto;
font-family:'Segoe UI',Tahoma,Geneva,Verdana,sans-serif;
line-height:1.8;
color:#333;}
.tx-header{background:linear-gradient(135deg,#667eea 0%,#764ba2 100%);
padding:40px 25px;
border-radius:16px;
text-align:center;
margin-bottom:35px;
box-shadow:0 8px 20px rgba(102,126,234,0.3);}
.tx-section{margin:35px 0;
padding:0;}
.tx-highlight-box{background:linear-gradient(135deg,#f5f7fa 0%,#c3cfe2 100%);
padding:20px;
border-radius:12px;
margin:25px 0;
border-left:5px solid #667eea;}
.tx-tip-box{background:#fff9e6;
padding:18px;
border-radius:10px;
margin:20px 0;
border-left:4px solid #ffd93d;}
.tx-step-box{background:#ffffff;
padding:20px;
border-radius:12px;
margin:20px 0;
box-shadow:0 2px 8px rgba(0,0,0,0.08);
border-top:3px solid #667eea;}
.tx-warning-box{background:#ffe6e6;
padding:18px;
border-radius:10px;
margin:20px 0;
border-left:4px solid #ff6b6b;}
.tx-table{width:100%;
border-collapse:collapse;
margin:20px 0;
font-size:0.95em;}
.tx-table th{background:#667eea;
color:white;
padding:12px;
text-align:left;
font-weight:600;}
.tx-table td{padding:12px;
border-bottom:1px solid #e1e4e8;}
.tx-table tr:nth-child(even){background:#f8f9fa;}
.tx-emoji{font-size:1.3em;
margin:0 3px;}</style></head>";
html += "<body><div class='container'>";
html += "<div class='header'><h1>๐ ์ค๋งํธ ํ๊ฒฝ ๋ชจ๋ํฐ๋ง</h1></div>";
html += "<div class='cards'>";
// ์จ๋ ์นด๋
html += "<div class='card'>";
html += "<div class='icon'>๐ก๏ธ</div>";
html += "<div class='value'>" + String(temperature, 1) + "ยฐC</div>";
html += "<div class='label'>์จ๋</div>";
html += "</div>";
// ์ต๋ ์นด๋
html += "<div class='card'>";
html += "<div class='icon'>๐ง</div>";
html += "<div class='value'>" + String(humidity, 1) + "%</div>";
html += "<div class='label'>์ต๋</div>";
html += "</div>";
// ์ฒด๊ฐ ์จ๋ ๊ณ์ฐ (๊ฐ๋จํ ๊ณต์)
float heatIndex = temperature + (0.5 * (humidity / 100) * (temperature - 14.5));
html += "<div class='card'>";
html += "<div class='icon'>๐ค๏ธ</div>";
html += "<div class='value'>" + String(heatIndex, 1) + "ยฐC</div>";
html += "<div class='label'>์ฒด๊ฐ์จ๋</div>";
html += "</div>";
html += "</div>";
html += "<div class='timestamp'>๋ง์ง๋ง ์
๋ฐ์ดํธ: " + String(millis() / 1000) + "์ด ์ </div>";
html += "</div></body></html>";
return html;
}
// JSON ํ์์ผ๋ก ๋ฐ์ดํฐ ์ ๊ณต (API ์๋ํฌ์ธํธ)
void handleData() {
String json = "{";
json += "\"temperature\":" + String(temperature, 2) + ",";
json += "\"humidity\":" + String(humidity, 2) + ",";
json += "\"timestamp\":" + String(millis());
json += "}";
server.send(200, "application/json", json);
}
void handleRoot() {
server.send(200, "text/html", getHTML());
}
void setup() {
Serial.begin(115200);
dht.begin();
// Wi-Fi ์ฐ๊ฒฐ
Serial.print("Wi-Fi ์ฐ๊ฒฐ ์ค...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("\nWi-Fi ์ฐ๊ฒฐ ์ฑ๊ณต!");
Serial.print("IP ์ฃผ์: ");
Serial.println(WiFi.localIP());
// ์น ์๋ฒ ์ค์
server.on("/", handleRoot);
server.on("/data", handleData); // JSON API
server.begin();
Serial.println("ํ๊ฒฝ ๋ชจ๋ํฐ๋ง ์์คํ
์์! ๐");
}
void loop() {
server.handleClient();
// 2์ด๋ง๋ค ์ผ์ ์ฝ๊ธฐ
if (millis() - lastUpdate > 2000) {
humidity = dht.readHumidity();
temperature = dht.readTemperature();
// ์ผ์ ์ฝ๊ธฐ ์คํจ ์ฒดํฌ
if (isnan(humidity) || isnan(temperature)) {
Serial.println("์ผ์ ์ฝ๊ธฐ ์คํจ!");
return;
}
Serial.print("์จ๋: ");
Serial.print(temperature);
Serial.print("ยฐC, ์ต๋: ");
Serial.print(humidity);
Serial.println("%");
lastUpdate = millis();
}
}
๐จ ์ด ํ๋ก์ ํธ์ ํน๋ณํ ๊ธฐ๋ฅ๋ค
1. ์๋ ์๋ก๊ณ ์นจ
<meta http-equiv='refresh' content='5'> ํ๊ทธ๋ก 5์ด๋ง๋ค ํ์ด์ง๊ฐ ์๋์ผ๋ก ์
๋ฐ์ดํธ๋ผ. ์ค์๊ฐ ๋ชจ๋ํฐ๋ง์ ํต์ฌ์ด์ง! โฑ๏ธ
2. ๋ฐ์ํ ๊ทธ๋ฆฌ๋ ๋ ์ด์์
CSS Grid๋ฅผ ์ฌ์ฉํด์ ํ๋ฉด ํฌ๊ธฐ์ ๋ฐ๋ผ ์นด๋๊ฐ ์๋์ผ๋ก ๋ฐฐ์น๋ผ. ์ค๋งํธํฐ์์๋ ์๋ฒฝํ๊ฒ ๋ณด์ฌ! ๐ฑ
3. JSON API ์๋ํฌ์ธํธ
/data ๊ฒฝ๋ก๋ก ์ ์ํ๋ฉด JSON ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ์ ์์ด. ๋ค๋ฅธ ์ฑ์ด๋ ์๋น์ค์ ์ฐ๋ํ ๋ ์ ์ฉํด! ๐
4. ์ฒด๊ฐ์จ๋ ๊ณ์ฐ
์จ๋์ ์ต๋๋ฅผ ์กฐํฉํด์ ์ค์ ๋ก ๋๊ปด์ง๋ ์จ๋๋ฅผ ๊ณ์ฐํด์ค. ๋ ์ค์ฉ์ ์ด์ง? ๐ก๏ธ
๐ฑ Blynk ์ฑ์ผ๋ก ์ค๋งํธํฐ ์ ์ดํ๊ธฐ
์น ๋ธ๋ผ์ฐ์ ๋ ์ข์ง๋ง, ์ ์ฉ ์ค๋งํธํฐ ์ฑ์ด ์์ผ๋ฉด ํจ์ฌ ํธํ๊ฒ ์ง? Blynk๋ ์ฝ๋ ๋ช ์ค๋ก ๋ฉ์ง IoT ์ฑ์ ๋ง๋ค ์ ์๊ฒ ํด์ฃผ๋ ํ๋ซํผ์ด์ผ. ๋ฌด๋ฃ๋ก ์ฌ์ฉํ ์ ์๊ณ , ์ ๋ง ๊ฐ๋ ฅํด! ๐ฒ
๐ Blynk ์์ํ๊ธฐ
1๋จ๊ณ: ์ฑ ์ค์น
๊ตฌ๊ธ ํ๋ ์ด์คํ ์ด๋ ์ฑ์คํ ์ด์์ "Blynk IoT"๋ฅผ ๊ฒ์ํด์ ์ค์นํด.
2๋จ๊ณ: ๊ณ์ ์์ฑ
์ด๋ฉ์ผ๋ก ๊ฐ๋จํ๊ฒ ๊ฐ์
ํ ์ ์์ด. ๋ฌด๋ฃ ํ๋์ผ๋ก๋ ์ถฉ๋ถํด!
3๋จ๊ณ: ์ ํ
ํ๋ฆฟ ์์ฑ
์ฑ์์ "New Template"์ ์ ํํ๊ณ , ๊ธฐ๊ธฐ ์ด๋ฆ์ ์ ํด์ค. ์๋ฅผ ๋ค์ด "์ค๋งํธ ํ ์ปจํธ๋กค๋ฌ" ๊ฐ์ ๊ฑฐ!
4๋จ๊ณ: Auth Token ๋ฐ๊ธฐ
ํ
ํ๋ฆฟ์ ๋ง๋ค๋ฉด ๊ณ ์ ํ ์ธ์ฆ ํ ํฐ์ ๋ฐ๊ฒ ๋ผ. ์ด๊ฑธ ์ฝ๋์ ๋ฃ์ด์ผ ํด!
#define BLYNK_TEMPLATE_ID "๋น์ ์_ํ
ํ๋ฆฟ_ID"
#define BLYNK_TEMPLATE_NAME "์ค๋งํธํ์ปจํธ๋กค๋ฌ"
#define BLYNK_AUTH_TOKEN "๋น์ ์_์ธ์ฆ_ํ ํฐ"
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
// Wi-Fi ์ ๋ณด
char ssid[] = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
char pass[] = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
// DHT ์ผ์ ์ค์
#define DHTPIN D2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// LED ํ
#define LED_PIN D4
// ํ์ด๋จธ ๊ฐ์ฒด
BlynkTimer timer;
// ์ผ์ ๋ฐ์ดํฐ๋ฅผ Blynk๋ก ์ ์กํ๋ ํจ์
void sendSensorData() {
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t)) {
Serial.println("์ผ์ ์ฝ๊ธฐ ์คํจ!");
return;
}
// Blynk ๊ฐ์ ํ์ผ๋ก ๋ฐ์ดํฐ ์ ์ก
Blynk.virtualWrite(V0, t); // V0์ ์จ๋
Blynk.virtualWrite(V1, h); // V1์ ์ต๋
Serial.print("์จ๋: ");
Serial.print(t);
Serial.print("ยฐC, ์ต๋: ");
Serial.print(h);
Serial.println("%");
}
// Blynk ์ฑ์์ ๋ฒํผ์ ๋๋ฅด๋ฉด ์คํ๋๋ ํจ์ (V2 ํ)
BLYNK_WRITE(V2) {
int value = param.asInt(); // ๋ฒํผ ์ํ (0 ๋๋ 1)
if (value == 1) {
digitalWrite(LED_PIN, LOW); // LED ์ผ๊ธฐ
Serial.println("LED ์ผ์ง! ๐ก");
} else {
digitalWrite(LED_PIN, HIGH); // LED ๋๊ธฐ
Serial.println("LED ๊บผ์ง! ๐");
}
}
// ์ฌ๋ผ์ด๋๋ก ๋ฐ๊ธฐ ์กฐ์ (PWM ํ ์ฌ์ฉ ์)
BLYNK_WRITE(V3) {
int brightness = param.asInt(); // 0~255
analogWrite(LED_PIN, brightness);
Serial.print("๋ฐ๊ธฐ: ");
Serial.println(brightness);
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
dht.begin();
// Blynk ์ฐ๊ฒฐ
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// 2์ด๋ง๋ค ์ผ์ ๋ฐ์ดํฐ ์ ์ก
timer.setInterval(2000L, sendSensorData);
Serial.println("Blynk ์์คํ
์ค๋น ์๋ฃ! ๐");
}
void loop() {
Blynk.run(); // Blynk ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์คํ
timer.run(); // ํ์ด๋จธ ์คํ
}
ํ ํ๋ฆฟ ์ค์ ์์ ๋ค์ ๊ฐ์ ํ๋ค์ ์ถ๊ฐํด:
โข V0: ์จ๋ (Double, 0~50)
โข V1: ์ต๋ (Double, 0~100)
โข V2: LED ์ ์ด (Integer, 0~1)
โข V3: ๋ฐ๊ธฐ ์กฐ์ (Integer, 0~255)
2. ์์ ฏ ๋ฐฐ์น
์ฑ ํ๋ฉด์ ๋ค์ ์์ ฏ๋ค์ ์ถ๊ฐํด:
โข Gauge ์์ ฏ 2๊ฐ (์จ๋, ์ต๋ ํ์์ฉ) โ V0, V1 ์ฐ๊ฒฐ
โข Switch ๋ฒํผ (LED ์ ์ด์ฉ) โ V2 ์ฐ๊ฒฐ
โข Slider (๋ฐ๊ธฐ ์กฐ์ ์ฉ) โ V3 ์ฐ๊ฒฐ
3. ๊ธฐ๊ธฐ ์ถ๊ฐ
"Add New Device"๋ก ์ค์ ๊ธฐ๊ธฐ๋ฅผ ๋ฑ๋กํ๊ณ , ์ฝ๋๋ฅผ ์ ๋ก๋ํ๋ฉด ์๋์ผ๋ก ์ฐ๊ฒฐ๋ผ! ๐
๐ Blynk์ ๊ฐ๋ ฅํ ๊ธฐ๋ฅ๋ค
๐ ์ค์๊ฐ ๊ทธ๋ํ: ์๊ฐ์ ๋ฐ๋ฅธ ์จ๋/์ต๋ ๋ณํ๋ฅผ ๊ทธ๋ํ๋ก ๋ณผ ์ ์์ด
๐ ์๋ฆผ ๊ธฐ๋ฅ: ํน์ ์กฐ๊ฑด์ด ๋๋ฉด ํธ์ ์๋ฆผ์ ๋ณด๋ผ ์ ์์ด
โฐ ํ์ด๋จธ: ํน์ ์๊ฐ์ ์๋์ผ๋ก ๊ธฐ๊ธฐ๋ฅผ ์ ์ดํ ์ ์์ด
๐ ์๊ฒฉ ์ ์ด: ์ ์ธ๊ณ ์ด๋์๋ ์ธํฐ๋ท๋ง ์์ผ๋ฉด ์ ์ด ๊ฐ๋ฅ!
๐ ๋ฐ์ดํฐ ๋ก๊น
: ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์๋์ผ๋ก ์ ์ฅํด์ ๋์ค์ ๋ถ์ํ ์ ์์ด
โ๏ธ MQTT๋ก ํด๋ผ์ฐ๋ ์ฐ๋ํ๊ธฐ
์ด์ ์ง์ง ํ๋ก๊ธ IoT ์์คํ ์ ๋ง๋ค์ด๋ณผ๊น? MQTT๋ IoT ๊ธฐ๊ธฐ๋ค์ด ์๋ก ํต์ ํ๋ ํ์ค ํ๋กํ ์ฝ์ด์ผ. ๊ฐ๋ณ๊ณ ํจ์จ์ ์ด์ด์ ์ ์ธ๊ณ IoT ํ๋ก์ ํธ์์ ์ฌ์ฉ๋๊ณ ์์ง! ๐
๐ MQTT๊ฐ ๋ญ์ผ?
MQTT(Message Queuing Telemetry Transport)๋ ๋ฐํ-๊ตฌ๋
(Publish-Subscribe) ๋ชจ๋ธ์ ์ฌ์ฉํ๋ ๋ฉ์์ง ํ๋กํ ์ฝ์ด์ผ.
ํต์ฌ ๊ฐ๋
:
๐ก Broker: ๋ฉ์์ง๋ฅผ ์ค๊ณํ๋ ์๋ฒ (์ฐ์ฒด๊ตญ ๊ฐ์ ์ญํ )
๐ค Publisher: ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ธฐ๊ธฐ (์๋์ด๋
ธ)
๐ฅ Subscriber: ๋ฉ์์ง๋ฅผ ๋ฐ๋ ๊ธฐ๊ธฐ (์ค๋งํธํฐ, ๋ค๋ฅธ ์๋์ด๋
ธ ๋ฑ)
๐ท๏ธ Topic: ๋ฉ์์ง์ ์ฃผ์ /์นดํ
๊ณ ๋ฆฌ (์: "home/temperature")
โข EMQX Cloud: ํ ๋ฌ ๋ฌด๋ฃ ์ฒดํ
โข Mosquitto: ์ง์ ์๋ฒ์ ์ค์น ๊ฐ๋ฅ (๋ผ์ฆ๋ฒ ๋ฆฌํ์ด์ ์ค์นํ๋ฉด ์์ ๋ฌด๋ฃ!)
โข test.mosquitto.org: ํ ์คํธ์ฉ ๊ณต๊ฐ ๋ธ๋ก์ปค (๋ณด์ ์ฃผ์!)
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
// Wi-Fi ์ค์
const char* ssid = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
const char* password = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
// MQTT ๋ธ๋ก์ปค ์ค์
const char* mqtt_server = "broker.hivemq.com"; // ๋๋ ๋น์ ์ ๋ธ๋ก์ปค ์ฃผ์
const int mqtt_port = 1883;
const char* mqtt_user = ""; // ํ์์ ์
๋ ฅ
const char* mqtt_password = ""; // ํ์์ ์
๋ ฅ
// MQTT ํ ํฝ ์ ์
const char* topic_temperature = "smarthome/sensor/temperature";
const char* topic_humidity = "smarthome/sensor/humidity";
const char* topic_led_control = "smarthome/control/led";
const char* topic_status = "smarthome/status";
// DHT ์ผ์
#define DHTPIN D2
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);
// LED ํ
#define LED_PIN D4
WiFiClient espClient;
PubSubClient client(espClient);
unsigned long lastMsg = 0;
float temperature = 0;
float humidity = 0;
// Wi-Fi ์ฐ๊ฒฐ ํจ์
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Wi-Fi ์ฐ๊ฒฐ ์ค: ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("Wi-Fi ์ฐ๊ฒฐ ์ฑ๊ณต!");
Serial.print("IP ์ฃผ์: ");
Serial.println(WiFi.localIP());
}
// MQTT ๋ฉ์์ง ์์ ์ฝ๋ฐฑ ํจ์
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("๋ฉ์์ง ๋์ฐฉ [");
Serial.print(topic);
Serial.print("]: ");
String message = "";
for (int i = 0; i < length; i++) {
message += (char)payload[i];
}
Serial.println(message);
// LED ์ ์ด ํ ํฝ ์ฒ๋ฆฌ
if (String(topic) == topic_led_control) {
if (message == "ON" || message == "1") {
digitalWrite(LED_PIN, LOW);
Serial.println("LED ์ผ์ง! ๐ก");
client.publish(topic_status, "LED is ON");
} else if (message == "OFF" || message == "0") {
digitalWrite(LED_PIN, HIGH);
Serial.println("LED ๊บผ์ง! ๐");
client.publish(topic_status, "LED is OFF");
}
}
}
// MQTT ์ฌ์ฐ๊ฒฐ ํจ์
void reconnect() {
while (!client.connected()) {
Serial.print("MQTT ์ฐ๊ฒฐ ์๋...");
// ๊ณ ์ ํ ํด๋ผ์ด์ธํธ ID ์์ฑ
String clientId = "ESP8266Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str(), mqtt_user, mqtt_password)) {
Serial.println("์ฐ๊ฒฐ ์ฑ๊ณต! ๐");
// ์ํ ๋ฉ์์ง ๋ฐํ
client.publish(topic_status, "ESP8266 Connected");
// LED ์ ์ด ํ ํฝ ๊ตฌ๋
client.subscribe(topic_led_control);
Serial.println("ํ ํฝ ๊ตฌ๋
์๋ฃ!");
} else {
Serial.print("์คํจ, rc=");
Serial.print(client.state());
Serial.println(" 5์ด ํ ์ฌ์๋...");
delay(5000);
}
}
}
void setup() {
Serial.begin(115200);
pinMode(LED_PIN, OUTPUT);
digitalWrite(LED_PIN, HIGH);
dht.begin();
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
client.setCallback(callback);
Serial.println("MQTT ์์คํ
์ค๋น ์๋ฃ! ๐");
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
// 5์ด๋ง๋ค ์ผ์ ๋ฐ์ดํฐ ๋ฐํ
if (now - lastMsg > 5000) {
lastMsg = now;
humidity = dht.readHumidity();
temperature = dht.readTemperature();
if (isnan(humidity) || isnan(temperature)) {
Serial.println("์ผ์ ์ฝ๊ธฐ ์คํจ!");
return;
}
// JSON ํ์์ผ๋ก ๋ฐ์ดํฐ ์์ฑ
StaticJsonDocument<200> doc;
doc["device"] = "ESP8266_Sensor";
doc["temperature"] = temperature;
doc["humidity"] = humidity;
doc["timestamp"] = now;
char jsonBuffer[200];
serializeJson(doc, jsonBuffer);
// ๊ฐ๋ณ ํ ํฝ์ผ๋ก ๋ฐํ
client.publish(topic_temperature, String(temperature).c_str());
client.publish(topic_humidity, String(humidity).c_str());
// JSON ๋ฐ์ดํฐ๋ ๋ฐํ
client.publish("smarthome/sensor/data", jsonBuffer);
Serial.print("๋ฐ์ดํฐ ๋ฐํ ์๋ฃ - ์จ๋: ");
Serial.print(temperature);
Serial.print("ยฐC, ์ต๋: ");
Serial.print(humidity);
Serial.println("%");
}
}
๐ฏ MQTT ์ฝ๋์ ํต์ฌ ํฌ์ธํธ
1. PubSubClient ๋ผ์ด๋ธ๋ฌ๋ฆฌ
ESP8266/ESP32์์ MQTT๋ฅผ ์ฝ๊ฒ ์ฌ์ฉํ ์ ์๊ฒ ํด์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ผ. ์ฐ๊ฒฐ, ๋ฐํ, ๊ตฌ๋
์ ๊ฐ๋จํ๊ฒ ์ฒ๋ฆฌํด์ค! ๐
2. ์ฝ๋ฐฑ ํจ์
callback() ํจ์๋ ๊ตฌ๋
ํ ํ ํฝ์ ๋ฉ์์ง๊ฐ ๋์ฐฉํ๋ฉด ์๋์ผ๋ก ์คํ๋ผ. ์ด๋ฒคํธ ๊ธฐ๋ฐ ํ๋ก๊ทธ๋๋ฐ์ ํต์ฌ์ด์ง! ๐ช
3. JSON ๋ฐ์ดํฐ ํฌ๋งท
ArduinoJson ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก ๊ตฌ์กฐํ๋ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฒ ๋ง๋ค ์ ์์ด. ์ฌ๋ฌ ๊ฐ์ ํ ๋ฒ์ ๋ณด๋ผ ๋ ์ ์ฉํด! ๐ฆ
4. ์๋ ์ฌ์ฐ๊ฒฐ
๋คํธ์ํฌ๊ฐ ๋๊ฒผ๋ค๊ฐ ๋ค์ ์ฐ๊ฒฐ๋๋ฉด ์๋์ผ๋ก MQTT ๋ธ๋ก์ปค์ ์ฌ์ฐ๊ฒฐํด. ์์ ์ฑ์ด ์ค์ํ๊ฑฐ๋ ! ๐
๐ Python์ผ๋ก MQTT ๋ฐ์ดํฐ ๋ฐ๊ธฐ
์๋์ด๋ ธ๊ฐ ๋ณด๋ธ ๋ฐ์ดํฐ๋ฅผ ์ปดํจํฐ์์ ๋ฐ์์ ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด? Python์ผ๋ก ๊ฐ๋จํ๊ฒ ๊ตฌํํ ์ ์์ด! ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅํ๊ฑฐ๋, ๊ทธ๋ํ๋ก ์๊ฐํํ๊ฑฐ๋, ๋ค๋ฅธ ์๋น์ค์ ์ฐ๋ํ ์ ์์ง. ๐
import paho.mqtt.client as mqtt
import json
from datetime import datetime
import sqlite3
# MQTT ๋ธ๋ก์ปค ์ค์
BROKER = "broker.hivemq.com"
PORT = 1883
TOPICS = [
("smarthome/sensor/data", 0),
("smarthome/control/led", 0)
]
# SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ
def init_database():
conn = sqlite3.connect('sensor_data.db')
cursor = conn.cursor()
cursor.execute('''
CREATE TABLE IF NOT EXISTS sensor_readings (
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
temperature REAL,
humidity REAL
)
''')
conn.commit()
conn.close()
print("๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ ์๋ฃ! ๐พ")
# ์ฐ๊ฒฐ ์ฑ๊ณต ์ฝ๋ฐฑ
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("MQTT ๋ธ๋ก์ปค ์ฐ๊ฒฐ ์ฑ๊ณต! ๐")
client.subscribe(TOPICS)
print(f"ํ ํฝ ๊ตฌ๋
์๋ฃ: {TOPICS}")
else:
print(f"์ฐ๊ฒฐ ์คํจ, ์ฝ๋: {rc}")
# ๋ฉ์์ง ์์ ์ฝ๋ฐฑ
def on_message(client, userdata, msg):
topic = msg.topic
payload = msg.payload.decode()
print(f"\n๐จ ๋ฉ์์ง ๋์ฐฉ!")
print(f"ํ ํฝ: {topic}")
print(f"๋ด์ฉ: {payload}")
# JSON ๋ฐ์ดํฐ ์ฒ๋ฆฌ
if topic == "smarthome/sensor/data":
try:
data = json.loads(payload)
temperature = data.get('temperature')
humidity = data.get('humidity')
# ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ์ ์ฅ
save_to_database(temperature, humidity)
# ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒดํฌ
check_alerts(temperature, humidity)
except json.JSONDecodeError:
print("JSON ํ์ฑ ์คํจ!")
# LED ์ ์ด ๋ช
๋ น ์ฒ๋ฆฌ
elif topic == "smarthome/control/led":
print(f"LED ์ํ ๋ณ๊ฒฝ: {payload}")
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ ์ฅ
def save_to_database(temperature, humidity):
conn = sqlite3.connect('sensor_data.db')
cursor = conn.cursor()
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
cursor.execute('''
INSERT INTO sensor_readings (timestamp, temperature, humidity)
VALUES (?, ?, ?)
''', (timestamp, temperature, humidity))
conn.commit()
conn.close()
print(f"โ
๋ฐ์ดํฐ ์ ์ฅ ์๋ฃ: {temperature}ยฐC, {humidity}%")
# ๊ฒฝ๊ณ ์กฐ๊ฑด ์ฒดํฌ
def check_alerts(temperature, humidity):
if temperature > 30:
print("๐ฅ ๊ฒฝ๊ณ : ์จ๋๊ฐ ๋๋ฌด ๋์ต๋๋ค!")
# ์ฌ๊ธฐ์ ์ด๋ฉ์ผ์ด๋ ํธ์ ์๋ฆผ์ ๋ณด๋ผ ์ ์์ด
if humidity > 80:
print("๐ง ๊ฒฝ๊ณ : ์ต๋๊ฐ ๋๋ฌด ๋์ต๋๋ค!")
if temperature < 10:
print("โ๏ธ ๊ฒฝ๊ณ : ์จ๋๊ฐ ๋๋ฌด ๋ฎ์ต๋๋ค!")
# ๋ฉ์ธ ํจ์
def main():
print("๐ MQTT ํด๋ผ์ด์ธํธ ์์...")
# ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ด๊ธฐํ
init_database()
# MQTT ํด๋ผ์ด์ธํธ ์์ฑ
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
# ๋ธ๋ก์ปค ์ฐ๊ฒฐ
try:
client.connect(BROKER, PORT, 60)
print(f"๋ธ๋ก์ปค ์ฐ๊ฒฐ ์๋: {BROKER}:{PORT}")
# ๋ฌดํ ๋ฃจํ (๋ฉ์์ง ์์ ๋๊ธฐ)
client.loop_forever()
except KeyboardInterrupt:
print("\nํ๋ก๊ทธ๋จ ์ข
๋ฃ...")
client.disconnect()
except Exception as e:
print(f"์ค๋ฅ ๋ฐ์: {e}")
if __name__ == "__main__":
main()
pip install paho-mqtt2. ์คํ ๋ฐฉ๋ฒ:
python mqtt_client.py3. ๋ฐ์ดํฐ ํ์ธ:
SQLite ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ์ผ(sensor_data.db)์ด ์์ฑ๋๊ณ , ๋ชจ๋ ์ผ์ ๋ฐ์ดํฐ๊ฐ ์๋์ผ๋ก ์ ์ฅ๋ผ!
๐ก ํ์ฅ ์์ด๋์ด
๐ ๋ฐ์ดํฐ ์๊ฐํ: matplotlib์ด๋ plotly๋ก ์ค์๊ฐ ๊ทธ๋ํ ๋ง๋ค๊ธฐ
๐ง ์ด๋ฉ์ผ ์๋ฆผ: smtplib๋ก ๊ฒฝ๊ณ ๋ฉ์ผ ์๋ ๋ฐ์ก
๐ ์น ๋์๋ณด๋: Flask๋ Django๋ก ์น ์ธํฐํ์ด์ค ๊ตฌ์ถ
๐ค ์๋ํ: ํน์ ์กฐ๊ฑด์์ ๋ค๋ฅธ ๊ธฐ๊ธฐ ์๋ ์ ์ด
โ๏ธ ํด๋ผ์ฐ๋ ์ฐ๋: AWS IoT, Google Cloud IoT์ ์ฐ๊ฒฐ
๐ ๋ณด์๊ณผ ์์ ์ฑ ๋์ด๊ธฐ
IoT ๊ธฐ๊ธฐ๋ฅผ ๋ง๋ค ๋ ๊ฐ์ฅ ์ค์ํ ๊ฑด ๋ณด์์ด์ผ! ํดํน๋นํ๋ฉด ๊ฐ์ธ์ ๋ณด๊ฐ ์ ์ถ๋๊ฑฐ๋, ๊ธฐ๊ธฐ๊ฐ ์ ์ฉ๋ ์ ์๊ฑฐ๋ . ๊ธฐ๋ณธ์ ์ธ ๋ณด์ ์กฐ์น๋ค์ ์์๋ณด์. ๐ก๏ธ
โ ๏ธ ์ ๋ ํ์ง ๋ง์์ผ ํ ๊ฒ๋ค
โ Wi-Fi ๋น๋ฐ๋ฒํธ๋ฅผ ์ฝ๋์ ํ๋์ฝ๋ฉํ์ง ๋ง! (GitHub์ ์ฌ๋ฆฌ๋ฉด ํฐ์ผ๋!)
โ ๊ณต๊ฐ MQTT ๋ธ๋ก์ปค์ ์ค์ํ ๋ฐ์ดํฐ ๋ณด๋ด์ง ๋ง!
โ ๊ธฐ๋ณธ ํฌํธ(80, 1883)๋ง ์ฌ์ฉํ์ง ๋ง!
โ ํ์จ์ด ์
๋ฐ์ดํธ ๊ธฐ๋ฅ ์์ด ๋ฐฐํฌํ์ง ๋ง!
โ ์๋ฌ ๋ฉ์์ง์ ๋ฏผ๊ฐํ ์ ๋ณด ํฌํจํ์ง ๋ง!
๐ 1. Wi-Fi ์๊ฒฉ์ฆ๋ช ์์ ํ๊ฒ ๊ด๋ฆฌํ๊ธฐ
Wi-Fi ์ ๋ณด๋ฅผ ๋ณ๋ ํ์ผ๋ก ๋ถ๋ฆฌํ๊ฑฐ๋, EEPROM์ ์ ์ฅํ๋ ๋ฐฉ๋ฒ์ ์ฌ์ฉํด:
#include <ESP8266WiFi.h>
#include <EEPROM.h>
// EEPROM ์ฃผ์ ์ ์
#define SSID_ADDR 0
#define PASS_ADDR 32
// Wi-Fi ์ค์ ์ ์ฅ
void saveWiFiConfig(String ssid, String password) {
EEPROM.begin(512);
// SSID ์ ์ฅ
for (int i = 0; i < ssid.length(); i++) {
EEPROM.write(SSID_ADDR + i, ssid[i]);
}
EEPROM.write(SSID_ADDR + ssid.length(), '\0');
// ๋น๋ฐ๋ฒํธ ์ ์ฅ
for (int i = 0; i < password.length(); i++) {
EEPROM.write(PASS_ADDR + i, password[i]);
}
EEPROM.write(PASS_ADDR + password.length(), '\0');
EEPROM.commit();
Serial.println("Wi-Fi ์ค์ ์ ์ฅ ์๋ฃ! ๐พ");
}
// Wi-Fi ์ค์ ์ฝ๊ธฐ
void loadWiFiConfig(char* ssid, char* password) {
EEPROM.begin(512);
// SSID ์ฝ๊ธฐ
for (int i = 0; i < 32; i++) {
ssid[i] = EEPROM.read(SSID_ADDR + i);
if (ssid[i] == '\0') break;
}
// ๋น๋ฐ๋ฒํธ ์ฝ๊ธฐ
for (int i = 0; i < 32; i++) {
password[i] = EEPROM.read(PASS_ADDR + i);
if (password[i] == '\0') break;
}
}
๐ 2. HTTPS์ MQTTS ์ฌ์ฉํ๊ธฐ
์ํธํ๋ ํต์ ์ ์ฌ์ฉํ๋ฉด ๋ฐ์ดํฐ๊ฐ ์ค๊ฐ์ ๊ฐ๋ก์ฑ์ด๋ ๊ฑธ ๋ฐฉ์งํ ์ ์์ด:
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>
// SSL/TLS ์ธ์ฆ์ (HiveMQ Cloud ์์)
const char* ca_cert = R"EOF(
-----BEGIN CERTIFICATE-----
์ฌ๊ธฐ์_์ธ์ฆ์_๋ด์ฉ_์
๋ ฅ
-----END CERTIFICATE-----
)EOF";
WiFiClientSecure espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
// ์ธ์ฆ์ ์ค์
espClient.setCACert(ca_cert);
// MQTTS ํฌํธ (8883)
client.setServer("your-broker.com", 8883);
Serial.println("๋ณด์ ์ฐ๊ฒฐ ์ค์ ์๋ฃ! ๐");
}
๐ก๏ธ 3. OTA(Over-The-Air) ์ ๋ฐ์ดํธ ๊ตฌํ
ํ์จ์ด๋ฅผ ๋ฌด์ ์ผ๋ก ์ ๋ฐ์ดํธํ ์ ์๊ฒ ํ๋ฉด, ๋ณด์ ํจ์น๋ฅผ ์ฝ๊ฒ ์ ์ฉํ ์ ์์ด:
#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>
void setup() {
Serial.begin(115200);
// Wi-Fi ์ฐ๊ฒฐ (์๋ต)
// OTA ์ค์
ArduinoOTA.setHostname("ESP8266-SmartHome");
ArduinoOTA.setPassword("your_ota_password"); // OTA ๋น๋ฐ๋ฒํธ ์ค์
ArduinoOTA.onStart([]() {
Serial.println("OTA ์
๋ฐ์ดํธ ์์...");
});
ArduinoOTA.onEnd([]() {
Serial.println("\nOTA ์
๋ฐ์ดํธ ์๋ฃ!");
});
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("์งํ๋ฅ : %u%%\r", (progress / (total / 100)));
});
ArduinoOTA.onError([](ota_error_t error) {
Serial.printf("์ค๋ฅ[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("์ธ์ฆ ์คํจ");
else if (error == OTA_BEGIN_ERROR) Serial.println("์์ ์คํจ");
else if (error == OTA_CONNECT_ERROR) Serial.println("์ฐ๊ฒฐ ์คํจ");
else if (error == OTA_RECEIVE_ERROR) Serial.println("์์ ์คํจ");
else if (error == OTA_END_ERROR) Serial.println("์ข
๋ฃ ์คํจ");
});
ArduinoOTA.begin();
Serial.println("OTA ์ค๋น ์๋ฃ! ๐");
}
void loop() {
ArduinoOTA.handle(); // OTA ์์ฒญ ์ฒ๋ฆฌ
// ๋๋จธ์ง ์ฝ๋...
}
์๋์ด๋ ธ IDE์์ ๋๊ตฌ โ ํฌํธ ๋ฉ๋ด๋ฅผ ๋ณด๋ฉด ๋คํธ์ํฌ ํฌํธ๊ฐ ๋ํ๋. ๊ทธ๊ฑธ ์ ํํ๊ณ ์ ๋ก๋ํ๋ฉด ๋ฌด์ ์ผ๋ก ํ์จ์ด๊ฐ ์ ๋ฐ์ดํธ๋ผ! USB ์ผ์ด๋ธ ์์ด๋ ๊ฐ๋ฅํด. ๐
โก 4. Watchdog ํ์ด๋จธ๋ก ์์ ์ฑ ๋์ด๊ธฐ
ํ๋ก๊ทธ๋จ์ด ๋ฉ์ถ๊ฑฐ๋ ๋ฌดํ๋ฃจํ์ ๋น ์ง๋ฉด ์๋์ผ๋ก ์ฌ์์ํ๊ฒ ๋ง๋ค์ด:
#include <ESP8266WiFi.h>
#include <Ticker.h>
Ticker watchdog;
volatile bool watchdogFlag = false;
// Watchdog ์ฝ๋ฐฑ
void watchdogCallback() {
watchdogFlag = true;
}
// Watchdog ๋ฆฌ์
void resetWatchdog() {
watchdogFlag = false;
}
void setup() {
Serial.begin(115200);
// Watchdog ํ์ด๋จธ ์์ (60์ด)
watchdog.attach(60, watchdogCallback);
Serial.println("Watchdog ํ์ฑํ! ๐");
}
void loop() {
// Watchdog ์ฒดํฌ
if (watchdogFlag) {
Serial.println("โ ๏ธ Watchdog ํ์์์! ์ฌ์์...");
ESP.restart();
}
// ์ ์ ๋์ ์ค์ด๋ฉด Watchdog ๋ฆฌ์
resetWatchdog();
// ๋๋จธ์ง ์ฝ๋...
delay(1000);
}
๐จ ์ค์ ํ๋ก์ ํธ: ์ค๋งํธ ํ๋ถ ๋ง๋ค๊ธฐ
์ด์ ๋ฐฐ์ด ๊ฑธ ๋ชจ๋ ํฉ์ณ์ ์ค์ฉ์ ์ธ ํ๋ก์ ํธ๋ฅผ ๋ง๋ค์ด๋ณด์! ํ ์ ์ต๋๋ฅผ ๋ชจ๋ํฐ๋งํ๊ณ , ์๋์ผ๋ก ๋ฌผ์ ์ฃผ๋ ์ค๋งํธ ํ๋ถ์ด์ผ. ๐ฑ
๐ ๏ธ ํ์ํ ๋ถํ
1๏ธโฃ NodeMCU (ESP8266) - 1๊ฐ
2๏ธโฃ ํ ์ ์ต๋ ์ผ์ (Capacitive Soil Moisture Sensor) - 1๊ฐ
3๏ธโฃ ๋ฏธ๋ ์ํฐ ํํ (3-6V) - 1๊ฐ
4๏ธโฃ ๋ฆด๋ ์ด ๋ชจ๋ (5V) - 1๊ฐ
5๏ธโฃ DHT11 ์จ์ต๋ ์ผ์ - 1๊ฐ
6๏ธโฃ ์ ํผ ์์ด์ด, ๋ธ๋ ๋๋ณด๋
7๏ธโฃ 5V ์ ์ ์ด๋ํฐ
์ด ๋น์ฉ: ์ฝ 2๋ง์ ๋ด์ธ (์ฌ๋ฅ๋ท์์ ๋ถํ ๊ตฌ๋งค ํ์ ๊ณต์ ํ๋ ์ ๋ฌธ๊ฐ๋ค๋ ๋ง์!)
๐ ํ๋ก ์ฐ๊ฒฐ
ํ ์ ์ต๋ ์ผ์:
โข VCC โ 3.3V
โข GND โ GND
โข AOUT โ A0 (์๋ ๋ก๊ทธ ์
๋ ฅ)
DHT11 ์ผ์:
โข VCC โ 3.3V
โข GND โ GND
โข DATA โ D2
๋ฆด๋ ์ด ๋ชจ๋:
โข VCC โ 5V (์ธ๋ถ ์ ์)
โข GND โ GND
โข IN โ D1
์ํฐ ํํ:
โข ๋ฆด๋ ์ด์ NO(Normally Open)์ COM ๋จ์์ ์ฐ๊ฒฐ
โข ์ ์์ ๋ณ๋ 5V ๊ณต๊ธ
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <DHT.h>
// Blynk ์ค์
#define BLYNK_TEMPLATE_ID "๋น์ ์_ํ
ํ๋ฆฟ_ID"
#define BLYNK_TEMPLATE_NAME "์ค๋งํธํ๋ถ"
#define BLYNK_AUTH_TOKEN "๋น์ ์_์ธ์ฆ_ํ ํฐ"
// Wi-Fi ์ค์
char ssid[] = "๋น์ ์_์์ดํ์ด_์ด๋ฆ";
char pass[] = "๋น์ ์_์์ดํ์ด_๋น๋ฐ๋ฒํธ";
// ํ ์ ์
#define SOIL_SENSOR_PIN A0
#define PUMP_PIN D1
#define DHT_PIN D2
#define DHT_TYPE DHT11
DHT dht(DHT_PIN, DHT_TYPE);
BlynkTimer timer;
// ์ค์ ๊ฐ
int soilMoistureThreshold = 30; // ์ต๋ 30% ์ดํ๋ฉด ๋ฌผ ์ฃผ๊ธฐ
bool autoWateringEnabled = true;
int wateringDuration = 5000; // 5์ด๊ฐ ๋ฌผ ์ฃผ๊ธฐ
// ์ผ์ ๋ฐ์ดํฐ ์ ์ก
void sendSensorData() {
// ํ ์ ์ต๋ ์ฝ๊ธฐ (0~1023, ๋ฎ์์๋ก ์ตํจ)
int soilValue = analogRead(SOIL_SENSOR_PIN);
int soilMoisture = map(soilValue, 1023, 0, 0, 100); // 0~100%๋ก ๋ณํ
// ์จ์ต๋ ์ฝ๊ธฐ
float temperature = dht.readTemperature();
float humidity = dht.readHumidity();
if (isnan(temperature) || isnan(humidity)) {
Serial.println("DHT ์ผ์ ์ฝ๊ธฐ ์คํจ!");
return;
}
// Blynk๋ก ๋ฐ์ดํฐ ์ ์ก
Blynk.virtualWrite(V0, soilMoisture); // ํ ์ ์ต๋
Blynk.virtualWrite(V1, temperature); // ์จ๋
Blynk.virtualWrite(V2, humidity); // ์ต๋
Serial.print("ํ ์ ์ต๋: ");
Serial.print(soilMoisture);
Serial.print("%, ์จ๋: ");
Serial.print(temperature);
Serial.print("ยฐC, ์ต๋: ");
Serial.print(humidity);
Serial.println("%");
// ์๋ ๋ฌผ์ฃผ๊ธฐ ์ฒดํฌ
if (autoWateringEnabled && soilMoisture < soilMoistureThreshold) {
waterPlant();
}
}
// ๋ฌผ ์ฃผ๊ธฐ ํจ์
void waterPlant() {
Serial.println("๐ง ๋ฌผ ์ฃผ๊ธฐ ์์!");
Blynk.logEvent("watering_started", "ํ๋ถ์ ๋ฌผ์ ์ฃผ๊ณ ์์ต๋๋ค.");
digitalWrite(PUMP_PIN, HIGH); // ํํ ์ผ๊ธฐ
delay(wateringDuration);
digitalWrite(PUMP_PIN, LOW); // ํํ ๋๊ธฐ
Serial.println("โ
๋ฌผ ์ฃผ๊ธฐ ์๋ฃ!");
Blynk.logEvent("watering_completed", "๋ฌผ ์ฃผ๊ธฐ๊ฐ ์๋ฃ๋์์ต๋๋ค.");
}
// Blynk ๋ฒํผ: ์๋ ๋ฌผ์ฃผ๊ธฐ (V3)
BLYNK_WRITE(V3) {
int value = param.asInt();
if (value == 1) {
waterPlant();
}
}
// Blynk ์ค์์น: ์๋ ๋ฌผ์ฃผ๊ธฐ ํ์ฑํ/๋นํ์ฑํ (V4)
BLYNK_WRITE(V4) {
autoWateringEnabled = param.asInt();
Serial.print("์๋ ๋ฌผ์ฃผ๊ธฐ: ");
Serial.println(autoWateringEnabled ? "ํ์ฑํ" : "๋นํ์ฑํ");
}
// Blynk ์ฌ๋ผ์ด๋: ์ต๋ ์๊ณ๊ฐ ์ค์ (V5)
BLYNK_WRITE(V5) {
soilMoistureThreshold = param.asInt();
Serial.print("์ต๋ ์๊ณ๊ฐ ๋ณ๊ฒฝ: ");
Serial.print(soilMoistureThreshold);
Serial.println("%");
}
// Blynk ์ฌ๋ผ์ด๋: ๋ฌผ์ฃผ๊ธฐ ์๊ฐ ์ค์ (V6)
BLYNK_WRITE(V6) {
wateringDuration = param.asInt() * 1000; // ์ด ๋จ์๋ฅผ ๋ฐ๋ฆฌ์ด๋ก ๋ณํ
Serial.print("๋ฌผ์ฃผ๊ธฐ ์๊ฐ ๋ณ๊ฒฝ: ");
Serial.print(wateringDuration / 1000);
Serial.println("์ด");
}
void setup() {
Serial.begin(115200);
pinMode(PUMP_PIN, OUTPUT);
digitalWrite(PUMP_PIN, LOW);
dht.begin();
// Blynk ์ฐ๊ฒฐ
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// 10์ด๋ง๋ค ์ผ์ ๋ฐ์ดํฐ ์ ์ก
timer.setInterval(10000L, sendSensorData);
Serial.println("๐ฑ ์ค๋งํธ ํ๋ถ ์์คํ
์์!");
}
void loop() {
Blynk.run();
timer.run();
}
๐ฏ ํ๋ก์ ํธ์ ํต์ฌ ๊ธฐ๋ฅ
๐ ์ค์๊ฐ ๋ชจ๋ํฐ๋ง: ํ ์ ์ต๋, ์จ๋, ์ต๋๋ฅผ 10์ด๋ง๋ค ์ฒดํฌ
๐ง ์๋ ๋ฌผ์ฃผ๊ธฐ: ํ ์์ด ๊ฑด์กฐํ๋ฉด ์๋์ผ๋ก ๋ฌผ์ ์ค
๐ฑ ์๊ฒฉ ์ ์ด: ์ค๋งํธํฐ์ผ๋ก ์ธ์ ์ด๋์๋ ์๋์ผ๋ก ๋ฌผ์ ์ค ์ ์์ด
โ๏ธ ๋ง์ถค ์ค์ : ์ต๋ ์๊ณ๊ฐ๊ณผ ๋ฌผ์ฃผ๊ธฐ ์๊ฐ์ ์กฐ์ ๊ฐ๋ฅ
๐ ์๋ฆผ ๊ธฐ๋ฅ: ๋ฌผ์ ์ค ๋๋ง๋ค ํธ์ ์๋ฆผ ๋ฐ์ก
๐ ๋ฐ์ดํฐ ๋ก๊น
: Blynk ํด๋ผ์ฐ๋์ ๋ชจ๋ ๋ฐ์ดํฐ ์๋ ์ ์ฅ
โข ๋ฌผํฑํฌ ์์ ์ผ์๋ก ๋ฌผ ๋ถ์กฑ ์๋ฆผ
โข ๋ ์จ API ์ฐ๋ํด์ ๋น ์ค๋ ๋ ์ ๋ฌผ์ฃผ๊ธฐ ์คํต
โข ์ฌ๋ฌ ํ๋ถ์ ๋์์ ๊ด๋ฆฌํ๋ ์์คํ ์ผ๋ก ํ์ฅ
โข ์๋ฌผ ์ฑ์ฅ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํด์ ์ต์ ์ ํ๊ฒฝ ์ ์
๐ ๋ฌธ์ ํด๊ฒฐ ๊ฐ์ด๋
IoT ํ๋ก์ ํธ๋ฅผ ํ๋ค ๋ณด๋ฉด ์ฌ๋ฌ ๊ฐ์ง ๋ฌธ์ ์ ๋ถ๋ชํ๊ฒ ๋ผ. ๊ฐ์ฅ ํํ ๋ฌธ์ ๋ค๊ณผ ํด๊ฒฐ ๋ฐฉ๋ฒ์ ์ ๋ฆฌํด๋ดค์ด! ๐ง
| ๋ฌธ์ | ์์ธ | ํด๊ฒฐ ๋ฐฉ๋ฒ |
|---|---|---|
| Wi-Fi ์ฐ๊ฒฐ ์ ๋จ | ์๋ชป๋ SSID/๋น๋ฐ๋ฒํธ, 5GHz ๋คํธ์ํฌ | 2.4GHz ๋คํธ์ํฌ ์ฌ์ฉ, ๋์๋ฌธ์ ํ์ธ, ํน์๋ฌธ์ ์ฃผ์ |
| ์ ๋ก๋ ์คํจ | ์๋ชป๋ ๋ณด๋/ํฌํธ ์ ํ, ๋๋ผ์ด๋ฒ ๋ฌธ์ | CH340 ๋๋ผ์ด๋ฒ ์ค์น, ์ฌ๋ฐ๋ฅธ ๋ณด๋ ์ ํ, USB ์ผ์ด๋ธ ๊ต์ฒด |
| ์ผ์ ๊ฐ์ด ์ด์ํจ | ์๋ชป๋ ์ฐ๊ฒฐ, ์ ์ ๋ถ์กฑ, ์ผ์ ๋ถ๋ | ์ฐ๊ฒฐ ์ฌํ์ธ, ์ธ๋ถ ์ ์ ์ฌ์ฉ, ์ผ์ ๊ต์ฒด |
| MQTT ์ฐ๊ฒฐ ๋๊น | ๋คํธ์ํฌ ๋ถ์์ , ๋ธ๋ก์ปค ๋ฌธ์ | ์ฌ์ฐ๊ฒฐ ๋ก์ง ์ถ๊ฐ, Watchdog ์ฌ์ฉ, ์์ ์ ์ธ ๋ธ๋ก์ปค ์ ํ |
| ๋ฉ๋ชจ๋ฆฌ ๋ถ์กฑ | ๋๋ฌด ๋ง์ ๋ณ์, ํฐ ๋ฌธ์์ด | F() ๋งคํฌ๋ก ์ฌ์ฉ, ๋ถํ์ํ ๋ณ์ ์ ๊ฑฐ, PROGMEM ํ์ฉ |
| ์น ์๋ฒ ๋๋ฆผ | ํฐ HTML, ๋๊ธฐ ์ฒ๋ฆฌ | HTML ์ต์ํ, ๋น๋๊ธฐ ์น ์๋ฒ ์ฌ์ฉ, ์ด๋ฏธ์ง ์ธ๋ถ ํธ์คํ |
โก ์ ์ ๊ด๋ จ ์ฃผ์์ฌํญ
์ ๋ ์ฃผ์! ๋ฆด๋ ์ด๋ ๋ชจํฐ๋ฅผ ์ฌ์ฉํ ๋๋ ๋ฐ๋์ ์ธ๋ถ ์ ์์ ์ฌ์ฉํด์ผ ํด. NodeMCU์ 3.3V ํ์ผ๋ก๋ ๋ถ์กฑํ๊ณ , USB ์ ์๋ง์ผ๋ก๋ ๋ถ์์ ํ ์ ์์ด. 5V 2A ์ด์์ ์ด๋ํฐ๋ฅผ ์ฌ์ฉํ๋ ๊ฒ ์์ ํด! โ ๏ธ
๊ทธ๋ฆฌ๊ณ ๋ฆด๋ ์ด ๋ชจ๋์ VCC๋ 5V์, ์ ํธ์ (IN)์ NodeMCU์ ๋์งํธ ํ์ ์ฐ๊ฒฐํด์ผ ํด. ์ ์๊ณผ ์ ํธ๋ฅผ ํผ๋ํ์ง ์๋๋ก ์กฐ์ฌ!
๐ ๋๋ฒ๊น ํ
1. ์๋ฆฌ์ผ ๋ชจ๋ํฐ ์ ๊ทน ํ์ฉ
Serial.println()์ผ๋ก ๋ณ์ ๊ฐ๊ณผ ์คํ ํ๋ฆ์ ๊ณ์ ์ถ๋ ฅํด๋ด. ์ด๋์ ๋ฌธ์ ๊ฐ ์๊ธฐ๋์ง ๊ธ๋ฐฉ ์ ์ ์์ด! ๐ฅ๏ธ
2. ๋จ๊ณ๋ณ๋ก ํ
์คํธ
๋ชจ๋ ๊ธฐ๋ฅ์ ํ ๋ฒ์ ๊ตฌํํ์ง ๋ง๊ณ , ํ๋์ฉ ํ
์คํธํ๋ฉด์ ์ถ๊ฐํด. Wi-Fi ์ฐ๊ฒฐ โ ์ผ์ ์ฝ๊ธฐ โ ์น ์๋ฒ โ MQTT ์์๋ก! ๐
3. ์์ ์ฝ๋ ์ฐธ๊ณ
ํ์ผ โ ์์ ๋ฉ๋ด์ ์๋ ๊ธฐ๋ณธ ์์ ๋ค์ ๋จผ์ ์คํํด๋ด. ๋์ํ๋ ์ฝ๋๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์์ ํ๋ ๊ฒ ํจ์ฌ ์ฌ์! ๐
4. ์ปค๋ฎค๋ํฐ ํ์ฉ
๋งํ๋ฉด ๊ตฌ๊ธ๋งํ๊ฑฐ๋, ์๋์ด๋
ธ ํฌ๋ผ, ๋ค์ด๋ฒ ์นดํ ๋ฑ์ ์ง๋ฌธํด๋ด. ๊ฐ์ ๋ฌธ์ ๋ฅผ ๊ฒช์ ์ฌ๋์ด ๋ฐ๋์ ์์ด! ๐ค
๐ ๋ค์ ๋จ๊ณ: ๋ ๋ฐ์ ์ํค๊ธฐ
๊ธฐ๋ณธ์ ๋ง์คํฐํ๋ค๋ฉด, ์ด์ ๋ ๋ฉ์ง ํ๋ก์ ํธ๋ก ๋์๊ฐ ์ฐจ๋ก์ผ! ์ฌ๊ธฐ ๋ช ๊ฐ์ง ์์ด๋์ด๋ฅผ ์๊ฐํ ๊ฒ. ๐ก
๐ 1. ์ค๋งํธ ํ ํตํฉ ์์คํ
์ฌ๋ฌ ๊ฐ์ ESP8266/ESP32๋ฅผ ์ฌ์ฉํด์ ์ง ์ ์ฒด๋ฅผ ์ค๋งํธํ๊ฒ ๋ง๋ค์ด๋ด:
๐ก ๊ฑฐ์ค: ์กฐ๋ช
์ ์ด, ์จ๋ ๋ชจ๋ํฐ๋ง
๐ช ํ๊ด: ๋์ด๋ฝ, ๋ชจ์
์ผ์
๐๏ธ ์นจ์ค: ์ปคํผ ์๋ ๊ฐํ, ๊ณต๊ธฐ์ง ์ธก์
๐ณ ์ฃผ๋ฐฉ: ๊ฐ์ค ๊ฐ์ง, ํํ๊ธฐ ์ ์ด
๋ชจ๋ ๊ธฐ๊ธฐ๋ฅผ MQTT๋ก ์ฐ๊ฒฐํ๊ณ , ์ค์ ๋์๋ณด๋์์ ํตํฉ ๊ด๋ฆฌ! Home Assistant๋ Node-RED ๊ฐ์ ํ๋ซํผ๊ณผ ์ฐ๋ํ๋ฉด ๋์ฑ ๊ฐ๋ ฅํด์ ธ. ๐ก
๐ค 2. AI์ ๋จธ์ ๋ฌ๋ ์ฐ๋
์ผ์ ๋ฐ์ดํฐ๋ฅผ ์์งํด์ ํจํด์ ๋ถ์ํ๊ณ , ์์ธก ๋ชจ๋ธ์ ๋ง๋ค์ด๋ด:
โข TensorFlow Lite๋ฅผ ESP32์ ํ์ฌํด์ ์ฃ์ง AI ๊ตฌํ
โข ํด๋ผ์ฐ๋์์ ๋จธ์ ๋ฌ๋ ๋ชจ๋ธ ํ์ต ํ ์์ธก ๊ฒฐ๊ณผ ๋ฐ๊ธฐ
โข ์์ฑ ์ธ์์ผ๋ก ๊ธฐ๊ธฐ ์ ์ด (Google Assistant, Alexa ์ฐ๋)
โข ์ด๋ฏธ์ง ์ธ์์ผ๋ก ๋ฌผ์ฒด ๊ฐ์ง (ESP32-CAM ์ฌ์ฉ)
์๋ฅผ ๋ค์ด, ์๋์ง ์ฌ์ฉ ํจํด์ ํ์ตํด์ ์ต์ ์ ์ ์ฝ ๋ฐฉ๋ฒ์ ์ ์ํ๊ฑฐ๋, ์๋ฌผ ์ ์ฌ์ง์ผ๋ก ๋ณ์ถฉํด๋ฅผ ์ง๋จํ ์ ์์ด! ๐ง
๐ 3. ๋ฐ์ดํฐ ๋ถ์๊ณผ ์๊ฐํ
์์งํ ๋ฐ์ดํฐ๋ฅผ ์๋ฏธ ์๊ฒ ํ์ฉํด๋ด:
โข InfluxDB + Grafana๋ก ์ค์๊ฐ ๋์๋ณด๋ ๊ตฌ์ถ
โข Python Pandas๋ก ๋ฐ์ดํฐ ๋ถ์ ๋ฐ ๋ฆฌํฌํธ ์์ฑ
โข Jupyter Notebook์ผ๋ก ์ธํฐ๋ํฐ๋ธ ๋ถ์
โข Tableau๋ Power BI๋ก ๋น์ฆ๋์ค ์ธํ
๋ฆฌ์ ์ค
์ฅ๊ธฐ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๋ถ์ํ๋ฉด ์จ๊ฒจ์ง ์ธ์ฌ์ดํธ๋ฅผ ๋ฐ๊ฒฌํ ์ ์์ด. ์๋ฅผ ๋ค์ด, "์ต๋๊ฐ ๋์ ๋ ์๋ฌผ์ด ๋ ์ ์๋๋ค" ๊ฐ์ ํจํด์ ์ฐพ์ ์ ์์ง! ๐
๐ 4. ์์ฉ ์ ํ ๊ฐ๋ฐ
์ทจ๋ฏธ ํ๋ก์ ํธ๋ฅผ ๋์ด์ ์ค์ ์ ํ์ผ๋ก ๋ง๋ค์ด๋ด:
โข PCB ์ค๊ณ (KiCad, EasyEDA ์ฌ์ฉ)
โข 3D ํ๋ฆฐํ
์ผ๋ก ์ผ์ด์ค ์ ์
โข ๋ฐฐํฐ๋ฆฌ ์ ์ ๋ฐ ์ ์ ๋ ฅ ๋ชจ๋ ๊ตฌํ
โข ๋๋ ์์ฐ์ ์ํ ํ์จ์ด ์ต์ ํ
โข ํฌ๋ผ์ฐ๋ ํ๋ฉ (ํฅ์คํํฐ, ์๋์ฆ)
์ค์ ๋ก ๋ง์ ์คํํธ์
๋ค์ด ์๋์ด๋
ธ ํ๋กํ ํ์
์ผ๋ก ์์ํ์ด. ๋์ ์์ด๋์ด๊ฐ ๋ค์ ํํธ ์ ํ์ด ๋ ์๋ ์์ด! ๐ฐ
๐ ํ์ต ๋ฆฌ์์ค ์ถ์ฒ
์จ๋ผ์ธ ๊ฐ์:
โข Udemy: "Complete ESP32/ESP8266 Course"
โข Coursera: "Introduction to the Internet of Things"
โข YouTube: Andreas Spiess, GreatScott!, ๋๋ค์ํฌ
์ปค๋ฎค๋ํฐ:
โข ์๋์ด๋
ธ ๊ณต์ ํฌ๋ผ (forum.arduino.cc)
โข ESP8266/ESP32 ์ปค๋ฎค๋ํฐ (esp8266.com)
โข ๋ค์ด๋ฒ ์นดํ: ์๋์ด๋
ธ ์ฌ์ฉ์ ๋ชจ์
โข ์ฌ๋ฅ๋ท์ ์ง์์ธ์ ์ฒ (๋ค์ํ ์ ๋ฌธ๊ฐ๋ค์ ๋
ธํ์ฐ!)
์ฑ
:
โข "ESP8266 ํ๋ก๊ทธ๋๋ฐ" - ํ๋น๋ฏธ๋์ด
โข "์ฌ๋ฌผ์ธํฐ๋ท์ ์ํ ESP32 ํ๋ก๊ทธ๋๋ฐ" - ์ ์ดํ
โข "Make: IoT" - ํ๋น๋ฏธ๋์ด
๐ฌ ๋ง์น๋ฉฐ
์, ์ฌ๊ธฐ๊น์ง ์ฝ์๋ค๋ฉด ์ ๋ง ๋๋จํด! ๐ ์ฐ๋ฆฌ๋ ์๋์ด๋
ธ Wi-Fi ๋ชจ๋์ ๊ธฐ์ด๋ถํฐ ์ค์ ํ๋ก์ ํธ, ๋ณด์, ๊ทธ๋ฆฌ๊ณ ๋ฏธ๋ ๋ฐ์ ๋ฐฉํฅ๊น์ง ๋ชจ๋ ์ดํด๋ดค์ด.
IoT๋ ์ ๋ง ๋งค๋ ฅ์ ์ธ ๋ถ์ผ์ผ. ํ๋์จ์ด์ ์ํํธ์จ์ด, ๋คํธ์ํฌ๊ฐ ๋ชจ๋ ๊ฒฐํฉ๋์ด ์๊ณ , ์์ํ ๊ฑธ ์ง์ ๋ง๋ค์ด์ ์ค์ํ์ ์ ์ฉํ ์ ์๊ฑฐ๋ . ์ฒ์์ LED ํ๋ ๊น๋นก์ด๋ ๊ฒ๋ ์ ๊ธฐํ๋๋ฐ, ์ด์ ๋ ์ ์ธ๊ณ ์ด๋์๋ ์ง์ ์จ๋๋ฅผ ํ์ธํ๊ณ ํ๋ถ์ ๋ฌผ์ ์ค ์ ์์์? ๐
๊ฐ์ฅ ์ค์ํ ๊ฑด ์ง์ ํด๋ณด๋ ๊ฒ์ด์ผ. ์ด ๊ธ์ ์ฝ๋๋ค์ ๊ทธ๋๋ก ๋ฐ๋ผ ํด๋ณด๊ณ , ์กฐ๊ธ์ฉ ์์ ํ๋ฉด์ ๋ค ์คํ์ผ๋ก ๋ง๋ค์ด๋ด. ์คํจํ๊ณ ๋๋ฒ๊น
ํ๋ ๊ณผ์ ์์ ์ง์ง ์ค๋ ฅ์ด ๋์ด๋๊ฑฐ๋ . ๐ช
๊ทธ๋ฆฌ๊ณ ํผ์ ํ๊ธฐ ์ด๋ ต๋ค๋ฉด ์ฌ๋ฅ๋ท ๊ฐ์ ํ๋ซํผ์ ํ์ฉํด๋ด. IoT ํ๋ก์ ํธ๋ฅผ ๋์์ฃผ๋ ์ ๋ฌธ๊ฐ๋ค๋ ๋ง๊ณ , ๋ฐ๋๋ก ๋ค๊ฐ ๋ฐฐ์ด ๊ฑธ ๋ค๋ฅธ ์ฌ๋์๊ฒ ๊ฐ๋ฅด์ณ์ฃผ๋ฉด์ ์์ต๋ ๋ผ ์ ์์ด. ์ง์์ ๋๋๋ ๊ฑด ์ ๋ง ๋ณด๋์ฐฌ ์ผ์ด์ผ! ๐ค
์์ผ๋ก IoT ๊ธฐ์ ์ ๋์ฑ ๋ฐ์ ํ ๊ฑฐ์ผ. 5G, AI, ๋ธ๋ก์ฒด์ธ๊ณผ ๊ฒฐํฉ๋๋ฉด์ ์ฐ๋ฆฌ๊ฐ ์์ํ์ง ๋ชปํ ์๋ก์ด ์๋น์ค๋ค์ด ๋์ฌ ๊ฑฐ๊ณ . ์ง๊ธ ๋ฐฐ์ฐ๋ ์ด ๊ธฐ์ ๋ค์ด ๋ฏธ๋์ ๊ธฐํ๊ฐ ๋ ์ ์์ด. ๐
์, ์ด์ ์ปดํจํฐ ์์์ ์ผ์ด๋์ ์ค์ ๋ก ๋ง๋ค์ด๋ณด์! ๋ธ๋ ๋๋ณด๋์ ์ ํผ ์์ด์ด๋ฅผ ๊บผ๋ด๊ณ , ESP8266์ ์ฐ๊ฒฐํ๊ณ , ์ฒซ ๋ฒ์งธ IoT ๊ธฐ๊ธฐ๋ฅผ ์์ฑํด๋ด. ๋ค๊ฐ ๋ง๋ ๊ธฐ๊ธฐ๊ฐ Wi-Fi์ ์ฐ๊ฒฐ๋๊ณ , ์ค๋งํธํฐ์ผ๋ก ์ ์ด๋๋ ์๊ฐ์ ์ง๋ฆฟํจ์ ๋๊ปด๋ด! ๐
์ง๋ฌธ์ด๋ ํ๋ก์ ํธ ์์ด๋์ด๊ฐ ์๋ค๋ฉด ์ธ์ ๋ ์ปค๋ฎค๋ํฐ์ ๊ณต์ ํด. ์ฐ๋ฆฌ๋ ๋ชจ๋ ํจ๊ป ๋ฐฐ์ฐ๊ณ ์ฑ์ฅํ๋ ๋ฉ์ด์ปค๋ค์ด๋๊น! ๐
ํดํผ ๋ฉ์ดํน! ๐๐ง๐ป
๐ ์ด ๊ธ์ด ๋์์ด ๋์๋ค๋ฉด, ์ฌ๋ฅ๋ท์์ ๋ ๋ง์ ์ง์์ ํํํด๋ณด์ธ์! ๐
ํ๋ก๊ทธ๋๋ฐ๋ถํฐ IoT, ํ๋์จ์ด๊น์ง - ๋น์ ์ ์ฌ๋ฅ์ ๋๋๊ณ ๋ฐฐ์ฐ๋ ๊ณต๊ฐ
๊ด๋ จ ํค์๋
๋๊ธ ์์ฑ
์ด ๊ธ์ ๋ํ ์ฌ๋ฌ๋ถ์ ์๊ฐ์ ๋ค๋ ค์ฃผ์ธ์
๋ก๊ทธ์ธ์ด ํ์ํฉ๋๋ค
๋๊ธ์ ์์ฑํ๋ ค๋ฉด ๋จผ์ ๋ก๊ทธ์ธํด์ฃผ์ธ์.
๋๊ธ 0
์ง์์ธ์ ์ฒ - ์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
์ง์ ์ฌ์ฐ๊ถ ๋ณดํธ ๊ณ ์ง
- ์ ์๊ถ ๋ฐ ์์ ๊ถ: ๋ณธ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ๋ ์ AI ๊ธฐ์ ๋ก ์์ฑ๋์์ผ๋ฉฐ, ๋ํ๋ฏผ๊ตญ ์ ์๊ถ๋ฒ ๋ฐ ๊ตญ์ ์ ์๊ถ ํ์ฝ์ ์ํด ๋ณดํธ๋ฉ๋๋ค.
- AI ์์ฑ ์ปจํ ์ธ ์ ๋ฒ์ ์ง์: ๋ณธ AI ์์ฑ ์ปจํ ์ธ ๋ ์ฌ๋ฅ๋ท์ ์ง์ ์ฐฝ์๋ฌผ๋ก ์ธ์ ๋๋ฉฐ, ๊ด๋ จ ๋ฒ๊ท์ ๋ฐ๋ผ ์ ์๊ถ ๋ณดํธ๋ฅผ ๋ฐ์ต๋๋ค.
- ์ฌ์ฉ ์ ํ: ์ฌ๋ฅ๋ท์ ๋ช ์์ ์๋ฉด ๋์ ์์ด ๋ณธ ์ปจํ ์ธ ๋ฅผ ๋ณต์ , ์์ , ๋ฐฐํฌ, ๋๋ ์์ ์ ์ผ๋ก ํ์ฉํ๋ ํ์๋ ์๊ฒฉํ ๊ธ์ง๋ฉ๋๋ค.
- ๋ฐ์ดํฐ ์์ง ๊ธ์ง: ๋ณธ ์ปจํ ์ธ ์ ๋ํ ๋ฌด๋จ ์คํฌ๋ํ, ํฌ๋กค๋ง, ๋ฐ ์๋ํ๋ ๋ฐ์ดํฐ ์์ง์ ๋ฒ์ ์ ์ฌ์ ๋์์ด ๋ฉ๋๋ค.
- AI ํ์ต ์ ํ: ์ฌ๋ฅ๋ท์ AI ์์ฑ ์ปจํ ์ธ ๋ฅผ ํ AI ๋ชจ๋ธ ํ์ต์ ๋ฌด๋จ ์ฌ์ฉํ๋ ํ์๋ ๊ธ์ง๋๋ฉฐ, ์ด๋ ์ง์ ์ฌ์ฐ๊ถ ์นจํด๋ก ๊ฐ์ฃผ๋ฉ๋๋ค.
์์ง ๋๊ธ์ด ์์ต๋๋ค.