서론
이전 글에서는 Wi-Fi를 Scan하여 주변의 AP(Access Point)가 어떤 것이 있는지 확인하고, Zephyr의 Wi-Fi Scan 과정과 Event Callback이 어떻게 동작하는지 살펴보았습니다.
이번 글에서는 여기서 한 단계 더 나아가, Zephyr ESP32 Wi-Fi AP 연결을 직접 실습해 보겠습니다. 검색된 AP 중 하나를 선택하여 ESP32를 실제로 연결하고, IP Network에 참여하는 과정까지 확인해 보겠습니다.
Wi-Fi AP에 연결하려면 SSID와 Password 등의 접속 정보를 설정하고 Zephyr의 Network Management API를 통해 연결을 요청해야 합니다. 연결 과정 역시 Scan과 마찬가지로 Event 기반으로 처리되며, 연결 결과는 Callback을 통해 확인할 수 있습니다.
또한 AP에 연결되는 것만으로 끝나는 것이 아니라, DHCP를 통해 ESP32에 IP Address가 정상적으로 할당되는지까지 확인해 보겠습니다.
이번 실습을 통해 다음과 같은 흐름을 확인하는 것이 목표입니다.
AP 연결 요청 → Wi-Fi 연결 Event → DHCP → IP Address 할당
여기까지 정상적으로 동작하면 ESP32가 Wi-Fi Network에 참여할 수 있는 기본 준비가 완료된 것입니다. 이후에는 UDP, TCP, HTTP, MQTT와 같은 실제 Network 통신 실습으로 확장할 수 있습니다.
Wi-Fi AP 연결 과정 이해하기
이전 실습의 Wi-Fi Scan은 ESP32 주변에 어떤 AP(Access Point)가 있는지 검색하는 과정이었습니다. Scan을 통해 SSID, Channel, RSSI, Security 방식 등의 정보를 확인할 수 있었지만, 아직 ESP32가 해당 네트워크에 참여한 것은 아닙니다.
이번 실습에서는 검색된 AP 중 하나를 선택하여 실제로 연결해 보겠습니다.
Wi-Fi AP에 연결하기 위해서는 일반적으로 다음과 같은 정보가 필요합니다.
- SSID : 연결하려는 Wi-Fi AP의 이름
- Password : Wi-Fi 접속 암호
- Security : WPA2 등의 보안 방식
이 정보를 이용하여 Zephyr에 AP 연결을 요청하면 ESP32의 Wi-Fi Driver가 실제 연결 과정을 수행합니다.
Zephyr의 Wi-Fi 연결 및 관리 기능에 대한 자세한 내용은 Zephyr Wi-Fi Management 공식 문서에서 확인할 수 있습니다.
공식 문서는 각 API와 Event의 기능을 확인하는 데 유용하지만, 실제 AP 연결 과정을 이해하려면 이들을 어떤 순서로 사용해야 하는지 함께 살펴볼 필요가 있습니다.
아래 그림은 AP 연결 요청부터 IP Address가 할당되기까지의 전체 과정을 나타낸 것입니다.

전체 과정은 크게 Wi-Fi Connection과 IP Network Connection의 두 단계로 나누어 볼 수 있습니다.
먼저 Wi-Fi Connection 단계에서는 SSID, Password, Security 정보를 이용하여 NET_REQUEST_WIFI_CONNECT로 AP 연결을 요청합니다. 이후 ESP32와 AP 사이에서 Authentication과 Association 과정이 진행되고, 그 결과는 NET_EVENT_WIFI_CONNECT_RESULT Event를 통해 Application에 전달됩니다.
여기까지 성공하면 ESP32는 Wi-Fi AP와 무선으로 연결된 상태가 됩니다.
그러나 Wi-Fi AP에 연결되었다는 것과 IP 네트워크를 사용할 수 있다는 것은 같은 의미가 아닙니다.
UDP나 TCP와 같은 IP 기반 통신을 하기 위해서는 ESP32에 IP Address가 필요합니다. 따라서 Wi-Fi 연결 후에는 DHCP를 통한 IP Network Configuration 과정이 이어집니다.
DHCP를 통해 IPv4 Address가 할당되면 Zephyr에서는 NET_EVENT_IPV4_ADDR_ADD Event가 발생합니다. 이 Event까지 확인하면 ESP32가 IP Address를 정상적으로 할당받아 네트워크 통신을 수행할 준비가 되었다고 볼 수 있습니다.
따라서 이번 실습에서 확인할 전체 흐름은 다음과 같이 정리할 수 있습니다.
SSID / Password / Security 설정 → AP 연결 요청 → Authentication & Association → Wi-Fi 연결 완료 → DHCP → IP Address 할당 → Network Ready
여기까지 완료되면 다음 단계에서 UDP나 TCP를 이용하여 ESP32와 다른 네트워크 장치 사이에 실제 데이터를 주고받을 수 있습니다.
프로젝트 생성 및 설정
이번 실습은 이전 Wi-Fi Scan 실습에서 사용한 ESP32 프로젝트를 기반으로 진행합니다.
Wi-Fi Scan 프로젝트에는 ESP32에서 Wi-Fi를 사용하기 위한 기본적인 프로젝트 구조와 설정이 이미 포함되어 있으므로, 기존 skpang_esp32_can_wifiscan 폴더를 복사하여 새로운 skpang_esp32_can_wificonnect 프로젝트를 만듭니다.
생성된 프로젝트의 폴더 구조는 아래와 같습니다.

기본적인 프로젝트 구조는 이전 Wi-Fi Scan 실습과 동일하지만, 이번에는 AP 연결과 DHCP를 통한 IP Address 할당이 필요하므로 프로젝트의 일부 설정과 소스 코드를 변경해야 합니다.
새 프로젝트를 생성한 후 다음 파일을 차례로 점검하고 수정합니다.
CMakeLists.txtprj.confCHANGELOG.md
이후 main.c는 Wi-Fi AP 연결 과정을 구현하기 위해 새롭게 작성하겠습니다.
CMakeList.txt 수정
CMakeLists.txt는 이전 Wi-Fi Scan 프로젝트의 설정을 그대로 사용하고, 아래와 같이 프로젝트 이름만 skpang_esp32_can_wificonnect로 변경합니다.

target_sources()에서는 이전과 동일하게 src/main.c를 Application Source로 지정합니다. 이번 실습에서는 별도의 Source File을 추가하지 않으므로 그 외의 설정은 변경하지 않습니다.
prj.conf 수정
prj.conf 파일은 이전 Wi-Fi Scan 프로젝트의 설정을 대부분 그대로 사용하고, 아래와 같이 두 가지 부분을 수정해 줍니다.

① IPv4 및 DHCP 설정 추가
이번 실습에서는 AP 연결 후 DHCP를 통해 IP Address를 할당받아야 하므로 다음 설정을 추가합니다.
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=y
CONFIG_NET_IPV4는 Zephyr의 IPv4 기능을 활성화하고, CONFIG_NET_DHCPV4는 DHCP Client 기능을 활성화합니다.
이 설정을 통해 ESP32가 Wi-Fi AP에 연결된 후 DHCP를 이용하여 IPv4 Address를 자동으로 할당받을 수 있습니다.
② Kernel Binary 이름 변경
새로운 프로젝트 이름에 맞게 다음과 같이 Kernel Binary 이름도 변경합니다.
CONFIG_KERNEL_BIN_NAME="skpang_esp32_can_wificonnect"
이 설정에 따라 빌드 결과 생성되는 Binary File의 이름도 새로운 프로젝트 이름에 맞게 변경됩니다.
그 외의 Wi-Fi, Network Management 및 Console 관련 설정은 이전 Wi-Fi Scan 프로젝트에서 사용했던 설정을 그대로 사용합니다.
CHANGELOG.md 수정
CHANGELOG.md 도 기존 파일에서 변경된 부분을 추가하여 완성합니다.

위 파일은 이번 실습을 완료한 후의 모습입니다. 프로젝트를 처음 시작할 때는 구현 내용을 미리 기록하지 않고, 개발을 진행하면서 변경되거나 추가된 내용을 순서대로 작성하면 됩니다.
처음 작성할 때 특히 중요한 부분은 Build 명령어입니다.
프로그램을 여러 번 수정하고 테스트하다 보면 동일한 Build 명령을 반복해서 사용하게 됩니다. 특히 Custom Board를 사용하는 경우에는 BOARD_ROOT와 같은 옵션까지 함께 입력해야 하므로 명령이 길어지고, 매번 직접 입력하면 실수하기도 쉽습니다.
따라서 프로젝트에서 사용하는 Build 명령을 CHANGELOG.md에 미리 기록해 두고, 필요할 때 복사하여 사용하는 것이 편리합니다.
이번 프로젝트에서 사용하는 Build 명령은 다음과 같습니다.
west build -b skpang_esp32_can/esp32/procpu -p always -- -DBOARD_ROOT="D:/Zephyr/workspace/my_boards"
이렇게 Build 및 Flash 명령과 주요 변경 사항을 프로젝트와 함께 기록해 두면, 시간이 지난 후 프로젝트를 다시 열었을 때도 개발 환경과 작업 내용을 빠르게 확인할 수 있습니다.
프로그램 구현
이번 프로그램은 앞에서 살펴본 Wi-Fi AP 연결 과정을 그대로 코드로 구현합니다.
전체적인 동작 흐름은 다음과 같습니다.
Network Interface 확인 → Event Callback 등록 → Wi-Fi 연결 정보 설정 → AP 연결 요청 → Wi-Fi 연결 Event 처리 → IPv4 Address Event 처리
프로그램에서는 Wi-Fi 연결 결과와 IPv4 Address 할당을 각각 Event Callback으로 처리합니다.
아래는 main.c의 전체 프로그램 입니다.




Wi-Fi 연결 정보 정의
먼저 연결할 AP의 SSID와 Password를 정의합니다.
#define WIFI_SSID "SSID"
#define WIFI_PASSWORD "Password"
실제 사용 시에는 "SSID"와 "Password" 부분을 연결하려는 Wi-Fi AP의 정보로 변경합니다.
이번 실습에서는 WPA2 방식의 AP 연결을 사용하므로 이후 wifi_connect_req_params 구조체에서 Security Type을 설정합니다.
Event Callback 준비
Wi-Fi 연결 결과와 IPv4 Address 할당 Event를 처리하기 위해 두 개의 Callback 구조체를 선언합니다.
static struct net_mgmt_event_callback wifi_connect_cb;
static struct net_mgmt_event_callback ipv4_cb;
wifi_connect_cb는 Wi-Fi AP 연결 결과를 처리하고, ipv4_cb는 DHCP를 통해 IPv4 Address가 할당되었을 때 사용합니다.
Callback으로 호출될 함수도 미리 선언합니다.
static void wifi_connect_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event,
struct net_if *iface);
static void ipv4_addr_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event,
struct net_if *iface);
Network Interface 확인
main()에서는 먼저 기본 Network Interface를 얻습니다.
iface = net_if_get_default();
net_if_get_default()는 현재 시스템에서 기본으로 사용하는 Network Interface의 Pointer를 반환합니다.
이번 ESP32 Wi-Fi 프로젝트에서는 이 Interface를 통해 Wi-Fi 연결 요청과 이후의 IP Network 처리가 이루어집니다.
만약 사용할 수 있는 기본 Network Interface가 없다면 프로그램을 종료합니다.
if (iface == NULL) {
printk("No default network interface found.\n");
return 0;
}
Wi-Fi 연결 Event Callback 등록
Wi-Fi 연결 결과를 받기 위해 NET_EVENT_WIFI_CONNECT_RESULT Event에 대한 Callback을 등록합니다.
net_mgmt_init_event_callback(&wifi_connect_cb,
wifi_connect_handler,
NET_EVENT_WIFI_CONNECT_RESULT);
net_mgmt_add_event_callback(&wifi_connect_cb);
net_mgmt_init_event_callback()에서 어떤 Event를 처리할 것인지와 호출될 Handler를 지정하고, net_mgmt_add_event_callback()을 이용하여 실제 Network Management Event Callback 목록에 등록합니다.
AP 연결 결과가 발생하면 Zephyr는 wifi_connect_handler()를 호출합니다.
IPv4 Address Event Callback 등록
다음으로 DHCP를 통해 IPv4 Address가 할당되었는지 확인하기 위한 Callback을 등록합니다.
net_mgmt_init_event_callback(&ipv4_cb,
ipv4_addr_handler,
NET_EVENT_IPV4_ADDR_ADD);
net_mgmt_add_event_callback(&ipv4_cb);
IPv4 Address가 Network Interface에 추가되면 NET_EVENT_IPV4_ADDR_ADD Event가 발생하고 ipv4_addr_handler()가 호출됩니다.
이 부분이 앞에서 살펴본 IP Network Connection 단계에 해당합니다.
Wi-Fi 연결 Parameter 설정
Wi-Fi 연결에 필요한 정보는 wifi_connect_req_params 구조체에 설정합니다.
struct wifi_connect_req_params params = {0};
SSID와 Password를 다음과 같이 지정합니다.
params.ssid = (const uint8_t *)WIFI_SSID;
params.ssid_length = strlen(WIFI_SSID);
params.psk = (const uint8_t *)WIFI_PASSWORD;
params.psk_length = strlen(WIFI_PASSWORD);
Security 방식과 Channel도 설정합니다.
params.security = WIFI_SECURITY_TYPE_PSK;
params.channel = WIFI_CHANNEL_ANY;
WIFI_CHANNEL_ANY를 사용하면 특정 Channel을 직접 지정하지 않고 Wi-Fi Driver가 해당 AP의 Channel을 찾아 연결할 수 있습니다.
Wi-Fi AP 연결 요청
모든 연결 Parameter가 준비되면 net_mgmt()를 이용하여 AP 연결을 요청합니다.
ret = net_mgmt(NET_REQUEST_WIFI_CONNECT,
iface,
¶ms,
sizeof(params));
여기서 NET_REQUEST_WIFI_CONNECT가 앞에서 그림으로 살펴본 Connect Request에 해당합니다.
net_mgmt()의 반환값은 연결 자체의 최종 성공 여부가 아니라 연결 요청이 정상적으로 접수되었는지를 나타냅니다.
if (ret != 0) {
printk("Wi-Fi connect request failed: %d\n", ret);
}
실제 Wi-Fi 연결 결과는 이후 발생하는 NET_EVENT_WIFI_CONNECT_RESULT Event를 통해 확인합니다.
Wi-Fi 연결 결과 확인
Wi-Fi 연결 과정이 완료되면 다음 Handler가 호출됩니다.
static void wifi_connect_handler(struct net_mgmt_event_callback *cb,
uint64_t mgmt_event,
struct net_if *iface)
Callback의 info에는 Wi-Fi 연결 결과가 전달됩니다.
const struct wifi_status *status =
(const struct wifi_status *)cb->info;
status->status가 0이면 AP 연결이 성공한 것입니다.
if (status->status == 0) {
printk("Wi-Fi connected successfully.\n");
} else {
printk("Wi-Fi connection failed: %d\n",
status->status);
}
이 단계까지 완료되면 ESP32와 Wi-Fi AP 사이의 무선 연결이 이루어진 상태입니다.
IPv4 Address 확인
Wi-Fi 연결 이후 DHCP를 통해 IPv4 Address가 할당되면 ipv4_addr_handler()가 호출됩니다.
먼저 Network Interface에서 현재 사용 가능한 IPv4 Address를 가져옵니다.
addr = net_if_ipv4_get_global_addr(iface, NET_ADDR_PREFERRED);
Address가 정상적으로 존재하면 net_addr_ntop()을 이용하여 사람이 읽을 수 있는 문자열 형태로 변환합니다.
net_addr_ntop(AF_INET,
addr,
addr_str,
sizeof(addr_str));
마지막으로 할당된 IPv4 Address를 Console에 출력합니다.
printk("IPv4 address: %s\n", addr_str);
이 메시지가 출력되면 ESP32가 DHCP를 통해 IP Address를 정상적으로 할당받았다는 것을 확인할 수 있습니다.
즉, 프로그램의 실제 동작은 다음과 같이 정리할 수 있습니다.
NET_REQUEST_WIFI_CONNECT → NET_EVENT_WIFI_CONNECT_RESULT → DHCP → NET_EVENT_IPV4_ADDR_ADD → IPv4 Address 확인
이 과정까지 완료되면 ESP32는 IP Network에 참여할 준비가 완료되며, 이후 UDP나 TCP를 이용한 실제 데이터 통신으로 확장할 수 있습니다.
빌드 및 실행 결과
이제 작성한 프로젝트를 Build하고 ESP32에서 실행해 보겠습니다.
Terminal에서 프로젝트 디렉터리로 이동한 후, 앞서 CHANGELOG.md에 기록해 두었던 Build 명령어를 복사하여 실행합니다.
Build가 정상적으로 완료되면 아래와 같이 Memory region별 사용량과 함께 마지막에 Successfully created ESP32 image. 메시지가 출력됩니다.

위 결과를 통해 skpang_esp32_can_wificonnect.elf가 정상적으로 생성되었으며, ESP32에 Flash할 수 있는 Image가 만들어졌음을 확인할 수 있습니다.
이제 생성된 Firmware를 ESP32에 Flash합니다.
명령어는 **west flash**입니다.
west flash
명령을 실행하면 Zephyr의 ESP32 Runner가 esptool을 이용하여 ESP32를 인식하고 Firmware를 Flash합니다.

위 화면에서는 ESP32가 COM13을 통해 정상적으로 인식되었으며, Firmware가 Flash Memory에 기록된 것을 확인할 수 있습니다.
특히 다음 메시지를 통해 Flash가 정상적으로 완료되었음을 확인할 수 있습니다.
Hash of data verified.
Hard resetting via RTS pin...
Flash가 완료되면 ESP32가 Reset되고 새로 기록된 Firmware가 실행됩니다.
이제 Serial Terminal을 열어 Wi-Fi AP 연결 과정과 IP Address 할당 결과를 확인해 보겠습니다.
아래는 Serial Terminal 프로그램인 Docklight의 화면입니다.

실행 결과에서 다음 두 메시지를 확인할 수 있습니다.
Wi-Fi connected successfully.
이 메시지는 ESP32가 지정한 Wi-Fi AP에 정상적으로 연결되었음을 의미합니다.
또한 다음과 같이 IPv4 Address도 출력됩니다.
IPv4 address: 192.168.9.8
이는 AP 연결 이후 DHCP를 통해 ESP32에 IPv4 Address가 정상적으로 할당되었음을 의미합니다.
따라서 앞에서 살펴본 두 단계인 Wi-Fi Connection과 IP Network Connection이 모두 정상적으로 완료되었음을 확인할 수 있습니다.
즉, ESP32는 이제 Wi-Fi AP에 연결되어 IP Address를 가진 하나의 Network Device가 되었으며, UDP나 TCP와 같은 IP 기반 통신을 수행할 준비가 완료되었습니다.
결론
이번 실습에서는 Zephyr를 이용하여 ESP32를 Wi-Fi AP에 연결하고, DHCP를 통해 IPv4 Address를 할당받는 과정까지 확인하였습니다.
이전 Wi-Fi Scan 실습이 주변 AP의 정보를 검색하는 단계였다면, 이번 실습에서는 한 단계 더 나아가 ESP32가 실제 Wi-Fi Network에 참여할 수 있도록 하였습니다.
특히 Wi-Fi AP에 연결되는 과정과 IP Address를 할당받는 과정이 서로 구분되어 있으며, Zephyr에서는 각각의 결과를 Network Management Event를 통해 처리할 수 있다는 것을 확인하였습니다.
이제 ESP32는 IP Network를 이용할 수 있는 기본적인 준비가 완료되었습니다. 하지만 아직 ESP32와 다른 장치 사이에서 실제 데이터를 주고받은 것은 아닙니다.
다음 실습에서는 UDP 또는 TCP를 이용하여 ESP32와 PC 사이에서 실제 데이터를 송수신해 보겠습니다. 이를 통해 Wi-Fi 연결에서 한 단계 더 나아가 실제 Network Communication이 어떻게 이루어지는지 살펴보겠습니다.