06주차 ‐ ESP32 Web Server 실습 1 - movie-01/SmartDevice GitHub Wiki

06주차 - ESP32 Web Server 실습 1


개요

  • ESP32 Wi‐Fi 모드
  • 웹서버
  • 웹서버 구축 실습
  • LED 제어 웹 서버 실습

📡 ESP32 Wi‐Fi 모드

ESP32는 Wi-Fi 및 Bluetooth를 모두 지원하는 강력한 SoC(System on Chip)로, 다양한 무선 통신 기능을 제공한다. 그 중 Wi-Fi는 IoT 개발에 있어서 핵심적인 역할을 하며, ESP32는 3가지 주요 Wi-Fi 모드를 지원한다. 이 모드를 이해하면 네트워크 연결 방식에 따라 적절한 설정이 가능해진다.

  • STA 모드: 기존 WiFi 네트워크에 클라이언트로 접속
  • AP 모드: ESP32 자체가 WiFi 네트워크 제공 (Soft AP)

https://github.com/movie-01/SmartDevice/wiki/6%EC%A3%BC%EC%B0%A8_%EC%B0%B8%EA%B3%A0-%E2%80%90-ESP32-Wi%E2%80%90Fi-%EB%AA%A8%EB%93%9C


🌐 웹서버

웹서버는 **클라이언트(브라우저 등)**로부터의 요청을 받아, 웹페이지나 데이터 등을 응답해주는 소프트웨어 또는 시스템을 말한다. 일반적으로 HTTP 또는 HTTPS 프로토콜을 사용하며, 웹 개발과 IoT 시스템에서 핵심적인 역할을 수행한다.

https://github.com/movie-01/SmartDevice/wiki/6%EC%A3%BC%EC%B0%A8_%EC%B0%B8%EA%B3%A0-%E2%80%90-%EC%9B%B9%EC%84%9C%EB%B2%84


웹서버 구축 실습 코드

ESP32가 지정된 Wi-Fi에 연결하고, 포트 80에서 웹서버를 구동하며, 클라이언트(브라우저 등)가 접속하면 "Hello from ESP32!"라는 텍스트를 전송하고 연결을 종료한다.

#include <WiFi.h> // ESP32 Wi-Fi 기능을 사용하기 위한 라이브러리 포함

// 접속할 Wi-Fi 네트워크의 SSID(이름)와 비밀번호
const char* ssid = "YourSSID";
const char* password = "YourPassword";

// 웹서버 객체 생성 (포트 80번 사용 - 기본 HTTP 포트)
WiFiServer server(80);

void setup() {
  Serial.begin(115200); // 시리얼 통신 시작 (디버깅용)

  WiFi.begin(ssid, password); // 지정한 SSID와 비밀번호로 Wi-Fi 네트워크에 접속 시도

  // Wi-Fi 연결이 완료될 때까지 대기
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting..."); // 연결 상태 출력
  }

  // 연결 완료 후 ESP32의 IP 주소 출력
  Serial.println(WiFi.localIP());

  // 웹서버 시작
  server.begin();
}

void loop() {
  // 클라이언트가 접속했는지 확인 (있다면 client 객체로 반환)
  WiFiClient client = server.available();

  // 클라이언트가 존재하면
  if (client) {
    // 클라이언트에게 간단한 메시지 전송
    client.println("Hello from ESP32!");

    delay(10); // 짧은 대기 (데이터 전송 시간 확보)

    // 클라이언트 연결 종료
    client.stop();
  }
}

💡 참고 팁

  • 공유기로 실습을 해도 괜찮지만 휴대폰 핫스팟 기능을 통해 실습하는 방법이 비교적 간단하다.
  • 브라우저에서 http://<ESP32_IP> 로 접속하면 텍스트 메시지를 받을 수 있다.
  • 이 구조를 확장하면 HTML 페이지나 JSON 응답, REST API 등을 구현할 수 있다.

❌ 출력을 이상한 문자로 되받을 경우

  • 소스 코드의 값과 아두이노의 설정 값이 다를 경우 이와 같은 결과를 출력한다.

image


🔧 도구 > 보드, 도구 > 포트를 다음 사진과 같이 설정한다.

image

🔧 도구 > 시리얼 모니터의 속도를 소스코드에 맞춰서 "115200" 설정해야 원하는 값을 얻을 수 있다.

image


❌ IP값을 접속 실패 시 방법

  • 사진과 같이 IP값을 똑같이 입력해도 계속 접속 실패가 나타날 수 있다.

image

🔧 ESP32와 브라우저(PC 또는 휴대폰)가 같은 Wi-Fi에 연결되어 있어야 한다.

예시 상황:

  • ESP32는 thismovie라는 핫스팟에 연결됨
  • 그런데 PC는 집 와이파이에 연결되어 있음 -> 이러면 IP 주소가 다르기 때문에 통신 안 됨

🔧 해결 방법:

  • PC나 휴대폰도 thismovie에 연결되어 있어야 함
  • ESP32와 같은 네트워크(같은 공유기, 같은 핫스팟) 에 있어야 접속 가능

✅ 정상적으로 출력이 되는 모습이다.

image


📲 LED 제어 웹 서버 실습

  • 라이브러리 매니저 검색창에 "ESPAsyncWebserver" 입력 후 "ESPAsyncWebSrv by dvarrel" 설치 image

💡 참고 팁

  • HTML을 아두이노 코드에 직접 client.println()으로 작성하는 방법이 있다.
  • HTML을 외부 파일을 통해 불러오는 방법이 있다.(이럴 땐 SPIFFS 또는 LittleFS 사용)
  • 이번 실습은 코드가 단순해서 client.println() 방법으로 작성할 것이다.

코드 작성(코드 안에 HTML 포함한 방법)

#include <WiFi.h>

// Wi-Fi 접속 정보
const char* ssid = "thismovie";
const char* password = "eltmanql0730";

// 보드에 내장된 LED 핀 (보통 GPIO2)
const int LED_PIN = 2;

// 웹서버 생성
WiFiServer server(80);

void setup() {
  pinMode(LED_PIN, OUTPUT);       // LED 핀 출력으로 설정
  digitalWrite(LED_PIN, LOW);     // 처음엔 꺼짐

  Serial.begin(115200);
  WiFi.begin(ssid, password);

  // Wi-Fi 연결 대기
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting...");
  }

  Serial.print("Connected! IP: ");
  Serial.println(WiFi.localIP());

  server.begin();
}

void loop() {
  WiFiClient client = server.available();

  if (client) {
    Serial.println("Client connected");

    // HTTP 요청 받기
    String request = client.readStringUntil('\r');
    Serial.println("Request: " + request);
    client.flush();

    // 요청 분석 (LED 제어)
    if (request.indexOf("GET /LED_ON") >= 0) {
      digitalWrite(LED_PIN, HIGH);  // LED 켜기
    } else if (request.indexOf("GET /LED_OFF") >= 0) {
      digitalWrite(LED_PIN, LOW);   // LED 끄기
    }

    // HTML 페이지 전송
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println();

    client.println("<!DOCTYPE html><html>");
    client.println("<head><title>LED 제어</title></head>");
    client.println("<body style='text-align:center; font-family:sans-serif;'>");
    client.println("<h1 style='color:#3498db;'>ESP32 LED 제어</h1>");

    client.println("<form action=\"/LED_ON\" method=\"GET\">");
    client.println("<button style='padding:15px 30px; font-size:20px; background-color:#3498db; color:white; border:none; border-radius:8px;'>불 켜기 🔵</button>");
    client.println("</form><br>");

    client.println("<form action=\"/LED_OFF\" method=\"GET\">");
    client.println("<button style='padding:15px 30px; font-size:20px; background-color:#aaa; color:white; border:none; border-radius:8px;'>불 끄기 ⚫</button>");
    client.println("</form>");

    client.println("</body></html>");

    delay(1);
    client.stop();
    Serial.println("Client disconnected");
  }
}

❌ 한글이 깨지는 현상

  • 이전 코드를 입력하면 한글이 깨지는 현상이 나타난다.

image

원인은 ESP32가 웹 브라우저에 HTML 보낼 때 문자 인코딩을 UTF-8로 지정하지 않으면 브라우저는 기본값(예: EUC-KR, ISO-8859-1 등)으로 해석해서 한글이 다 깨져서 보인다.

✅ Content-Type에 "charset=UTF-8" 추가해주고 HTML

안에 다음 코드를 입력하면 된다.
<meta charset="UTF-8">

🔧 다음 코드는 수정된 부분이다.

client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html; charset=UTF-8");  // charset 추가
client.println();

client.println("<!DOCTYPE html><html>");
client.println("<head>");
client.println("<meta charset=\"UTF-8\">");  // 여기에도 추가
client.println("<title>LED 제어</title>");
client.println("</head>");
client.println("<body>");
client.println("<h1>파란 불 켜기</h1>");

✨ 이제 브라우저에서 한글이 깔끔하게 제대로 출력 된다.

LED.mp4
⚠️ **GitHub.com Fallback** ⚠️