사례 연구 3: 개인 자동화 유틸리티
아이디어
순전히 이기적인 것: 매일 아침 그날의 캘린더 일정과 날씨를 가져와, 한 줄 요약으로 포맷하고, 개인 텔레그램 채팅으로 보내는 스크립트. 핵심은 커피 전에 앱 세 개를 여는 것을 그만두는 것이었다.
스펙
내 시간대로 오전 7시에 돌아가는 예약 작업. 내 캘린더에서
오늘의 일정을 읽고, 내 도시의 예보를 가져오고, 이런 텔레그램
메시지 하나를 보낸다: "오늘 일정 3개, 첫 일정 9:30. 최고 24C,
오후 4시 이후 비." 어떤 소스가 실패하면, 가진 것이라도 보내고
무엇이 빠졌는지 메모하라.
그 마지막 문장 — 충돌하는 대신 우아하게 성능 저하시키기 — 는 명시적으로 요청해야 하는 종류의 동작이다. AI는 그것을 가정하지 않는다. 말하지 않으면, 모델이 기본으로 손을 뻗는 것은 "에러 시 throw"이고, 오전 7시 cron 작업에서 그것은 조용한 아침과 왜 그런지에 대한 단서 부재를 뜻한다.
스택
단일 예약 서버리스 함수(Cron으로 트리거되는 Worker)라, 계속 돌려둘 머신이 없다. 전체가 파일 하나에 스케줄 하나다. 개인 유틸리티에서 이것은 들리는 것보다 더 중요하다: 보살펴야 할 서버가 있는 무엇이든 결국 당신이 결제를 잊어버릴 것이고, 그러면 프로젝트는 실패가 아니라 방치로 죽는다.
핵심 프롬프트
Asia/Seoul 오전 7시에 cron으로 트리거되는 Cloudflare Worker를
작성하라. 날씨 API와 캘린더 API를 호출하고(두 토큰 다 비밀로
제공하겠다), 한 줄 요약을 만들어, Telegram Bot API로 POST한다.
각 외부 호출을 try/catch로 감싸서 한 번의 실패가 메시지를
죽이지 않게. 모든 토큰을 env에서 읽어라.
오전 7시를 기다리지 않고 문구를 반복 개선하고 싶었을 때:
수동 트리거를 추가하라: Worker가 GET 요청과 ?test=1 쿼리
파라미터로 호출되면, 같은 로직을 즉시 돌리고 메시지를 보내는
대신 그 텍스트를 응답으로 반환하라. 나만 트리거할 수 있도록
이걸 비밀 토큰 뒤에 두어라.
그 테스트 트리거가 우리를 잔혹한 피드백 루프에서 구해줬다 — 하루에 한 번이 아니라 원할 때 출력을 볼 수 있었다. 이것은 훔칠 가치가 있는 일반적인 수다: 코드가 스케줄로 돌아갈 때면 언제든, 시계를 기다리기로 약속하기 전에 지금 온디맨드로 돌릴 방법을 스스로 만들어 두어라.
장애물
텔레그램 메시지는 도착했지만, 시간이 틀렸다: 일정이 한국 시간이 아니라 UTC로 표시됐다. 날씨는 괜찮았다. 우리는 그것을 분리했다:
캘린더 시간이 9시간 어긋난다 — Asia/Seoul이 아니라 UTC를
표시한다. 날씨 시간("오후 4시 이후 비")은 정확하다. 둘 다
이렇게 포맷한다: [붙여넣음]. 캘린더 포맷팅만 고치고 날씨 경로는
왜 이미 맞았는지 알려달라.
AI는 날씨 API가 이미 현지화된 문자열을 반환하는 반면, 캘린더 API는 우리가 그대로 출력하던 UTC 타임스탬프를 반환한다고 설명했다. 캘린더 포맷팅 단계에 단일 시간대 변환을 추가했다. 수정을 "캘린더 경로만"으로 범위 좁힌 것이 AI가 멀쩡히 동작하던 날씨 코드를 다시 쓰는 것을 막았다 — AI 수정이 멀쩡하던 것을 깨뜨리는 흔한 방식이다. 그 프롬프트의 후반부 — "날씨 경로는 왜 이미 맞았는지 알려달라" — 는 두 가지 일을 했다: 추측이 아니라 실제 근본 원인을 알려줬고, AI가 그 차이를 분명히 표현하게 강제해서 그 수정이 두 경로를 하나의 깨진 것으로 실수로 "통합"하지 않게 했다.
출시
여기서 "출시"는 그저 Worker를 배포하고, cron 스케줄을 설정하고, API 토큰을 암호화된 비밀로 추가하는 것을 뜻했다. 우리는 ?test=1 엔드포인트를 몇 번 쳐서 메시지가 잘 읽히는지 확인한 뒤, 그대로 두었다. 그 이후로 매일 아침 돌아가고 있다 — 그리고 우아한 성능 저하 줄은 한 달 뒤 날씨 API에 장애가 났을 때 그 값어치를 증명했는데, 메시지는 여전히 도착했고 단지 예보만 빠졌을 뿐이었다.