> ## Content Index
> Fetch the complete content index at: https://withkai.io/llms.txt
> Use this file to discover other available public pages before exploring further.

# [이것도 AI로 될까? — 차 관리 편] 5부 — 집 안에서만 되는 건 절반이었다
- URL: https://withkai.io/igeosdo-airo-doelgga-ca-gwanri-pyeon-5bu-jib-aneseoman-doeneun-geon-jeolbanieossda/
- Published: 2026-08-22T14:27:20.000Z
- Updated: 2026-08-22T14:27:20.000Z
- Author: Kai U
- Tags: AI, IT·개발, 도커, 생산성

> **이번 편의 요청의 요지**  
> 정비소나 외출 중에도 내 기록 도구를 쓰게 하되, 집 안의 데이터와 관리 화면은 안전하게 지켜 줘.

## 집 안에서만 되는 것은 절반만 된 것이다

여기까지 만든 것들은 전부 집 NAS 안에서 돈다. 기록을 넣는 곳도, 판정하는 곳도, 화면도 거기 있다.

집에서는 잘 된다. 문제는 정비소가 집에 없다는 것이다.

정비를 받고 나오면서 기록을 넣으려면 밖에서 서버에 닿아야 한다. 화면을 열어 "지금 뭐가 갈 때가 됐지"를 보는 것도 대개 밖에서다. **집 안에서만 되는 도구는 정작 필요한 순간에 안 되는 도구다.**

그래서 AI에게 집 안의 서버를 밖에서도 쓰게 해 달라고 했다. 조건은 두 가지였다. 사람이 쓰는 화면은 인증 뒤에 열리고, 기계가 부르는 길은 필요한 범위만 열려야 했다. 편리함을 늘리면서 집 안의 다른 데이터까지 함께 내놓고 싶지는 않았다.

## 공유기에 구멍을 내는 방법은 쓰지 않았다

밖에서 집 안으로 들어오는 흔한 방법은 공유기에 포트를 여는 것이다. 특정 포트로 들어온 요청을 안쪽 기기로 넘겨 주면 된다. 설정도 몇 분이면 끝난다.

쓰지 않았다. 포트를 열면 그 순간부터 **인터넷 전체가 그 문을 두드릴 수 있다.** 내가 주소를 아무에게도 안 알려 줘도 상관없다. 온종일 모든 IP의 모든 포트를 훑고 다니는 것들이 있고, 열린 포트는 며칠 안에 목록에 오른다.

그 문 뒤에 있는 것이 로그인 화면이라 해도 마음이 놓이지 않았다. 로그인 화면이 있다는 것은 **그 소프트웨어가 인터넷에 노출돼 있다**는 뜻이고, 거기에 취약점이 발견되면 내가 패치를 올리기 전까지는 열려 있는 것이다. 집 NAS에는 정비 기록만 있는 것이 아니다.

## 터널은 안에서 밖으로 연결한다

대신 터널 방식을 썼다. Cloudflare가 제공하는 것이다.

![Cloudflare 연결 상태 화면](https://withkai.io/content/images/2026/08/carlog-5-cloudflare-connected.png)

*Cloudflare 연결이 켜진 상태를 확인한 화면이다. 실제 터널은 NAS 안의 프로그램이 바깥으로 연결을 유지한다.*

방향이 반대인 것이 핵심이다. 밖에서 안으로 들어오는 문을 여는 게 아니라, **안에 있는 작은 프로그램이 밖으로 나가서 연결을 유지한다.** 방문자는 Cloudflare에 접속하고, Cloudflare가 그 연결을 통해 내 NAS로 요청을 넘긴다.

그래서 공유기에는 아무 구멍도 나지 않는다. 포트 스캔에도 안 잡힌다. 스캔할 열린 포트가 없기 때문이다. NAS의 실제 주소도 밖에서 보이지 않는다.

설치는 도커 컨테이너 하나 띄우고 관리 화면에서 어느 주소를 어디로 보낼지 정하는 것이 전부였다. 인증서도 알아서 붙는다.

## 열어 놓고 아무나 못 들어오게

터널만 놓으면 그 주소는 인터넷에 공개된 것이다. 포트는 안 열었지만 주소를 아는 사람은 들어올 수 있다.

그래서 앞에 인증을 하나 더 걸었다. Cloudflare가 방문자를 먼저 확인하고, 통과한 사람만 뒤로 보내 준다. **내 서버에 요청이 닿기 전에** 걸러진다는 점이 중요했다. 서버의 로그인 화면이 첫 방어선이면 그 화면 자체가 공격 대상이 되는데, 이 방식에서는 서버가 아예 요청을 받지 않는다.

정책은 단순하게 뒀다. 허용 목록에 이메일 하나. 로그인하면 한동안 유지되고 그 뒤에는 다시 확인한다.

설정하고 나서 확인은 로그인하지 않은 상태로 해 봤다. 브라우저는 이미 로그인돼 있으니 소용이 없다. 터미널에서 주소를 두드려 보니 전부 로그인 화면으로 넘기는 응답이 왔다. **화면이 아니라 응답 코드로 확인해야 한다.** 시크릿 창으로 여는 방법도 있지만 이쪽이 확실하다.

## 주소가 바뀌자 관리 화면이 깨졌다

터널을 붙이고 나서 데이터 관리 화면을 열었더니 껍데기만 나왔다. 로그인은 되는데 그 뒤가 하얗다.

브라우저 개발자 도구를 열어 보니 화면을 그리는 데 필요한 파일들이 전부 없다고 나오고 있었다. 서버는 멀쩡히 돌고 있는데 파일을 못 찾는다.

원인은 그 도구가 **자기 주소를 알고 있어야 한다**는 데 있었다. 설정에 공개 주소를 적는 칸이 있고, 화면에 필요한 파일들의 경로를 그 값으로 만들어 낸다. 나는 그 칸을 집 안에서 쓰던 주소로 둔 채 밖에서 열고 있었다. 서버는 밖에서 온 요청에 대해 안쪽 주소로 된 경로를 돌려주고 있었던 것이다.

값을 새 주소로 고치고 다시 띄우자 바로 열렸다.

터널을 붙이는 것은 앞단의 일이라고 생각했는데, **뒤에 있는 프로그램이 자기가 어디에 있다고 생각하는지**도 함께 맞춰야 했다. 주소를 하나 새로 내면 그 주소를 아는 곳이 여러 군데 생긴다.

## 콘솔이 안 열려서 삼십 분을 썼다

또 하나. 관리 도구에서 컨테이너 안으로 들어가는 콘솔이 밖에서는 안 열렸다. 집 안에서는 되는데 밖에서만 안 된다.

콘솔은 일반 요청이 아니라 **연결을 유지하는 방식**을 쓴다. 처음에 보통의 HTTP로 접속한 다음 그 연결을 다른 방식으로 바꿔 달라고 요청하고, 그때부터 양쪽이 계속 주고받는다. 터미널이니 그래야 한다.

앞단 프록시에 그 전환을 지원하는 설정이 있어서 켜 뒀는데도 안 됐다. 알고 보니 인증을 붙이려고 따로 써 둔 설정 블록이 **기본 설정을 통째로 덮고 있었다.** 전환에 필요한 헤더 세 줄이 그 블록에는 없었다.

그 세 줄을 직접 넣으니 열렸다.

설정을 겹쳐 쓸 때 나중 것이 앞엣것을 부분적으로 보완할 거라고 기대했는데, 실제로는 **그 자리를 통째로 가져갔다.** 이런 것은 문서를 읽어도 잘 안 보인다. 안 되는 것을 만나고 나서야 어느 설정이 어느 설정을 덮는지 들여다보게 된다.

## 로그인을 걸었더니 봇이 로그인 화면을 받았다

여기서 이 편의 진짜 이야기가 시작된다.

같은 방식으로 워크플로 도구에도 인증을 걸려고 했다. 관리 화면이 열려 있으면 위험하니 당연한 수순이라고 생각했다.

그런데 그 도구는 **웹훅을 받는다.** 아이폰 단축어가 명세서 글자를 보내는 곳이고, 텔레그램이 새 메시지를 알려 주는 곳이다.

인증을 걸면 어떻게 되나. 단축어가 요청을 보내면 **로그인 화면이 돌아온다.** 단축어는 로그인할 수 없다. 텔레그램도 마찬가지다. 사람이 브라우저로 들어올 때만 성립하는 방식을 기계가 부르는 곳에 걸면, 그 순간 기계는 전부 막힌다.

당연한 이야기인데 걸어 보기 전까지는 생각하지 못했다. **"보안을 걸었다"와 "쓸 수 있다"가 충돌하는 지점이 있다는 것**을 그때 알았다.

## 사람이 쓰는 곳과 기계가 부르는 곳을 갈랐다

그래서 하나로 덮지 않고 나눴다.

|          | 누가 부르나     | 어떻게 지키나                      |
| -------- | ---------- | ---------------------------- |
| 화면·관리 도구 | 사람이 브라우저로  | 앞단에서 인증. 통과해야 서버에 닿는다        |
| 웹훅       | 기계가 프로그램으로 | 앞단 인증 없음. **대신 비밀 헤더를 요구한다** |

웹훅 쪽은 주소를 아는 것만으로는 안 되게 했다. 요청에 약속된 헤더가 실려 있어야 받아 준다. 단축어와 봇은 그 값을 갖고 있고, 지나가다 주소를 발견한 쪽은 갖고 있지 않다.

완벽한 방식은 아니다. 헤더 값이 새면 그걸로 끝이다. 다만 **기계가 부르는 문에는 기계가 통과할 수 있는 자물쇠를 달아야 한다.** 사람용 자물쇠를 달면 문이 잠기는 게 아니라 기능이 멈춘다.

관리 도구 중 하나는 아예 다른 방식으로 뒀다. 그건 원래 다른 인증 시스템 뒤에 있었고, 굳이 옮기지 않았다. 옮기다가 그 도구 자체를 못 쓰게 되면 **고칠 수단까지 함께 잃는다.** 컨테이너를 관리하는 도구를 컨테이너 관리 도구로 재배포하는 상황은 피하고 싶었다.

## 무엇이 열려 있는지 알고 있어야 한다

정리하고 나니 열린 것과 닫힌 것이 이렇게 됐다.

- 공유기 포트: **없음**
- 사람이 쓰는 주소: 인증 뒤. 이메일 하나만
- 기계가 부르는 주소: 열려 있고 **헤더로 확인**
- 그 밖의 것: 집 안에서만

이 목록을 적어 두는 것이 실은 가장 중요한 일이었다. 하나씩 설정할 때는 각각 합리적인데, 몇 달 지나면 **무엇이 왜 열려 있는지 기억나지 않는다.** 기억나지 않는 문은 닫지도 못한다. 닫으면 뭐가 깨질지 모르니까.

그래서 설치 절차와 함께 이 목록을 문서로 남겼다. 새로 뭔가를 열 때마다 여기에 한 줄을 더하고, 왜 열었는지도 적는다.

## 편한 쪽과 안전한 쪽이 다를 때

이 편에서 두 번 결정을 뒤집었다.

한 번은 포트를 여는 대신 터널을 쓴 것이다. 포트를 여는 쪽이 훨씬 간단했다. 다른 한 번은 모든 곳에 인증을 걸려다 기계가 부르는 곳은 빼기로 한 것이다. 전부 거는 쪽이 마음은 편했다.

두 번 다 "더 안전한 쪽"이 답은 아니었다. 첫 번째는 더 안전한 쪽이 맞았고, 두 번째는 **더 안전하게 만들려던 것이 기능을 멈추게 했다.** 보안은 세게 걸수록 좋은 게 아니라 **무엇을 지키려는지 정하고 거기에 맞춰야** 한다는 것을 두 번째에서 배웠다.

지금 이 시스템에서 지키려는 것은 명확하다. 정비 기록에 차량번호와 정비소 정보가 들어 있고, 같은 NAS에 다른 것들도 있다. 사람이 들어오는 문은 좁게, 기계가 들어오는 문은 열되 열쇠를 요구하는 것. 그 정도면 지금 규모에는 맞는다고 봤다.

이제 정비소를 나와서 사진을 찍고, 알림을 확인하고, 필요하면 기록을 바로 넣을 수 있다. 도구가 집 안에 있다는 사실은 그대로지만, 사용하는 순간만큼은 장소에 묶이지 않는다.

돌아보면 AI가 내 생활을 대신한 것은 아니다. 내가 불편한 장면을 설명하면 AI가 코드를 만들고, 나는 실제로 써 보면서 틀린 곳을 고쳤다. 사진을 보낼지 말지, 버튼을 둘지, 무엇을 자동화하지 않을지는 사람이 정했다. **AI가 코드를 썼고, 그 코드가 내 생활의 한 부분을 덜 번거롭게 만들었다.** 이것도 AI로 될까라는 질문에 대한 내 대답은, 생활의 불편을 구체적으로 설명하고 계속 고칠 수 있다면 된다는 쪽이다.

---

## 제작 기록

이 글의 초고 작성과 자료 정리, 그리고 터널·인증 설정과 확인 절차의 문서화에는 Claude Code가 사용됐다. 시리즈의 제목·본문 윤문과 재구성, 게시용 이미지 편집과 Ghost 드래프트 반영에는 ChatGPT(Codex)가 함께했다. 공개 발행 전 전체 내용과 화면은 사람이 직접 검토하고 수정했다. 본문에는 실제 주소와 정책 이름을 쓰지 않았다.