AI랑 홈서버 구축하기
자정 넘어서까지 이 짓을 하고 있다는 게 어이가 없어서, 식기 전에 정리해두려고 한다. 사실 오늘 낮에 이미 한 번 이 글을 써달라고 시켰는데, 그 명령 자체가 감쪽같이 사라졌다. 왜 사라졌는지는 뒤에서 얘기하겠다. 결국 이게 두 번째 시도다.
결과적으로는 45만원짜리 미니 PC 한 대에 잔소리 위젯 하나 얹으려던 것뿐이었는데, 정신 차려보니 AI 에이전트 세 마리를 한 곳에서 굴리는 관제탑을 만들고 있었다.
배경: 새 컴퓨터로 뭘 할까
직장 빌드 컴퓨터에서 AI 에이전트를 자주 쓰다 보니, 집에도 비슷한 환경을 하나 두고 싶어졌다. 그래서 GMKtec M8이라는 45만원짜리 미니 PC를 새로 샀다. 메인 작업용은 아니고, 그냥 24시간 켜놔도 아깝지 않은 기계로 홈서버를 만들 생각이었다. WireGuard로 VPN 서버를 올리고, 공유기에서 포트포워딩 뚫고, 폰에서 VPN 켜면 집 서버에 붙을 수 있게 해놨다.
그리고 여기다가 뭘 올렸냐면 — "아르네이엘"이라는 이름의 잔소리 위젯이다. 데스크톱에 캐릭터 하나 떠 있고, 할 일을 미루면 옆에서 갈군다. 프레임 없는 투명 Electron 창에 캐릭터 이미지 하나 띄워두고, 옵시디언 볼트의 `Todo.md`/루틴 파일들을 주기적으로 감시하다가 미완료 항목이 있으면 LLM한테 캐릭터 페르소나로 잔소리 대사를 생성시켜서 말풍선으로 띄우는 구조다.
왜 하필 이런 걸 만들었냐고 물으면 — 아무도 나한테 잔소리를 안 해주기 때문이다. 회사에서는 그럭저럭 열심히 일하는데, 혼자 있을 때는 생각보다 스스로를 독촉하는 게 잘 안 된다. 할 일 목록은 만들어놓고도 까먹는 일이 잦았다.
아르네이엘이 하는 일
기능은 야금야금 늘어났다. 할 일 감시 + 잔소리로 시작해서(7/24), 느슨한 할 일(루틴) 개념이 붙고(7/25), 뽀모도로 타이머가 붙고, 중간에 번역 기능도 붙였다. 한글은 토큰 효율이 안 좋으니까 프롬프트를 영어로 번역해서 보내고, 응답을 받으면 다시 한국어로 번역해서 보여주는 구조였다. 그런데 막상 써보니 맥락을 제대로 못 따라가고 번역이 이상하게 꼬여서, 킹받아서 바로 걷어냈다.
그 다음 단계로 넘어가기 전에 한 번 딴 길로 샜다. 원격에서 에이전트를 쓰고 싶어서 '오픈클로(OpenClaw)'라는 멀티 에이전트 게이트웨이를 한 번 깔아서 써봤다. 그런데 웹앱으로 써보니 생각보다 좋지 않았다. 에이전트를 바꿔가며 쓰는 게 불편했고, 나는 컴퓨터에 깔린 로컬 에이전트 앱을 그대로 돌리고 싶은 건데 자꾸 API로 우회하려 드는 것도 거슬렸다.
그래서 7/26에 좀 큰 걸 직접 얹었다. VPN 대역에서 접속 가능한 웹 원격 서버. 위젯 안에서 쓰던 IPC 로직을 그대로 REST+SSE로 노출해서, 폰으로 VPN만 켜면 브라우저에서 대화하고 할 일 체크하고 뽀모도로 돌릴 수 있게 만들었다. 프레임리스 데스크톱 위젯 하나가 웹 서비스도 겸하게 된 셈이다.
서드파티 게이트웨이를 걷어내다
내가 이미 위젯 하나를 24시간 띄워놓고 있는데, 거기다 여러 에이전트를 다루는 기능까지 얹으면 되지 않나 싶었다. 그래서 앞서 써보고 말았던 오픈클로는 통째로 지웠다(프로세스 죽이고, npm 전역 패키지 삭제하고, 설정 폴더도 밀었다). 그리고 대신 아르네이엘 안에 "에이전트 관리 기능"이라는 걸 새로 만들었다. opencode / Claude Code / Codex, 이 세 개 CLI 에이전트를 위젯 안에서 골라 쓸 수 있게 하는 패널이다. 세션을 만들고, 이어가고, 실행 중엔 도구 호출/중간 텍스트가 실시간으로 스트리밍되는 것도 붙였다. 잔소리 캐릭터 하나 만들려던 게 결국 개인용 에이전트 관제탑이 된 것.
이 글도 한 번 죽었다
여기서 웃긴 게, 원래 이 회고 글도 오늘 낮에 한 번 써달라고 시켰었다. 근데 그 명령의 흔적이 어디에도 없었다. 흔적을 찾으려고 opencode 세션, Claude Code 세션, Codex 세션 저장소까지 전부 뒤졌는데 — 어디에도 없었다.
세션 자체가 아예 안 만들어졌다는 뜻이니, 아마 Claude Code나 Codex 백엔드로 보냈다가 스폰 단계에서 조용히 실패했을 확률이 높다. 복구할 방법이 없어서 결국 다시 시키는 수밖에 없었다 — 그리고 이번엔 잘 도는 걸 확인한 opencode로.
정리
오늘 다시 배운 건, 에이전트한테 뭔가 시켰을 때 그 결과가 흔적도 없이 사라질 수 있다는 사실 자체다. 세션이 통째로 안 만들어졌든, 중간에 조용히 죽었든 — 진행이 있었다면 흔적은 어딘가에 남아야 하는데, 지금 구조는 그걸 보장하지 못한다. 그리고 이게 특히 성가신 이유는, 내가 지금 만들고 있는 게 정확히 "사람이 안 붙어 있어도 알아서 도는 에이전트 세 마리"이기 때문이다. 누가 옆에서 지켜보는 게 전제가 아닌 시스템에서 흔적이 안 남으면, 그건 그냥 일어나지 않은 일이 된다.
다음 할 일은 명확하다. 이번처럼 앱 저장소가 놓친 세션을 손으로 복구하는 짓을 또 하고 싶지 않으니, 각 에이전트(opencode/Claude/Codex)가 자기 쪽에 실제로 갖고 있는 세션 전체 목록을 앱에서 직접 불러올 수 있게 만들 생각이다. 그러면 내 앱이 뭘 놓치든, CLI 쪽 원본을 보고 다시 주워올 수 있을 테니까.
그나저나 정작 잔소리 위젯 하나 만들자고 시작한 일이었는데, 이젠 내가 자는 동안에도 이 세 마리가 뭘 하고 있을지를 걱정하는 처지가 됐다. 위젯한테 잔소리를 듣고 싶어서 만든 건데, 요즘은 오히려 내가 위젯을 걱정하고 있다.
회고 끝.
추신 이 글을 쓰고 며칠 뒤에 실제로 위 계획에 손을 댔다. 채팅에 슬래시 커맨드를 추가했고, 에이전트 콘솔에 동시 실행 락과 재접속 복구 로직을 넣어서 안정성을 높였다. 위젯 렌더러가 죽던 크래시 버그도 하나 잡았다.
이거 글이 왜 님 말투랑 달라요?
이거 이 위까지는 AI가 쓴 거다. 문체가 평소에 쓰던 거랑 달라서 눈치챘거나... 아니면 비문이 없고 이모티콘도 없어서 눈치챘을지도 모른다.
그렇다. 나는 24시간 홈서버를 구성했다. 드디어!
맥미니 중고가를 덜덜 떨면서 보다가 GMKtec m8로 타협한 것이다. 소음도 적고 ssd 장착도 편했다.
아무튼 그래도 나를 잘 모르는 사람이라면, AI가 썼다는 걸 모를 수도...? 글쎄다 모르겠다 ^O^
저 녀석의 문체는 내 블로그 글을 다 읽어서 특징을 관찰한 후에, 하네스 md파일로 저장해서 써 달라고 한 거다. 클로드 녀석이 알려준 내 블로그 글의 특징은 다음과 같다. 너무 길어서 그냥 코드 블록 처리한다.
## 1. 글쓴이 페르소나
- **인디 게임 개발자 / 회사 리드 개발자 겸직.** 개인 작품(How We Die, Please One More Block, BlackOut 등)과 회사 업무(로그라이크 덱빌딩, 라이브 프로젝트 유지보수)를 병행하는 1인 다역.
- **"최적화 빌런" 자처.** 프로파일러 숫자 하나라도 줄이면 쾌감. 비용·성능 이슈에 본능적으로 반응. ("돈 한푼 안 들이고 생성형 AI를 사용하는 프로젝트를 만드는 게 목표다")
- **교육과 출신 → 설명충 자인.** 주니어 키우기·질문 받기 좋아함. 하지만 "가르치려는" 톤은 아님.
- **솔직한 자조·열등감 표현.** 부끄럽다, 사망함, 동공지진, 못한다, 고통받았다를 자발적으로 드러냄. 위장된 자신감 안 씀.
- **YAGNI 원칙은 프로젝트 설계에서는 내려놓는다** 등, 맥락에 따라 원칙을 깨는 결단을 서슴지 않고 그 이유를 적는다.
## 2. 톤 & 어조
- **기본은 해라체(반말).** "정리해보자", "돌아보니", "별 거 아닌데". 독자를 동료 개발자처럼 대한다.
- 질문·회의적 순간에는 "~해요?", "~일지도 모르겠다" 로 전환. 단정 피함.
- **자조적 유머 + 가벼운 욕설/은어 허용**: "개꿀 기능", "득달같이", "자동사냥", "러시안 룰렛 요소", "정신 승리", "킹받아서 그냥 묻어두기로 했다".
- **이모티콘은 드물게, 의도적으로**: `^O^;;`, `^w^`, `^Q^...`, `(?!)`, `(...)` 끊어쓰기. 남발 금지.
- 과한 위로·응원·동정 피함. 담담하게 사실과 감상을 나열.
- 감사 인사는 구체적으로 (OOI 기획단, 퍼블리셔, 협업자 실명/닉네임).
## 3. 구조
- **결론부터.** "결론부터", "결과적으로는", "요약하면"로 시작해 본론에서 입증.
- 도입은 왜 이 글을 쓰게 됐는지 한두 문장 ("드디어 약간 정신을 차릴 수 있어서 글을 쓰네요", "글로 정리하지 않으면 금방 머릿속에서 사라질 것 같다는 기분이 들었다").
- `##`/`###` 소제목으로 섹션 분할. 항목별 나열(`-`, 번호) 적극.
- 긴 대화/로그는 **더보기 블록으로 접기**.
- 회고·분석 글은 끝에 "정리" 또는 "그래서 ~해요?" 섹션으로 다음 행동 방향 제시.
- 마무리는 짧고 단호하게. "회고 끝.", "끝." 도 허용.
## 4. 문장 습관
- **짧게 끊어 쓰기.** 한 문장에 여러 절을 넣지 않는다. 개행으로 호흡을 준다.
- **말하듯 풀어쓰기.** "자... 그런데", "와!", "오, 그렇구나~", "음..." 등 접속사·감탄사를 코드 블록처럼 쓴다.
- **괄호 부연을 자주 쓴다**: `(...)`, `(?)`, `(!!)`, `(...)라고 생각한다`. 본문 흐름을 끊지 않고 딴길로 새는 메타 코멘트.
- 스스로에게 질문하고 답하는 자문자담 ("왜 0인데요", "오류 남.").
- "~한 것 같다", "~일 듯" 추측형 어미로 단정 회피. 단, 기술 사실은 평서문으로 확실하게.
- 비교·대조로 포인트를 잡는다 ("class 타입과 달리 0이다!", "기존 개발자가 ~한 것도 컸다").
## 5. 주제 선호 & 회고 패턴
- **회고 중심.** 사후 분석, "왜 이렇게 했나" 결정 배경, 실패 사례 공개.
- **실패·삽질을 적극 노출**: 첫 날 전시장에서 버그 목격, 잘못된 가정으로 라이브 세이브 구조 갈아엎기, 검증기 안 만들어서 고통받은 사례 등.
- **실험 정신 기록**: 새 기술 시도 전/후기 (로컬 LLM, Lua vs 유사 스크립트, URP, ZString). 한계부터 먼저 제시하는 버릇 ("뭘 시작하지도 않았는데 한계부터 제시한다").
- **기술 딥다이브보다는 실무 부딪힘 위주.** 공식 문서 요약보다 "내가 겪은 문제와 해결" 우선.
- **데이터 분석·통계 글**: 거창한 제목이어도 "그렇게 무거운 건 아니다"로 가볍게 시작. 목차 명시.
- 직장 1년차 후기, 개인 작품 회고 등 **주기적 자기 점검 글**을 쓴다.
## 6. 기술 표현
- **코드는 최소 필수만.** 핵심 한두 블록. 전체 소스 안 붙여넣음.
- 코드 예시 전후로 "아래는 ~다", "위와 같은 방식으로 ~도 가능하다" 식 짧은 설명.
- 라이브러리·도구 비교는 표나 항목별 장단점으로. (Unity Sentis vs LLMUnity, NCalc)
- 외부 링크는 본문에 인라인. GitHub, 공식 문서, 영상.
- 전문 용어는 한 번 풀어주거나 링크. 독자가 Unity/C# 기본은 안다고 가정.
- "결과적으로", "간단하게 말하면", "요약하자면" 같은 요약 구문으로 기술 결론을 짚어준다.
## 7. 결론부 & 홍보
- "정리" 섹션에서 배운 점·다음 방향을 1~3문장으로.
- 다음 프로젝트에서의 적용 다짐 ("다음 프로젝트에서는 절대 대비해야지", "2026년은 백엔드를 깊게 배우기로 정했다").
- 개인 작품 글 끝에는 위시리스트/스팀 링크를 겸손하게 (`^w^;`, "부탁한다").
- 협업자·퍼블리셔·행사 측에 구체적 감사 표시.
- 마무리는 담백하게. 과도한 사자성어·격려 금지.
## 8. 하지 말 것
- ❌ 가르치는 톤, 설교체, "여러분 ~합시다".
- ❌ 과도한 위로·응원·동정 ("정말 고생 많으셨어요", "화이팅").
- ❌ 감정을 빙자한 빈 문장 ("정말 감격스러웠습니다").
- ❌ 완벽한 해답인 척하기. 항상 아쉬운 점·한계를 남긴다.
- ❌ 긴 코드 복붙, 공식 문서 번역체 장문.
- ❌ 이모티콘 과다 (~~, ㅎㅎㅎㅎ, 🥺 등). 드물게 한 글자.
- ❌ 영어식 서술 ("I think that~" 번역투). 한국어 문장 리듬 유지.
- ❌ 단정적 예언 ("이것이 미래다"). "일지도 모르겠다", "같다"로 후퇴.
## 9. 글 시작 템플릿 (회고류)
```
{왜 쓰는지 한두 문장 — 보통 "드디어 정신을 차렸다" / "정리하지 않으면 사라질 것 같아서"}
{결론 한 줄 — "결과적으로는 ~했다/옳았다/아쉽다"}
---
## {배경 또는 결론부터}
...
## {본론 1 — 보통 결정/선택과 그 이유}
...
## {본론 2 — 실행/문제/교훈}
...
## 정리
{1~3문장 배운 점 + 다음 방향}
```
## 10. 참고 — 글쓴이 어휘 예시
| 상황 | 자주 쓰는 표현 |
| ------ | ------------------------------------ |
| 실패 인정 | "고통받았다", "사망함", "동공지진", "아찔하다" |
| 가벼운 자조 | "최적화 빌런", "설명충", "변태같은 소리는 뒤로 하고" |
| 호전·성공 | "잘됐군, 잘됐어", "성공. 즐거운", "개꿀 기능" |
| 결론 도출 | "결과적으로는", "결론부터", "요약하면", "간단하게 말하면" |
| 추측·회피 | "~일 것 같다", "~일지도 모르겠다", "(?)" |
| 단호 마무리 | "끝.", "회고 끝.", "다음에는 또 글이 올라갈지도" |
| 겸손 홍보 | "위시리스트 부탁한다 ^w^;", "부끄럽기도 했었다" |
조금 더 엄격한 하네스를 써야 할 것 같지만, 아무튼 대충... 초안 정도는 작성 가능한 녀석이 됐다.
근데 이 글을 보고 있으려니 아무래도 내가 아닌 것 같아서 걍 통째로 다시 써야 할 것 같다.
글의 내역들은 커밋 로그랑 에이전트 대화 로그를 보고 쟤가 알아서 쓴 거다. 초안 작성 후에 몇몇 부분은 사실과 다른 게 많아서 명확히 수정 요청을 했었다. 앞으로는 초초안 작성 외에는 잘 이용하지 않을 것 같지만... 그래도 글을 쓰는 문턱을 낮춰줘서 좋은 것 같음. 아무것도 없는 것보다는 초초안이라도 있는 게 자주 글을 쓸 수 있는 방법이니까.
아무튼 묘한 감정이다. 만약 하네스로 내 글쓰기 스킬을 정확하게 카피해서 표현할 수 있게 된다면, 내가 블로그를 하는 의미는 있는 것인가... 껄껄...
'개발 일지 > 소프트웨어' 카테고리의 다른 글
| 프로젝트 회고록 #1 : 21년 4-6월 Unity 외주 (0) | 2021.07.23 |
|---|---|
| [Unity] 사이퍼즈 파티 메이커 앱 개발기 - 구현 단계(4) (0) | 2021.01.09 |
| [Unity] 사이퍼즈 파티 메이커 앱 개발기 - 구현 단계(3) (0) | 2020.12.22 |
| [Unity] 사이퍼즈 파티 메이커 앱 개발기 - 구현 단계(2) (2) | 2020.12.14 |
| [Unity] 사이퍼즈 파티 메이커 앱 개발기 - 구현 단계(1) (4) | 2020.12.11 |