생각을 정리하는 마인드맵, 풀맵 →
릴스 해설

램 400KB 칩이 53만 개 도메인을 막는 방법


한 줄 요약: 스마트 플러그에도 들어가는 2달러짜리 칩이 도메인 이름 대신 5바이트짜리 ’지문’만 저장하는 방식으로, 53만 개 광고 도메인을 10밀리초 안에 골라내는 Pi-hole급 네트워크 광고 차단기를 만든다는 이야기.

tectalks.io 계정의 릴스는 “2달러짜리 광고 차단기를 만들었는데, 집 안 모든 기기에서 작동한다”로 시작해요. 반응도 뜨거워서 좋아요 2,381개, 댓글이 749개 달렸어요.

릴스가 소개하는 원 프로젝트는 GitHub의 esp32-c3-adblock으로, MIT 라이선스로 공개된 오픈소스예요. 톰스 하드웨어(Tom’s Hardware)와 XDA도 다룬 만큼 검증된 프로젝트이고요. 이 글은 릴스 캡션과 원 저장소의 README를 함께 대조해 썼어요.

뭘 하는 칩인가요

ESP32-C3(스마트 플러그 같은 저가 가전에 들어가는 와이파이 칩)는 램이 400KB뿐인 초소형 칩이에요. 이 보드를 집 공유기 뒷면의 남는 USB 포트에 꽂아 전력을 얻고, 와이파이로 네트워크에 접속해요. 설치는 기기의 DNS 서버 주소를 이 칩으로 지정하는 게 전부죠.

준비 과정도 부담이 없어요. 코딩 없이 브라우저에서 바로 펌웨어를 올리는 원클릭 설치 기능이 준비돼 있어요. 대시보드 화면에서 차단 통계를 보고, 펌웨어와 차단 목록도 무선으로 업데이트할 수 있어요.

DNS 차단의 원리

DNS(Domain Name System, 도메인 이름을 IP 주소로 바꿔 주는 인터넷 안내소)는 모든 통신의 출발점이에요. 기기가 웹사이트를 열 때마다 “이 도메인의 IP 주소가 뭐죠?“라고 가장 먼저 묻거든요.

이 차단기는 그 문의 가운데 블랙리스트에 올라온 광고·추적기 도메인에는 0.0.0.0(연결될 곳이 없는 주소)으로 답해요. 질문 단계에서 걸러지니 광고 요청은 광고 서버에 도달할 일이 없어요. 이런 방식을 싱크홀(sinkhole, 요청을 빨아들여 아무 데도 못 가게 막는 방식)이라고 불러요.

브라우저 확장 프로그램은 그 브라우저에만, 차단 앱은 그 폰에만 작동하죠. DNS 차단은 네트워크에 물린 모든 기기에서 일어나요. 앱을 깔 수 없는 스마트 TV, 게임기, IoT 가전까지 커버된다는 게 이 릴스가 내세우는 장점이에요.

설치 후에는 이렇게 확인할 수 있어요.

dig @<차단기 IP> doubleclick.net   # → 0.0.0.0 (차단)
dig @<차단기 IP> github.com        # → 실제 IP (통과)

램이 부족할 때 쓰는 지문 트릭

릴스는 여기가 “정말 영리한 부분”이라고 강조해요. 파이홀(Pi-hole, 라즈베리파이에 설치하는 대표적인 DNS 광고 차단 프로그램)은 차단 목록 전체를 램에 올려서 빠르게 찾아요. 그래서 컴퓨터급 메모리가 필요하죠.

이 칩은 램이 400KB라서 53만 개 도메인 문자열을 통째로 올리는 건 애초에 불가능해요. 그래서 제작자가 택한 건 이름을 저장하지 않는 방식이에요. 각 도메인을 FNV-1a(빠르고 단순한 해시 함수)로 돌려 40비트, 즉 5바이트짜리 지문만 뽑아요.

지문이 흩어져 있으면 찾기 어려우니 순서대로 정렬해서 플래시(전원을 꺼도 내용이 남는 칩 안의 저장 공간)에 기록해요. 비유하자면, 이름은 전부 버리고 각각의 지문만 작은 노트(플래시)에 사전순으로 정리해 둔 사람이 돼요. 53만 개의 지문은 각각 5바이트니까 약 2.7MB면 충분해요.

찾을 때도 같은 논리예요. 요청이 들어오면 그 도메인의 지문을 뽑고, 정렬된 노트에서 절반씩 범위를 접어 가며 대조하는 이진 탐색(binary search)을 실행해요. 플래시를 읽는 횟수는 대략 18회 수준이고, 와이파이 왕복 시간을 포함해도 답은 10밀리초 안에 나와요.

램 사용량은 목록 크기와 거의 무관하게 50KB 안쪽으로 유지돼요. 플래시는 넉넉한데 작업대(램)가 좁아도, 지문만 챙기면 충분하다는 발상이죠. 단, 지문은 유일하지 않아서 아주 드물게 서로 다른 도메인이 같은 지문을 얻는데, 이건 아래 한계에서 다시 나와요.

지문 길이 40비트의 계산

지문이 같은 도메인이 겹치는 일을 해시 충돌(collision, 다른 입력이 같은 결과값을 얻는 현상)이라고 불러요. 지문이 길수록 충돌 확률은 내려가고, 그 대신 저장 공간은 커져요.

README가 40비트를 고른 계산은 이래요. 32비트로 줄이면 25만 개 목록에서 충돌이 대략 7개 생기고, 64비트로 늘리면 도메인당 3바이트를 “없는 문제를 푸는 데” 낭비하게 돼요. 40비트는 14만 개 규모에서 충돌 0개, 53만 개에서 약 1개가 나오는 지점이에요.

이 방식의 이득은 저가 칩에만 국한되지 않아요. 램에 목록 전체를 올리는 종래 방식은 여분 램(PSRAM)이 달린 8달러짜리 칩을 요구해요. 지문-플래시 방식은 플래시 4MB짜리 2달러 칩에서 같은 일을 하면서 램은 50KB만 써요.

더 큰 칩에서도 지문 방식이 앞서요. 16MB 플래시를 얹은 ESP32-S3에서는 도메인 270만 개를 담는데, 문자열 방식은 8MB 여분 램에서 46만 6천 개가 한계예요. 결국 이건 저가 칩에 억지로 우겨 넣은 편법이 아니라 데이터 구조의 승리예요.

그래서 한계는 뭔가요

릴스도 캡션에서 한계를 솔직하게 인정해요. 첫째, 제작자는 이걸 파이홀의 대체품이 아니라, 본체 차단기가 재부팅되는 잠깐 동안을 맡아 줄 백업용으로 만들었어요. README도 메인 DNS 뒤에 붙이는 보조 서버로 쓰라고 안내하고요.

둘째, 도메인 기준 차단이라는 근본 한계가 있어요. 광고가 콘텐츠와 같은 도메인에서 함께 오는 유튜브 광고는 블랙리스트로 걸러낼 수 없어요.

셋째, 앞서 말한 지문 충돌 1건이에요. 53만 개 목록에서 운 나쁜 도메인 하나가 억울하게 차단될 수 있다는 뜻이에요.

현실적인 트레이드오프도 하나 있어요. 플래시 4MB 안에서 펌웨어 무선 업데이트(OTA)를 켜면 펌웨어 자리를 두 개 쓰느라 블랙리스트 공간이 약 1.3MB로 줄어요. 목록은 25만 개 정도까지 제한되고, 53만 개 “ultimate” 목록은 무선 업데이트를 접은 파티션 구성에서만 들어가요.

기본 목록은 StevenBlack과 Hagezi Light를 합쳐 약 14만 개예요. 와츠앱이나 소셜 서비스가 막히는 일을 피한 구성이에요.

어떻게 연결되나요

이 릴스에서 배울 건 하드웨어가 아니라 설계예요. “목록을 다 보관하려면 램이 충분해야 한다”는 당연한 전제를, 이름을 버리고 지문만 정렬해 두는 데이터 구조로 깬 거예요. 제작자는 영감의 출처로 s60sc/ESP32_AdBlocker(0.0.0.0 싱크홀 아이디어의 선배 프로젝트)를 밝히면서, 이번 구현은 PSRAM 없는 칩용 지문-플래시 최적화에 집중했다고 설명해요.

로드맵에 남은 과제도 보이네요. 플래시 읽기를 18회에서 1~2회로 줄이는 색인 개선이 다음 목표예요. 해결되면 응답 속도가 더 빨라지겠죠.

직접 해보고 싶다면 준비물은 보드 하나예요. 브라우저 플래셔로 기본 목록을 올리고, 공유기 USB 포트에 꽂고, 기기 DNS를 칩 주소로 지정하면 끝이에요. 3D 프린팅 케이스 파일까지 공개돼 있으니 릴스 속 그 모양 그대로 만들 수도 있어요.

램이 부족하다는 말을 “저장 방식을 바꾸자”로 뒤집은 사례라는 점이 이 릴스의 교훈이에요. Pi-hole이라는 제품보다, 이름을 버리고 지문을 남긴 그 발상이 더 오래 남을 거예요.

이 글의 내용은 아래 자료를 기준으로 확인했어요.