본문 바로가기
스마트폰 (Mobile)

아파트 인터콤을 Apple Home에 연결하는 방법: DIY 스마트 출입 제어

by 날으는물고기 2026. 3. 25.

아파트 인터콤을 Apple Home에 연결하는 방법: DIY 스마트 출입 제어

728x90

레거시 출입 시스템을 스마트홈으로 확장하는 현실적인 접근

왜 인터콤을 스마트홈에 연결하려고 할까?

아파트나 빌라의 인터콤 시스템은 대부분 오래된 구조를 유지하고 있습니다.
기본적으로는 다음과 같은 방식입니다.

  • 방문자가 인터콤에서 호출
  • 거주자가 전화 또는 인터폰으로 응답
  • 특정 키 입력(DTMF 등)으로 문 개방

하지만 이런 구조는 다음과 같은 한계를 가지고 있습니다.

  • 통신 장애 발생 시 완전히 사용 불가
  • 스마트폰 기반 제어 불가능
  • 스마트홈 시스템과 연동 불가

이러한 문제를 해결하기 위해 등장한 접근이 바로 기존 인터콤을 유지하면서 스마트홈으로 확장하는 DIY 방식입니다.

핵심 아이디어: “전체를 바꾸지 말고, 중간을 건드린다”

이 프로젝트의 가장 중요한 개념은 다음 한 줄로 정리됩니다.

👉 인터콤을 해킹하지 말고, “문을 여는 신호”만 가로채라

300x250

일반적인 인터콤 구조를 보면

[인터콤 본체] → [제어 박스] → [솔레노이드(문잠금)]

문을 여는 동작은 결국

👉 솔레노이드에 전기가 흐르면 열림

즉, 복잡한 통신을 분석할 필요 없이
👉 전기 신호만 제어하면 된다는 구조입니다.

전체 아키텍처 구조

구성 요소

  • ESP32 (Wi-Fi 기반 마이크로컨트롤러)
  • 릴레이 모듈
  • 기존 인터콤 배선
  • Apple Home (Matter 기반)

구조 흐름

[iPhone - Apple Home]
        ↓
   (Matter / Wi-Fi)
        ↓
     [ESP32]
        ↓
     [Relay]
        ↓
[Door Solenoid Line]
        ↓
      [Gate Open]

구현 방식 상세

솔레노이드 라인 찾기

가장 중요한 단계입니다. 인터콤 내부에서 “문 열림 신호선”을 찾아야 합니다.

일반적으로 특징
  • 12V 또는 24V DC
  • 인터콤 버튼 누르면 전압 인가
  • 일정 시간 후 자동 차단

릴레이 병렬 연결

기존 시스템을 유지하기 위해 직렬이 아니라 병렬 연결을 해야 합니다.

[기존 인터콤] ----+
                  +---- [솔레노이드]
[ESP32 Relay] ----+

이 방식의 장점

  • 기존 인터콤 그대로 사용 가능
  • ESP32 장애 시 영향 없음

ESP32 제어 로직

기본 동작은 매우 단순합니다.

if (unlock_command_received) {
    relay_on();
    wait(10 seconds);
    relay_off();
}

핵심 포인트

  • 반드시 타이머 기반 자동 종료
  • 무기한 열림 방지

Matter 기반 Apple Home 연동

ESP32에 Matter 펌웨어를 적용하면 Apple Home에서 바로 제어 가능합니다.

기능
  • iPhone에서 게이트 열기
  • Siri 연동 가능
  • 자동화 (예: 위치 기반 열림)

실제 구현 시 주요 문제와 해결 방법

문제 1: 전원 공급

인터콤 내부 전원은 예상과 다를 수 있습니다.

  • 12V 단자가 출력이 아니라 입력인 경우 존재
해결
AC 18V → DC 12V 변환 (정류 + 레귤레이터)

문제 2: ESP32 메모리 부족

특히 Matter + Wi-Fi + Bluetooth 동시 사용 시 발생

해결 전략
  • Bluetooth는 초기 페어링 후 비활성화
  • Wi-Fi만 유지

문제 3: 안정성

  • 네트워크 끊김
  • ESP32 재부팅
대응
  • 상태 복구 로직 필요
  • 기본 상태 = “잠김”

반드시 고려해야 할 사항

이 프로젝트는 편의성보다 출입통제 시스템을 다루는 보안 작업입니다.

핵심 보안 원칙

  1. Fail-safe 설계
  • 장치 장애 시 기존 인터콤 정상 동작
  1. 자동 잠금 강제
MAX_OPEN_TIME = 10 seconds
  1. 네트워크 의존 최소화
  • 오프라인에서도 기본 기능 유지
  1. 물리적 접근 보호
  • ESP32 및 배선 은폐
  • 외부 노출 금지
  1. 인증 강화
  • Apple Home 계정 보호
  • 2FA 필수

운영 점검 체크리스트

실제 운영 환경에서는 다음을 반드시 점검해야 합니다.

✔️ 기능 테스트

  • 앱 → 문 열림 정상 동작
  • 자동 닫힘 확인

✔️ 장애 테스트

  • ESP32 전원 차단 시 정상 동작 여부
  • 네트워크 끊김 시 영향

✔️ 보안 테스트

  • 무단 접근 가능 여부
  • 릴레이 강제 트리거 가능성

활용 확장 아이디어

이 구조는 단순 인터콤을 넘어 다양한 곳에 활용 가능합니다.

확장 사례

  • 사무실 출입통제 시스템
  • 서버실 접근 제어
  • 창고 자동 개폐
  • 주차장 게이트

권장 부품

최소 구성은 아래 정도면 됩니다.

  • ESP32 개발보드 1개
  • 1채널 옵토절연 릴레이 모듈 1개
  • 5V 안정화 전원 또는 인터콤 내부의 저전압 보조전원
  • 점퍼선, 납땜 자재, 수축튜브
  • 필요 시 DC-DC 벅 컨버터
  • 작은 절연 케이스

ESP32 Arduino Matter 예제는 릴레이나 전구 같은 on/off 장치를 대상으로 만들어져 있고, 상태 저장과 버튼 기반 decommissioning까지 포함합니다. 또 ESP32ESP32-S2는 BLE 커미셔닝을 지원하지 않으므로, 이 경우 Wi-Fi 자격증명을 스케치에 직접 넣는 방식이 필요합니다.

배선도

가장 많이 쓰는 형태는 기존 문열림 버튼과 릴레이 접점을 병렬로 붙이는 방식입니다.
즉, ESP32가 직접 전기를 “공급”하는 게 아니라, 기존 버튼을 대신 눌러주는 dry contact 역할만 합니다.

[ESP32]                         [릴레이 모듈]                     [인터콤]
3.3V/5V 전원  -----------------> VCC
GND          -----------------> GND
GPIO 23      -----------------> IN

릴레이 COM   -----------------> 기존 문열림 버튼 한쪽 단자
릴레이 NO    -----------------> 기존 문열림 버튼 다른쪽 단자

이 구조의 장점은 다음과 같습니다.

  • 기존 인터콤 로직을 거의 건드리지 않음
  • ESP32가 죽어도 원래 버튼은 유지 가능
  • 문열림 동작만 “추가”할 수 있음

주의할 점은, 실제로 어떤 단자에 붙여야 하는지는 인터콤 모델마다 다르다는 것입니다.
문열림 버튼 입력선인지, 릴레이 트리거 입력인지, 솔레노이드 직결선인지 먼저 확인해야 합니다. 가능하면 버튼 접점과 병렬로 넣는 쪽이 가장 안전합니다.

회로 구성 포인트

릴레이 모듈은 가능하면 아래 조건을 만족하는 제품이 좋습니다.

  • 3.3V 로직 입력 호환
  • 옵토절연
  • COM / NO / NC dry contact 지원
  • 문열림은 보통 NO 접점만 사용

권장 연결은 다음처럼 생각하면 됩니다.

ESP32 GPIO23 ----> 릴레이 IN
ESP32 GND   -----> 릴레이 GND
5V 전원    -----> 릴레이 VCC

릴레이 COM  -----> 인터콤 버튼 A
릴레이 NO   -----> 인터콤 버튼 B

릴레이가 active-low 타입이면 코드에서 HIGH/LOW 반전이 필요합니다.
아래 예제는 이 부분을 설정값으로 바꿀 수 있게 해두었습니다.

실제 ESP32 코드

아래 코드는 Arduino ESP32 MatterMatterOnOffPlugin을 이용한 예제입니다.
Espressif 문서에 나온 on/off plugin은 릴레이, 전원 스위치, 스마트 플러그 같은 장치에 적합하고, begin(), setOnOff(), onChange() 같은 API를 제공합니다.

#include <Arduino.h>
#include <Matter.h>
#include <WiFi.h>
#include <Preferences.h>

// ========================
// 사용 환경에 맞게 수정
// ========================
const char* WIFI_SSID = "YOUR_WIFI_SSID";
const char* WIFI_PASS = "YOUR_WIFI_PASSWORD";

// 릴레이 제어 GPIO
constexpr uint8_t RELAY_PIN = 23;

// 대부분의 릴레이 모듈은 active-low인 경우가 많습니다.
// ON일 때 LOW를 넣는다면 true, HIGH를 넣는다면 false로 바꾸세요.
constexpr bool RELAY_ACTIVE_LOW = true;

// 문열림 펄스 시간
constexpr uint32_t OPEN_PULSE_MS = 800;

// Matter 설정 저장
Preferences prefs;
const char* PREF_NS = "doorrelay";
const char* PREF_KEY_STATE = "state";

// Matter on/off plugin endpoint
MatterOnOffPlugin DoorRelay;

// 상태 제어
volatile bool pulseRunning = false;
unsigned long pulseDeadline = 0;

// 릴레이 실제 출력
void setRelay(bool on) {
  if (RELAY_ACTIVE_LOW) {
    digitalWrite(RELAY_PIN, on ? LOW : HIGH);
  } else {
    digitalWrite(RELAY_PIN, on ? HIGH : LOW);
  }
}

// Matter 상태 변경 콜백
bool onMatterStateChange(bool newState) {
  Serial.printf("[Matter] state = %s\n", newState ? "ON" : "OFF");

  if (newState) {
    // 문열림 버튼을 짧게 눌렀다가 자동 복귀
    setRelay(true);
    pulseDeadline = millis() + OPEN_PULSE_MS;
    pulseRunning = true;
  } else {
    setRelay(false);
    pulseRunning = false;
  }

  // 마지막 상태 저장
  prefs.putBool(PREF_KEY_STATE, newState);
  return true;
}

void setup() {
  Serial.begin(115200);
  delay(500);

  pinMode(RELAY_PIN, OUTPUT);
  setRelay(false);

  prefs.begin(PREF_NS, false);
  bool lastState = prefs.getBool(PREF_KEY_STATE, false);

  // Wi-Fi 연결
  WiFi.mode(WIFI_STA);
  WiFi.begin(WIFI_SSID, WIFI_PASS);

  Serial.printf("Connecting to Wi-Fi: %s\n", WIFI_SSID);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("Wi-Fi connected, IP = ");
  Serial.println(WiFi.localIP());

  // Matter endpoint 시작
  DoorRelay.begin(lastState);
  DoorRelay.onChange(onMatterStateChange);

  // Matter stack 시작
  Matter.begin();

  if (Matter.isDeviceCommissioned()) {
    Serial.println("Matter commissioned already.");
    Serial.printf("Initial state: %s\n", DoorRelay.getOnOff() ? "ON" : "OFF");
    DoorRelay.updateAccessory();
  } else {
    Serial.println("Matter not commissioned yet.");
    Serial.println("Open the Home app and add accessory using the pairing code / QR.");
    Serial.printf("Manual pairing code: %s\n", Matter.getManualPairingCode().c_str());
    Serial.printf("QR code URL: %s\n", Matter.getOnboardingQRCodeUrl().c_str());
  }
}

void loop() {
  // 커미셔닝이 끝날 때까지 안내 출력
  if (!Matter.isDeviceCommissioned()) {
    delay(1000);
    return;
  }

  // 펄스 종료 처리
  if (pulseRunning && (long)(millis() - pulseDeadline) >= 0) {
    pulseRunning = false;
    setRelay(false);

    // Home 앱 상태도 OFF로 되돌림
    DoorRelay.setOnOff(false);
  }

  delay(10);
}

이 코드는 Home 앱에서 스위치를 ON 하면 릴레이를 잠깐 붙였다가 자동으로 OFF로 되돌립니다.
즉, 실제 인터콤 문열림 버튼을 “짧게 한 번 누르는 것”과 같은 동작을 만듭니다.

이 방식이 좋은 이유는 다음과 같습니다.

  • 문이 계속 열린 상태로 남지 않음
  • Home 앱에서는 단순한 on/off 액세서리로 보임
  • 릴레이 제어와 Matter 상태를 쉽게 맞출 수 있음

Espressif 문서의 MatterOnOffPlugin도 on/off 상태, 콜백, 상태 저장, updateAccessory 같은 흐름을 전제로 합니다.

업로드 전 설정

Arduino IDE에서 다음처럼 설정하는 것이 중요합니다.

  • 보드 선택
  • Partition Scheme: Huge APP (3MB No OTA / 1MB SPIFFS)
  • Erase All Flash Before Sketch Upload 활성화

Espressif의 Matter 예제도 동일하게 Huge APP 파티션과 전체 플래시 삭제를 요구하며, 이전 네트워크 자격증명이나 Matter fabric 정보가 남아 있으면 커미셔닝 실패나 연결 문제를 만들 수 있다고 설명합니다.

Apple Home에 추가하는 방법

플래시 후 시리얼 모니터를 열면 Matter가 아직 커미셔닝되지 않았다는 메시지와 함께 수동 페어링 코드QR 코드 URL이 출력됩니다. 그 값을 이용해 Apple Home 앱에서 액세서리를 추가하면 됩니다. Espressif의 예제도 이 방식을 그대로 사용합니다. Apple 문서 기준으로 Matter 액세서리는 Home 앱 또는 HomeKit 기반 앱으로 추가할 수 있고, 추가 후에는 Home 앱, Siri, 제어 센터 등에서 투명하게 사용할 수 있습니다.

실전에서 꼭 확인할 점

  1. 문열림 버튼과 병렬 연결인지 확인
    솔레노이드 직결선에 무작정 넣지 말고, 가능한 한 기존 버튼 입력과 병렬로 붙이세요.
  2. 릴레이 접점 규격 확인
    AC인지 DC인지, 몇 볼트인지, 몇 암페어인지 반드시 확인하세요.
  3. 기본 상태는 OFF
    전원 재인가 후 자동으로 열린 상태가 되지 않게 해야 합니다.
  4. 물리 버튼 유지
    ESP32가 고장나도 기존 인터콤 버튼은 그대로 동작해야 합니다.
  5. 케이스 절연
    금속 박스 안에 넣을 경우 쇼트와 감전 방지를 위해 절연 고정을 하세요.

더 안정적으로 만들고 싶다면

실사용 수준으로 올릴 때는 아래를 추가하면 좋습니다.

  • 전원 입력에 퓨즈 추가
  • 릴레이 출력에 서지 보호
  • ESP32 리셋용 버튼
  • 문열림 시간 조정용 웹 설정 페이지
  • Home 앱과 별개로 로컬 물리 버튼 1개 추가
728x90
그리드형(광고전용)

댓글