happy_various AI 실전 기록

LLM 중계기 개발기 5부 · 25편 / 전체 33편

2026년 10월 1일 기준

이 글에는 제휴 링크가 없고 글에 나오는 제품을 만든 곳들(Electron 프로젝트·마이크로소프트·구글·앤트로픽)과 아무 관계가 없습니다. 제가 직접 만든 중계기의 개발 기록을 바탕으로 썼습니다. 삽화는 GPT 이미지 생성, 도식은 직접 제작했습니다.

무거운 껍데기를 걷어내다 — 대형 SUV에서 경차로 (LLM 중계기 개발기)

혼자 동네 마트에 가는데 7인승 대형 SUV를 몰고 간다고 해 볼게요. 장바구니 하나 실을 자리면 충분한데, 차는 매번 빈 좌석 여섯 개와 넓은 짐칸까지 통째로 끌고 다닙니다. 기름도 그만큼 먹고, 주차 칸도 그만큼 차지하고요. 차가 나쁜 건 아니에요. 하는 일에 비해 너무 클 뿐이죠.

제 LLM 중계기의 겉껍데기가 꼭 그랬습니다. 중계기는 화면 구석에 작게 떠 있는 앱인데, 그 껍데기 안에 웹 브라우저 한 벌을 통째로 싣고 다녔어요. 재 보니 앱이 쓰는 메모리 329MB 가운데 274MB가 껍데기 몫이었습니다.

이 글은 LLM 중계기 개발기의 25편이자, 5부 ‘만들고 나서가 더 어렵다 — 설치·업데이트’의 마지막 편입니다. 지난 24편 「조용한 업데이트는 멈춘 줄 안다」에서는 진행 창 없이 돌던 업데이트가 멈춘 것처럼 보여서 진행률 막대를 붙인 이야기를 했어요. 오늘은 20편과 21편에서 “25편에서 다룹니다”라고 미뤄 둔 이야기, 8월에 앱의 겉껍데기를 통째로 바꾼 일입니다.

커다란 SUV에서 내려 작고 동그란 경차로 신나게 옮겨 타는 로봇 (GPT 이미지 생성)

결론 요약

🚙 1. Electron — 브라우저 한 벌을 싣고 다니는 앱 껍데기

중계기의 관리 화면은 처음부터 웹 페이지였어요. 웹 페이지를 만드는 기술(HTML과 자바스크립트)로 화면을 짰고, 중계기 서버가 내 컴퓨터 안에서 그 페이지를 보여 줍니다.

그런데 웹 페이지를 ‘앱’처럼 쓰려면 껍데기가 필요해요. 아이콘을 눌러 켜고, 화면 구석에 작은 아이콘이 떠 있고, 주소창 없는 창이 열리는 것 말이에요. 7월에 첫 버전을 만들 때 고른 껍데기가 Electron(일렉트론)이었습니다.

Electron은 웹 기술로 만든 화면을 데스크톱 앱으로 포장해 주는 도구예요. 널리 쓰이는 방식인데, 비결이 하나 있어요. 앱마다 자기 전용 웹 브라우저를 한 벌씩 싣고 다닌다는 거예요. 크롬·엣지와 뿌리가 같은 브라우저 엔진(Chromium, 크로미엄)이 앱 안에 통째로 들어 있어서, 어느 컴퓨터에서 켜도 화면이 똑같이 그려집니다.

편한 대신 무거워요.

브라우저 도시가 통째로 들어 있는 커다란 배낭을 내려놓고 홀가분하게 기지개를 켜는 로봇 (GPT 이미지 생성)

📏 2. 먼저 재 봤다 — 329MB 중 274MB가 껍데기

계기는 함께 쓰던 사람의 한마디였어요. “네이티브가 성능이 좋다.” 네이티브(native) 앱은 브라우저를 빌리지 않고 운영체제의 기본 부품으로 직접 만든 앱을 말해요. 8월 6일 새벽의 저장 기록(커밋)과 그날 쓴 계획서에는 이 말을 그대로 따르지 않고 실측으로 검증했다고 적혀 있습니다.

여기서 메모리는 프로그램이 켜져 있는 동안 실제로 차지하고 있는 크기예요.

그다음 그 274MB가 무슨 일을 하는지 봤어요. 껍데기 코드는 302줄이었고, 하는 일은 네 가지뿐이었습니다.

① 관리 화면을 가리키는 창 하나 ② 화면 구석의 트레이 아이콘 ③ 중계기가 두 번 켜지지 않게 막는 잠금 ④ 지난번에 남은 좀비를 치우고 문 번호(포트)를 되찾는 일 (21편)

창 하나와 아이콘 하나를 띄우려고 브라우저 한 벌을 싣고 다닌 셈이에요. 장바구니 하나 사러 7인승을 끌고 나간 것처럼요.

Electron 앱과 앱 모드 런처의 메모리, Electron판과 트레이판의 압축 파일 크기, 그리고 상자 안에 든 것 (직접 제작)

반대로 서버는 병목이 아니었어요. 55MB에 CPU 사용률 0.2%였거든요. 그래서 기록은 선을 분명히 그었습니다. 걷어낼 것은 껍데기이고, 서버는 다시 짜지 않는다. 이유도 함께 적혀 있어요.

“네이티브가 낫다”는 말은 반만 맞았던 거예요. 껍데기에 대해서는 맞았고, 서버에 대해서는 아니었죠.

🪟 3. 브라우저는 빌려 쓴다 — ‘앱 모드’ 창

남은 문제는 ‘전용 창’이었어요. Electron을 빼면 창을 그려 줄 브라우저가 없어집니다. 그런데 컴퓨터에는 이미 브라우저가 깔려 있죠. 그래서 그걸 빌리기로 했어요.

Edge나 Chrome 같은 브라우저에는 앱 모드라는 켜는 방법이 있어요. 브라우저를 부를 때 --app= 뒤에 주소를 붙이면, 주소창도 탭도 없는 독립된 창이 하나 열려요. 쓰는 사람 눈에는 데스크톱 앱 창과 다르지 않은데, 중계기가 싣고 다니는 브라우저는 0바이트가 됩니다. 집을 지고 다니는 대신, 이미 서 있는 집의 창문 하나를 여는 셈이에요.

수레에 실린 무거운 이동식 집을 내려 두고, 이미 서 있는 아늑한 집의 창문을 여는 로봇 (GPT 이미지 생성)

같은 날 새벽에 새 시작 프로그램(런처)이 생겼어요. 하는 일은 세 단계예요.

① 문 번호를 확보한다 — 좀비 치우기와 빈 번호 찾기를 Electron 없이 그대로 옮겼어요. 이미 켜진 정상 중계기는 치우지 않고 그 화면을 쓰게 하고, 낯선 프로그램은 절대 끄지 않는다는 규칙도 그대로예요 ② 중계기 서버를 켠다 ③ 앱 모드로 전용 창을 연다

창을 여는 데는 순서를 정해 두었어요. ‘아무것도 안 열린 채 이유도 모르는’ 상태를 남기지 않으려고요.

일부러 하지 않은 일도 하나 있어요. 브라우저에는 설정과 방문 기록을 담는 프로필이라는 폴더가 있는데, 전용 창에 별도 프로필을 주면 깔끔하게 분리되긴 해요. 하지만 그러면 브라우저가 통째로 하나 더 떠요. 기록은 이걸 “가벼우려고 Electron을 걷어냈는데 같은 비용을 다시 내는 꼴”이라고 적었습니다. 그래서 프로필을 따로 주지 않고, 이미 켜져 있는 브라우저에 창만 하나 붙게 했어요.

결과는 저장 기록에 이렇게 남았어요. 런처 61MB, Electron 329MB, 81% 감소. 기록은 이 길을 ‘서버 하나 + 브라우저 창 하나’라고 적었어요. 창은 이미 켜져 있던 브라우저에 붙기 때문에, 창이 쓰는 몫은 런처가 아니라 브라우저 쪽에 잡힌다는 뜻이에요. 쓰는 사람에게 진짜로 줄어든 건 ‘브라우저 한 벌을 하나 더 띄우던 비용’입니다.

⚖️ 4. 빌려 쓰는 값 — 컴퓨터마다 달라지는 것들

남의 집 창문을 빌리면 그 집 사정을 따라야 해요. 브라우저를 빌린 대가도 있었습니다.

① 어떤 브라우저가 깔려 있는지 컴퓨터마다 다르다 윈도에는 대개 Edge가 들어 있어서 첫 후보에서 거의 열리지만, 다른 컴퓨터는 사정이 제각각이에요. 3절의 순서(앱 모드 → 기본 브라우저 탭 → 주소 안내)가 그래서 필요했어요. Electron 시절에는 앱에 실린 같은 브라우저 엔진이 화면을 그렸는데, 이제는 그 컴퓨터에 깔린 브라우저가 그려 줍니다.

② 브라우저의 버릇을 따라야 한다 런처를 저장하고 7분 뒤의 저장 기록에는 맥에서 확인하다 찾은 고장이 적혀 있어요. 20편 끝에서 잠깐 말한 그 일이에요. 브라우저가 이미 켜져 있으면, 맥의 ‘앱 열기’ 명령은 “앱 모드로 열어 달라”는 부탁을 조용히 버리고 브라우저만 앞으로 가져왔어요. 런처는 “전용 창을 열었다”고 기록했지만 실제 창은 어디에도 없었죠. 기록은 이걸 성공을 위장하는 실패라고 불렀어요.

브라우저 앱 안에 든 실행 파일을 직접 부르게 바꾸자, 이미 켜진 브라우저가 부탁을 넘겨받아 창을 열었어요. 브라우저를 새로 하나 더 띄우는 방법은 쓰지 않았어요. 이번에도 가벼워지려던 의미가 사라지니까요.

③ 창이 닫혀도 런처는 모른다 창은 브라우저의 것이라, 사용자가 창을 닫아도 런처에게는 소식이 오지 않아요. Electron에서는 ‘창이 모두 닫힘’을 알아채 정리 담당을 불렀는데(21편), 그 손잡이가 사라진 거예요. 창만 닫고 AI 프로그램은 남기는 일은 기록에 따르면 “이 저장소가 반복해서 겪은 좀비 사고의 재발 경로”였어요.

그래서 런처가 생기고 20분 남짓 뒤, 관리 화면 위쪽에 ⏻ 종료 버튼을 달고 중계기에 ‘종료 창구’를 따로 만들었어요. 응답부터 보내고 정리하는 순서와 11초 상한은 21편 5절에서 이야기했어요.

④ Electron이 잠가 둔 열쇠 Electron에는 운영체제의 금고를 빌려 내용을 잠가 주는 기능이 있어요. 중계기는 사용자가 넣어 둔 API 키 같은 열쇠를 이 기능으로 잠가 두었고요. Electron을 빼면 그 금고를 여는 손잡이도 함께 사라집니다.

조사해 보니 계획서에 적은 것보다 위험이 컸어요. 예전 코드는 열쇠를 열지 못하면 아무 말 없이 ‘빈 금고’를 돌려줬거든요. 사용자 눈에는 열쇠가 사라진 것처럼 보이고, 다시 입력하면 그 저장이 원래 파일을 덮어써서 정말로 영영 사라지는 길이었어요. 기록은 이걸 “조용한 데이터 손실 경로”라고 적었어요. 그날 새벽부터 이렇게 막았습니다.

공짜는 아니었어요. 새로 저장하는 열쇠는 운영체제의 금고 대신 중계기가 직접 잠그게 됐고, 그만큼 운영체제가 해 주던 보호 한 겹을 잃었어요. 기록은 이걸 Electron을 없애는 이상 피할 수 없는 교환이라며 ‘의도된 선택’으로 문서에 남겼고, 지금도 새 열쇠는 이 방식으로 저장돼요.

🧰 5. 이틀 뒤, 껍데기를 통째로 바꾸다 — 작은 트레이 프로그램

계획서에는 네 단계가 적혀 있었어요.

① Electron 없는 런처를 Electron 옆에 나란히 둔다 (8월 6일 새벽 완료) ② 종료 창구를 만들고, 잠긴 열쇠를 옮겨 담는다 (같은 날 새벽 완료) ③ 배포판 포장 방식을 바꾼다 — 목표는 112MB에서 50MB 이하 ④ Electron을 지운다 — 단, 검사는 지우지 않고 검사할 대상만 옮긴다

③과 ④는 8월 8일 새벽 한 번의 저장에 함께 들어갔어요. 그런데 이때 바뀐 모양은 계획서의 ‘앱 모드 창’보다 한 걸음 더 나갔습니다. 전용 창마저 내려놓았거든요.

껍데기가 하던 네 가지 일은 이렇게 자리를 옮겼어요.

① 관리 화면 창 → 필요할 때만 여는 기본 브라우저 탭 ② 트레이 아이콘 → 운영체제마다 따로 만든 작은 트레이 프로그램 ③ 두 번 켜지지 않게 잠금 → 트레이가 직접 막고, 두 번째로 실행하면 이미 켜진 트레이에게 설정 화면을 열어 달라고 부탁 ④ 좀비 치우기 → 런처에 옮겨 둔 그대로

트레이 프로그램의 코드는 첫날 889줄이었어요. 업데이트를 맡는 도우미까지 들어 있어서 Electron 껍데기(302줄)보다 오히려 길어요. 23·24편의 자동 업데이트도 이 트레이가 맡은 일이에요. 그래도 이 889줄은 브라우저를 싣고 다니지 않아요. 가벼움은 코드 줄 수가 아니라 싣고 다니는 짐에서 온다는 걸 보여 준 셈이에요.

대신 내려놓은 편리함도 있어요. Electron은 하나의 코드로 세 운영체제를 덮었지만, 이제는 트레이 프로그램을 운영체제마다 따로 만들어야 했어요. 기록에도 맥판과 리눅스판은 윈도에서 묶고 구조만 검증했으니, 그 운영체제에서 실제로 켜 보는 확인이 아직 필요하다고 적혀 있어요.

쓰는 사람에게 달라진 점은 이래요.

📐 6. 남긴 규칙 — 재고, 무거운 곳을 자르고, 약속은 그대로

① 자르기 전에 잰다 “네이티브가 낫다”는 말을 그대로 따랐다면 서버까지 다시 짜는 쪽으로 갈 수도 있었어요. 숫자 네 개(329·55·274·112)가 어디를 잘라야 하는지 먼저 알려 줬어요.

② 탓하기 쉬운 곳이 아니라 무거운 곳을 자른다 1만 줄이 넘는 서버는 가장 큰 덩어리라 탓하기 쉬웠어요. 하지만 잰 숫자로는 302줄짜리 껍데기와 그 안에 실린 브라우저가 무거웠어요. 그래서 서버는 남기고 껍데기 속 브라우저만 뺐어요. 껍데기를 바꿔도 그대로인 AI 프로그램들에는 다른 방법이 쓰였고요. 5절에서 본 것처럼 필요할 때만 켜고, 쉬면 내려놓는 방식이에요.

③ 약속은 그대로 옮긴다 껍데기는 바뀌어도 바깥에서 보는 약속은 같아야 해요.

정리

① 앱 전체는 329MB를 썼는데 중계기 서버는 55MB였어요. 나머지 274MB는 브라우저 한 벌을 품은 Electron 껍데기 몫이었고, 그 껍데기가 하던 일은 창 하나·트레이·두 번 켜기 잠금·좀비 치우기, 네 가지뿐이었어요 ② 서버는 다시 짜지 않고 브라우저만 걷어냈어요. 이미 깔린 브라우저의 앱 모드를 빌려 61MB가 됐고, 브라우저가 컴퓨터마다 다르다는 것·맥의 버릇·창 닫힘을 모른다는 것·잠긴 열쇠라는 값을 치렀어요. 이틀 뒤에는 작은 트레이 프로그램으로 바꿔 윈도용 압축 파일이 112MB에서 41.6MB로 줄었어요 ③ 자르기 전에 재고, 무거운 곳을 자르고, 끄는 약속과 검사는 그대로 옮겼어요

이렇게 5부 ‘만들고 나서가 더 어렵다’를 마칩니다. 다른 컴퓨터에서 켜고, 끄고, 준비 상태를 알리고, 새 판으로 바꾸고, 가볍게 만드는 일까지, 만든 다음의 일이 만드는 일만큼 많았어요.

다음 26편은 「한 질문, 여러 AI의 답」이에요. 6부 ‘중계기 위에서, 그리고 회고’를 시작하며, 같은 질문을 여러 AI에게 한꺼번에 던지는 이야기를 할게요.


2026년 10월 1일 기준입니다. 제가 만든 중계기의 개발 기록(저장 기록의 시각과 메모, 계획서와 설계 문서, 배포 기록)을 바탕으로 썼고, 메모리와 파일 크기는 그 기록에 남은 실측값입니다. 특정 기업·서비스의 공식 입장이 아닙니다.