# 사설 카카오톡 봇 설치·운영 가이드 ### Iris + redroid + IrisPy(Python) on Mac mini (Apple Silicon) 작성 기준일: 2026-07-23 대상 환경: M4 Mac mini 기본형(16GB 통합메모리, macOS) / 시놀로지 NAS는 이번 구성에서 미사용 문서 목적: **다른 AI(코딩 에이전트)가 이 문서만 보고 실제 구현을 이어갈 수 있도록** 배경, 결정 근거, 정확한 명령어, 전체 코드, 미검증 항목을 빠짐없이 남긴다. --- ## 0. 이 문서를 인수받는 AI에게 - 이 프로젝트의 최종 사용자(이하 "사용자")는 비개발자가 아니라 Python3/PySide6/SQLite/MariaDB로 자동화 파이프라인을 직접 운영해온 개발자다. 다만 이번 카카오톡 봇 관련 인프라(UTM, redroid, Iris)는 처음 다루므로, **명령어를 실행 가능한 형태 그대로** 제시할 것. - 사용자는 "항상 진실만 말하고, 추측이나 짐작을 금지하며, 불확실하면 명시적으로 밝힐 것"을 강하게 요구한다. 이 문서에서 `[확인 필요]`로 표시된 항목은 **검색으로 확인하지 못했거나 공식 문서에 명시되지 않은 부분**이다. 절대로 그럴듯하게 지어내서 채우지 말고, 실제로 실행/검증한 뒤 그 결과로 문서를 갱신할 것. - 이 문서 하나로 처음부터 끝까지 재현 가능해야 한다. 외부 파일 참조(`iris_bot_skeleton.py`, `setup_iris_redroid.sh`) 없이도 아래 부록에 전체 코드가 그대로 들어있다. --- ## 1. 배경 및 아키텍처 결정 근거 ### 1.1 왜 메신저봇R을 버렸는가 기존에 사용자는 안드로이드용 "메신저봇R"을 썼으나 자주 다운되어 불편함을 겪었다. 메신저봇R 계열(채팅자동응답봇 포함)은 `NotificationListenerService`로 안드로이드 알림을 파싱하는 방식으로 동작한다. 이 방식은: - 채팅방이 열려 있으면 알림이 뜨지 않아 봇이 작동하지 않음 - 사진·파일 전송, 초대·강퇴 등 미지원 - 알림 파싱 자체가 구조적으로 불안정 (다운 잦음의 근본 원인일 가능성) ### 1.2 왜 Iris를 선택했는가 Iris(GitHub: `dolidolih/Iris`, 최신 릴리스 v0.30, 2026-03-10)는 알림을 읽는 대신 **카카오톡 로컬 SQLite DB를 안드로이드 기기 내부에서 직접 조회**하는 네이티브 앱이다. - 알림 파싱 방식보다 안정적이고 기능이 많음 (입퇴장 감지, 이미지 송수신 등) - Python 클라이언트(`irispy-client`)가 존재 — 사용자의 기존 Python 스택과 자연스럽게 연동 - 다만 **카카오톡 DB 접근을 위해 안드로이드 기기(또는 컨테이너)에 root 권한이 필수** ### 1.3 왜 redroid인가 (root 확보 방법) 물리 안드로이드 기기를 루팅하는 대신, 처음부터 root 상태로 뜨는 컨테이너형 안드로이드(redroid)를 사용한다. - redroid는 VM이 아니라 **호스트 리눅스 커널의 binder/ashmem 커널 모듈을 그대로 공유해서 쓰는 Docker 컨테이너**다. - 가상화 확장 기능(VT-x/AMD-V)이 필요 없고, 루팅이라는 개념 자체가 없다(컨테이너가 처음부터 root 접근 가능한 상태로 뜸). - 대안이었던 LDPlayer(Windows/Mac용 안드로이드 에뮬레이터, GUI 필요)보다 서버 상시 구동에 적합. ### 1.4 왜 시놀로지 NAS가 아닌 Mac mini + UTM인가 - **시놀로지 DSM**: 리눅스 커널 기반이지만 Ubuntu/CentOS 같은 표준 배포판이 아니며 apt/yum 패키지 매니저가 없다. redroid에 필요한 binder/ashmem 커널 모듈을 빌드/로드하려면 표준 커널 헤더가 필요한데, DSM 같은 커스텀·락다운 커널에는 이게 없는 경우가 많다. 구조적으로 유사한 사례로 Unraid에서 동일한 문제(binderfs/ashmem 드라이버 부재, 커스텀 커널 빌드 실패)가 실제로 보고되었다. **시놀로지 DSM에서 redroid를 직접 시도해 성공/실패한 사례는 검색으로 확인하지 못함 — 구조적 유추에 근거한 비권장 판단이며, 확정된 사실이 아님을 사용자에게도 이미 고지함.** - **Mac mini(macOS)**: macOS 커널(XNU)은 리눅스가 아니므로 binder/ashmem 모듈을 애초에 올릴 수 없다. 따라서 UTM으로 **완전한 표준 Ubuntu ARM64 VM**을 하나 띄우고, 그 안에서 진짜 리눅스 서버처럼 Docker + redroid를 돌린다. 이 VM은 redroid의 요구사항이 아니라 "macOS 위에 리눅스 커널 환경을 마련하기 위한 우회 수단"일 뿐이다. 향후 실제 리눅스 서버(VPS 등)를 마련하면 VM 단계 없이 그대로 Docker + redroid로 이전 가능하다. ### 1.5 Mac mini 하드웨어 확인 사실 Apple 공식 기술 사양 기준, M4 Mac mini(2024) 기본 구성은 10코어 CPU, 10코어 GPU, **16GB 통합 메모리**, 256GB~512GB 저장장치다. Ubuntu VM(4~8GB 할당) + redroid 컨테이너 + Python 스크립트 상시 구동 정도는 여유 있게 감당 가능하다고 판단한다(다만 실측 부하 테스트는 하지 않았음 — `[확인 필요]`). --- ## 2. 전체 아키텍처 ``` M4 Mac mini (macOS, 16GB 통합메모리) └─ UTM (무료, Apple Silicon 네이티브 가상화, Apple Hypervisor 프레임워크 사용) └─ Ubuntu ARM64 VM (4GB로 시작, 부족 시 증설) └─ Docker └─ redroid 컨테이너 (redroid/redroid:15.0.0-latest, arm64/amd64 멀티아치) ├─ 카카오톡 앱 (봇 전용 세컨 계정으로 로그인 — 사용자가 이미 보유) └─ Iris.apk (카카오톡 DB 감시 + HTTP 브로커, 기본 포트 3000) ↕ HTTP (webhook 수신 / REST API 발신) iris_bot_skeleton.py (Flask, 포트 5000) — 실제 봇 로직, 같은 VM에서 구동 ``` 포트 설계: - `5555` : adb (redroid 컨테이너 제어용, **외부 네트워크에 노출 금지**) - `3000` : Iris HTTP API (컨테이너 내부 → VM 호스트로 -p 옵션으로 개방) - `5000` : iris_bot_skeleton.py (Flask 웹훅 수신 서버, VM 호스트에서 직접 구동) --- ## 3. 사전 준비물 / 전제 조건 | 항목 | 상태 | |---|---| | 하드웨어 | M4 Mac mini 기본형, 16GB 통합메모리 — 보유 확인됨 | | 카카오톡 봇 계정 | 세컨(서브) 계정 — 사용자가 이미 보유, 이걸로 진행 확정 | | 시놀로지 NAS | 보유하고 있으나 **이번 구성에서는 사용하지 않음** (1.4절 근거) | | VM 소프트�어 | UTM (무료, `brew install --cask utm`) | | VM 게스트 OS | Ubuntu Server ARM64 (LTS 최신 버전 권장) | | VM 메모리 할당 | 4GB로 시작 → 운영하며 부족하면 증설 (사용자 확정 방침) | | 네트워크 | Mac mini와 Ubuntu VM이 같은 로컬 네트워크에서 서로 통신 가능해야 함 | --- ## 4. 설치 단계 (순서대로 실행) ### 4.1 UTM 설치 및 Ubuntu ARM64 VM 생성 ```bash # Mac mini(macOS) 터미널에서 brew install --cask utm ``` UTM 앱 실행 → "+" 새 VM → **Virtualise**(에뮬레이션 아님, Apple Silicon 네이티브 성능) 선택 → Ubuntu Server ARM64 ISO 지정 → 설치 마법사 진행. - 메모리: 4096MB - CPU: 기본값(자동 코어 관리) - 디스크: 최소 20GB 이상 권장(카카오톡+Iris+Docker 이미지 용량 고려) — `[확인 필요: 정확한 최소 디스크 용량은 실측 필요]` 설치 완료 후 VM 내부에서 SSH 접속을 켜두면 이후 작업이 편하다(선택): ```bash sudo apt-get install -y openssh-server ``` ### 4.2 redroid + 커널 모듈 셋업 (VM 안에서 실행) 아래 스크립트를 VM에 `setup_iris_redroid.sh`로 저장 후 실행한다. 전체 내용은 부록 A에 포함되어 있다. ```bash chmod +x setup_iris_redroid.sh ./setup_iris_redroid.sh ``` 스크립트가 하는 일: 1. `apt-get install linux-modules-extra-$(uname -r) adb docker.io curl jq` 2. `sudo modprobe binder_linux devices="binder,hwbinder,vndbinder"` (커널 5.18+ 에서는 `ashmem_linux`는 없어도 정상 — 이미 내장됨) 3. `docker run` 으로 redroid 컨테이너 실행, adb 포트(5555)와 Iris HTTP 포트(3000)를 모두 `-p`로 개방 4. `adb connect localhost:5555` 재부팅 시 `binder_linux` 커널 모듈이 초기화되므로, 운영 단계(5장)에서 systemd로 재실행을 자동화해야 한다. ### 4.3 카카오톡 앱 설치 및 세컨 계정 로그인 ```bash adb install KakaoTalk.apk # 사용자가 사전에 카카오톡 apk 파일을 준비해야 함 sudo apt-get install -y scrcpy scrcpy -s localhost:5555 ``` scrcpy 화면에서 **세컨 계정**으로 직접 로그인한다. 문자 인증 등 사람이 직접 확인해야 하는 단계가 있을 수 있다. ### 4.4 Iris 설치 1. 브라우저(또는 `curl`)로 https://github.com/dolidolih/Iris/releases 에서 최신 `Iris.apk`와 `iris_control` 다운로드. `[확인 필요]`: 릴리스 asset 파일명은 버전마다 바뀔 수 있어 자동화 스크립트에 URL을 하드코딩하지 않았다. 실행 시점에 실제 페이지에서 최신 파일명을 확인할 것. 2. VM으로 옮긴 뒤: ```bash adb push Iris.apk /data/local/tmp chmod +x iris_control ./iris_control install ./iris_control start ``` 3. 정상 기동 확인: ```bash curl http://localhost:3000/config ``` 기대 응답 예시(공식 문서 기준): ```json { "bot_name": "[YOUR_BOT_NAME]", "bot_http_port": 3000, "web_server_endpoint": "[YOUR_WEB_SERVER_URL]", "db_polling_rate": 300, "message_send_rate": 200, "bot_id": 1234567890 } ``` ### 4.5 웹훅(메시지 전달) 연결 호스트 게이트웨이 IP 확인 (Docker 기본 브리지 게이트웨이는 보통 `172.17.0.1`이지만 `[확인 필요]`, 실행 시 직접 확인할 것): ```bash sudo docker network inspect bridge | grep Gateway ``` Iris에 웹훅 주소 등록: ```bash curl -X POST -H "Content-Type: application/json" \ -d '{"endpoint": "http://<확인한 게이트웨이 IP>:5000/on_message"}' \ http://localhost:3000/config/endpoint ``` ### 4.6 봇 로직 서버 실행 `iris_bot_skeleton.py`(전체 코드는 부록 B)를 VM에 올린 뒤: ```bash pip3 install flask requests python3 iris_bot_skeleton.py ``` ### 4.7 동작 확인 절차 (수용 기준 / Acceptance Criteria) 아래를 모두 통과해야 "설치 완료"로 간주한다. 1. 봇 계정이 아닌 다른 카카오톡 계정에서, 봇 계정이 속한 채팅방에 텍스트 메시지를 보낸다. 2. `iris_bot_skeleton.py`의 로그에 해당 메시지의 실제 payload(JSON)가 찍히는지 확인한다. 3. 봇 계정이 `echo: <원본 메시지>` 형태로 자동 응답하는지 확인한다. 4. 같은 채팅방에 이미지를 보낸다 → 로그에 `attachment` 필드가 채워진 payload가 찍히는지 확인한다. 5. 봇이 임의의 이미지 파일을 `/reply`(type=image)로 정상 전송할 수 있는지 확인한다. 6. 위 1~5가 모두 확인되면, `[확인 필요]`로 남겨둔 "텍스트/이미지 구분 컬럼" 부분을 실제 로그 기반으로 확정하고 이 문서(6.1절)를 갱신한다. --- ## 5. 운영 — 재부팅 대응 자동화 ```ini # /etc/systemd/system/kakaobot-redroid.service [Unit] Description=Iris redroid KakaoTalk bot stack After=docker.service Requires=docker.service [Service] Type=oneshot RemainAfterExit=true ExecStart=/home//setup_iris_redroid.sh [Install] WantedBy=multi-user.target ``` ```bash sudo systemctl enable kakaobot-redroid.service ``` `iris_bot_skeleton.py`도 별도 systemd 서비스(또는 최소한 `nohup`/`screen`/`tmux`)로 상시 구동되게 설정한다. 예시: ```ini # /etc/systemd/system/kakaobot-app.service [Unit] Description=Iris bot Flask app After=kakaobot-redroid.service [Service] Type=simple WorkingDirectory=/home/ ExecStart=/usr/bin/python3 /home//iris_bot_skeleton.py Restart=on-failure [Install] WantedBy=multi-user.target ``` `[확인 필요]`: redroid 컨테이너가 재시작될 때 카카오톡 앱이 자동으로 재로그인되는지, 세션이 만료되어 수동 재로그인이 필요한지는 검증되지 않았다. 실제 재부팅 테스트로 확인 후 이 절을 갱신할 것. --- ## 6. 기능별 API 레퍼런스 (Iris 공식 README `dolidolih/Iris` 기준, 확정된 스펙) ### 6.1 메시지 수신 (웹훅) Iris가 새 메시지를 감지하면 `web_server_endpoint`로 아래 JSON을 POST한다. ```json { "msg": "복호화된 메시지 내용", "room": "채팅방 이름 (1:1인 경우 발신자 이름)", "sender": "발신자 이름", "json": { "_id": "...", "chat_id": "...", "user_id": "...", "message": "복호화된 메시지 (msg 필드와 동일)", "attachment": "복호화된 첨부(이미지 등) 정보", "v": "원래 v 컬럼 값 (JSON 형식)" } } ``` `/ws` 로 WebSocket 연결 시 동일한 이벤트가 WebSocket으로도 전달된다. `[확인 필요]`: 텍스트/이미지/이모티콘 등 메시지 종류를 구분하는 정확한 컬럼(`chat_logs.type` 값 매핑 등)은 공식 README에 명시되어 있지 않았다. `attachment` 필드의 존재 유무로 1차 분기하도록 스켈레톤 코드를 작성했으나, 실제 payload를 로그로 확인해 정확한 분기 조건으로 교체해야 한다(4.7절 수용 기준 6번 참고). ### 6.2 메시지·이미지 발신 — `POST /reply` ```json { "type": "text", "room": "[CHAT_ROOM_ID]", "data": "[MESSAGE_TEXT]" } ``` ```json { "type": "image", "room": "[CHAT_ROOM_ID]", "data": "[BASE64_ENCODED_IMAGE]" } ``` MP4 영상은 다음 형식으로 전송한다. ```json { "type": "video", "room": "[CHAT_ROOM_ID]", "data": "[BASE64_ENCODED_MP4]" } ``` ```json { "type": "image_multiple", "room": "[CHAT_ROOM_ID]", "data": ["[BASE64_1]", "[BASE64_2]"] } ``` ### 6.3 기타 확정된 엔드포인트 | 엔드포인트 | 메소드 | 용도 | |---|---|---| | `/query` | POST | `chat_logs` 등 테이블에 SQL 쿼리 실행, `message`/`attachment`(with `user_id`, `enc`) 조회 시 자동 복호화 | | `/decrypt` | POST | `{enc, b64_ciphertext, user_id}` → `{plain_text}` 개별 메시지 복호화 | | `/aot` | GET | access_token/refresh_token 등 인증 토큰 조회 | | `/config` | GET | 현재 설정 조회 (`bot_name`, `bot_http_port`, `web_server_endpoint`, `db_polling_rate`, `message_send_rate`, `bot_id`) | | `/config/endpoint` | POST | 웹훅 주소 변경 `{"endpoint": "..."}` | | `/config/dbrate` | POST | DB 폴링 주기(ms) 변경 `{"rate": N}` | | `/config/sendrate` | POST | 메시지 전송 간격(ms) 변경 `{"rate": N}` | | `/config/botport` | POST | Iris HTTP 포트 변경 (재시작 필요) | | `/dashboard` | GET | 브라우저 기반 설정 UI | ### 6.4 `/query` 예시 (참고용, 아직 스켈레톤에는 미사용) ```bash curl -X POST -H "Content-Type: application/json" \ -d '{"query": "SELECT _id, chat_id, user_id, message FROM chat_logs WHERE user_id = ? ORDER BY _id DESC LIMIT 5", "bind": ["1234567890"]}' \ http://localhost:3000/query ``` --- ## 7. 리스크 및 주의사항 - **약관 위반 가능성**: 이런 방식의 봇 사용은 카카오 공식 지원 범위 밖이며, 계정 정지 가능성은 실제로 존재하는 리스크다. 관련 커뮤니티 문서(나무위키 등)에서도 이 방식 사용에 따른 정지 책임은 사용자 본인에게 있다고 명시한다. - **redroid 보안 경고 (공식 문서 명시)**: adb 포트(5555)를 공용 네트워크에 노출하면 안 된다. 노출 시 redroid 컨테이너뿐 아니라 호스트 OS까지 침해당할 수 있다. VM은 내부망/NAT로만 접근되게 하고, 필요하면 SSH 터널로만 열어둘 것. - **redroid에서의 카카오톡 로그인 이상탐지 여부**: `[확인 필요]` — 컨테이너/가상 환경에서의 로그인이 카카오 측 이상탐지에 걸릴지는 신뢰할 수 있는 최신 자료를 찾지 못해 확인할 수 없다. 실사용 중 로그인이 풀리거나 계정이 제한될 가능성을 배제할 수 없다. - **irispy-client 정확한 API 문법**: `[확인 필요]` — 이 문서와 부록 코드는 검증된 raw HTTP API(6장)만 사용했다. 고수준 Python 라이브러리 `irispy-client`의 데코레이터 문법(예: 이벤트 핸들러 등록 방식)은 실제 소스코드를 확인하지 못해 이 문서에 포함하지 않았다. 필요 시 `pip install irispy-client` 후 실제 소스를 열어 검증하고 리팩터링할 것. --- ## 부록 A. `setup_iris_redroid.sh` 전체 코드 ```bash #!/usr/bin/env bash # ============================================================ # redroid + Iris 자동 셋업 스크립트 # Ubuntu VM(UTM, Apple Silicon Mac mini 위) 안에서 실행하세요. # ============================================================ set -e # ---- 0. 설정값 (필요하면 여기만 수정) ---- REDROID_TAG="redroid/redroid:15.0.0-latest" # 최신 안정 태그, arm64/amd64 모두 지원 DATA_DIR="$HOME/redroid-data" FLASK_PORT=5000 # iris_bot_skeleton.py 포트 IRIS_HTTP_PORT=3000 # Iris 기본 HTTP 포트 echo "=== 1. 커널 모듈 로드 ===" sudo apt-get update -y sudo apt-get install -y linux-modules-extra-"$(uname -r)" adb docker.io curl jq sudo modprobe binder_linux devices="binder,hwbinder,vndbinder" || true sudo modprobe ashmem_linux || true # 커널 5.18+ 에서는 없어도 정상 echo "=== 2. redroid 컨테이너 실행 (adb 5555, Iris HTTP 3000 포트 개방) ===" mkdir -p "$DATA_DIR" sudo docker rm -f redroid 2>/dev/null || true sudo docker run -itd --rm --privileged \ --pull always \ -v "$DATA_DIR":/data \ -p 5555:5555 \ -p "$IRIS_HTTP_PORT":"$IRIS_HTTP_PORT" \ --name redroid \ "$REDROID_TAG" echo "=== 3. adb 연결 대기 ===" sleep 8 adb connect localhost:5555 echo "=== 4. Iris 다운로드 안내 ===" cat <<'EOF' ------------------------------------------------------------ 다음은 자동화하지 않았습니다 (릴리스 파일명이 버전마다 바뀔 수 있어 잘못된 파일을 내려받는 사고를 막기 위함입니다): 1) 브라우저에서 아래 페이지를 열어 최신 Iris.apk, iris_control, iris_control.ps1(윈도우 전용, 여기선 불필요) 을 받으세요. https://github.com/dolidolih/Iris/releases 2) 받은 파일을 이 VM의 홈 디렉토리로 옮긴 뒤 아래를 실행하세요. adb push Iris.apk /data/local/tmp chmod +x iris_control ./iris_control install ./iris_control start 3) 정상 기동 확인: curl http://localhost:3000/config 4) 웹훅 주소를 이 VM에서 실행할 Flask 서버로 연결 (iris_bot_skeleton.py 를 이 VM에 올려두고 실행한 뒤): curl -X POST -H "Content-Type: application/json" \ -d '{"endpoint": "http://localhost:5000/on_message"}' \ http://localhost:3000/config/endpoint * redroid 컨테이너와 Flask가 같은 VM(호스트)에서 돈다면 "localhost" 대신 실제로는 컨테이너 -> 호스트로 나가는 경로가 필요합니다. 아래로 호스트 게이트웨이 IP를 확인하세요: sudo docker network inspect bridge | grep Gateway 보통 172.17.0.1 입니다. 위 endpoint 값을 "http://172.17.0.1:5000/on_message" 로 바꿔서 다시 curl 하세요. ------------------------------------------------------------ EOF echo "=== 스크립트 종료. 위 4단계 안내를 따라 수동 진행하세요. ===" ``` --- ## 부록 B. `iris_bot_skeleton.py` 전체 코드 ```python """ Iris 카카오톡 봇 - 최소 동작 스켈레톤 전제: - Iris.apk가 redroid(Ubuntu VM 위 Docker) 안에서 실행 중 - Iris 대시보드(http://[IRIS_IP]:3000/dashboard)에서 web_server_endpoint 를 이 스크립트가 떠 있는 주소로 설정해둔 상태 예) http://192.168.64.1:5000/on_message 이 스크립트는 Iris 공식 README(dolidolih/Iris)에 명시된 HTTP API 스키마만 사용합니다. 검증되지 않은 고수준 라이브러리 (irispy-client의 데코레이터 문법 등)는 쓰지 않았습니다 — 그 부분은 실제 라이브러리 소스를 확인한 뒤 리팩터링하는 것을 권장합니다. """ import os import requests from flask import Flask, request, jsonify app = Flask(__name__) # Iris가 떠 있는 주소 (redroid 컨테이너의 IP:PORT) IRIS_HOST = os.environ.get("IRIS_HOST", "http://192.168.64.2:3000") def send_text(room_id: str, text: str) -> None: """Iris 공식 /reply 엔드포인트 스키마 그대로 사용 (text)""" payload = {"type": "text", "room": room_id, "data": text} requests.post(f"{IRIS_HOST}/reply", json=payload, timeout=10) def send_image_base64(room_id: str, b64_image: str) -> None: """Iris 공식 /reply 엔드포인트 스키마 그대로 사용 (image)""" payload = {"type": "image", "room": room_id, "data": b64_image} requests.post(f"{IRIS_HOST}/reply", json=payload, timeout=10) @app.route("/on_message", methods=["POST"]) def on_message(): """ Iris가 새 메시지를 감지하면 web_server_endpoint로 POST하는 바디는 공식 README 기준 아래 형태로 확정되어 있습니다: { "msg": "복호화된 메시지 내용", "room": "채팅방 이름(또는 1:1인 경우 발신자 이름)", "sender": "발신자 이름", "json": { # chat_logs 원본 row (일부 필드 복호화됨) "_id": "...", "chat_id": "...", "user_id": "...", "message": "복호화된 메시지", "attachment": "복호화된 첨부(이미지 등) 정보", "v": "...", # 그 외 chat_logs 컬럼들 (예: type) } } 주의: 텍스트/이미지/이모티콘 등 메시지 종류를 구분하는 정확한 컬럼(예: chat_logs.type 의 값 매핑)은 공식 문서에 명시되어 있지 않아, 이 부분은 실제 chat_logs.json 응답을 로그로 찍어 직접 확인한 뒤 분기 조건을 채워 넣어야 합니다. 아래는 그 뼈대만 잡아둔 것입니다. """ data = request.get_json(force=True, silent=True) or {} room_id = data.get("json", {}).get("chat_id") text = data.get("msg", "") attachment = data.get("json", {}).get("attachment") if not room_id: return jsonify({"ok": False, "error": "chat_id missing"}), 400 # 우선 로그로 실제 payload 구조를 확인하세요. app.logger.info("RECEIVED: room=%s sender=%s msg=%s attachment=%s", room_id, data.get("sender"), text, attachment) if attachment: # 이미지/첨부가 있는 메시지로 추정되는 경우 send_text(room_id, "이미지를 받았습니다. (처리 로직은 여기에 구현)") elif text: # 가장 단순한 형태: 받은 텍스트를 그대로 에코 send_text(room_id, f"echo: {text}") return jsonify({"ok": True}) if __name__ == "__main__": # 운영 시에는 gunicorn/uvicorn 등으로 교체 권장 app.run(host="0.0.0.0", port=5000) ``` --- ## 8. 참고 자료 (출처) - Iris 공식 저장소 (HTTP API 전체 스펙, 최신 릴리스 v0.30): https://github.com/dolidolih/Iris - iris_bot 샘플 봇 저장소 (irispy-client 초기 설정): https://github.com/dolidolih/iris_bot - PyKakaoDBBot (redroid + Python 카카오 DB 봇): https://github.com/dolidolih/PyKakaoDBBot - redroid 공식 문서: https://github.com/remote-android/redroid-doc - redroid Docker 이미지 및 Quick Start: https://hub.docker.com/r/redroid/redroid - redroid 커널 모듈: https://github.com/remote-android/redroid-modules - Unraid에서 redroid 실패 사례(구조적 유추 근거): https://forums.unraid.net/topic/149492-how-do-i-install-binderfs-ashmem-kernel-driver-module/ - 카카오톡 봇 제작법 개요 (나무위키): https://namu.wiki/w/%EC%B9%B4%EC%B9%B4%EC%98%A4%ED%86%A1%20%EB%B4%87/%EC%A0%9C%EC%9E%91%EB%B2%95 - Apple Mac mini(2024) 공식 기술 사양: https://support.apple.com/ko-kr/121555 - UTM 공식 정보: https://en.wikipedia.org/wiki/UTM_(software) - Ubuntu ARM64 on Apple Silicon (UTM 가이드): https://xanzhu.com/blog/install-ubuntu-utm-apple-silicon