매일 아침 LeetCode와 시스템 디자인 요약본을 문자로 보내주는 AI 에이전트를 만든 방법
요약
Obsidian 노트를 기반으로 매일 아침 iMessage로 학습 요약본을 보내주는 자동화 스크립트와 대화형 학습 에이전트 구축 방법을 소개합니다. Gemini API와 AppleScript를 활용하여 별도의 앱 실행 없이도 효율적인 복습 환경을 조성하는 기술적 과정을 다룹니다.
핵심 포인트
- Obsidian의 마크다운 파일을 Gemini API로 요약하여 iMessage로 자동 전송
- 심볼릭 링크를 활용해 Obsidian 노트를 AI 에이전트의 데이터 소스로 직접 연결
- AppleScript를 이용한 macOS 내장 메시지 앱 자동화 구현
- 무작위 주제 선정 및 프롬프트 엔지니어링을 통한 맞춤형 학습 경험 제공
제 문제는 이렇습니다. 무언가를 한 번 공부하면 실제로 그것이 필요한 순간, 보통 면접 중간처럼 너무 늦어버린 시점까지 그것이 존재한다는 사실조차 완전히 잊어버린다는 것입니다. 이미 할 일이 가득한 일상에 또 다른 부담을 주지 않으면서 이 문제를 해결하고 싶었습니다. 그래서 두 가지를 만들었습니다. 첫째, 매일 아침 8시에 실행되어 제가 공부한 모든 내용 중 무작위 주제를 선정하고, iMessage로 일반 텍스트(plain-text) 요약본을 보내주는 자동화 스크립트입니다. 별도의 앱을 열 필요도, 새로운 습관을 만들 필요도 없습니다. 그냥 나타날 뿐입니다. 둘째, Antigravity CLI를 사용하여 언제든 대화할 수 있는 대화형 학습 에이전트입니다. 퀴즈를 내달라고 하면 퀴즈를 내주고, 노트의 빈 부분을 채워달라고 하면 무엇이 빠졌는지 정확히 알려줍니다. 멋진 점은 제가 Obsidian에서 노트를 작성한다는 것인데, 별도의 동기화나 내보내기 과정 없이 심볼릭 링크(symlinks)를 사용하여 AI가 제 실제 Obsidian 파일들을 직접 가리키도록 만들었다는 것입니다. Obsidian에서 수정하면 에이전트가 즉시 확인합니다. 단일 진실 공급원(One source of truth)인 셈이죠. 제가 이것을 어떻게 만들었는지 정확히 알려드리겠습니다.
아침 자동화
스크립트 자체는 간단합니다. 제 Obsidian Vault의 경로를 설정하고, 모든 폴더를 탐색하며, 모든 .md 파일을 리스트로 수집합니다. 그런 다음 random.choice()를 사용하여 하나를 무작위로 선택하고, 그 내용을 읽은 뒤 Gemini에게 무엇을 할지 지시하는 프롬프트(prompt)를 작성합니다: '이 노트를 요약해줘, 일반 텍스트로, 마크다운 없이, 짧게 유지해줘'. API 호출은 Gemini로 직접 이루어지며, 응답은 JSON 형식으로 돌아옵니다. 저는 data["candidates"][0]["content"]["parts"][0]["text"]에서 실제 텍스트를 추출합니다. 그런 다음 macOS의 내장 자동화 언어인 AppleScript를 사용하여 메시지(Messages) 앱이 제 번호로 메시지를 보내도록 합니다. 스크립트를 실행하면 요약본이 iMessage로 도착합니다. 간단하죠. 전체 스크립트는 다음과 같습니다:
import os
import random
import subprocess
import urllib.request
import urllib.error
import json
import time
Obsidian Vault 전체를 자동으로 스캔하여 모든 마크다운 노트를 찾음
vault_path = " /Users/your-username/Documents/Obsidian Vault "
notes = []
for root , dirs , files in os . walk ( vault_path ):
for file in files :
if file . endswith ( " .md " ):
notes . append ( os . path .
join ( root , file )) if not notes : print ( " No notes found in Obsidian vault " ) exit ( 1 ) # 무작위로 노트 하나 선택 picked = random . choice ( notes ) note_name = os . path . basename ( picked ) with open ( picked , " r " ) as f : content = f . read () # 프롬프트 구성 prompt = f """ 당신은 MSCS (컴퓨터 과학 석사) 학생을 위한 시스템 디자인 (System Design) 학습 보조 도구입니다. 아래는 " { note_name } " 에 대한 학생의 개인 노트입니다. 이를 읽고 마크다운 (Markdown), 별표 (*), 굵게 (Bold), 글머리 기호 없이 일반 텍스트로 간결한 아침 요약본을 작성하세요. 형식은 반드시 다음과 같아야 합니다: TOPIC: <주제 이름> WHAT IT COVERS: 한 줄 개요 KEY CONCEPTS: 1. 첫 번째 개념 2. 두 번째 개념 3. 세 번째 개념 KEY TAKEAWAY: 학생이 반드시 기억해야 할 한 줄 요약 WATCH OUT FOR: 흔히 하는 실수나 까다로운 부분 짧고 명확하게 작성하세요 — 이것은 강의가 아니라 아침 복습용입니다. Notes: { content } """ # 재시도 로직을 포함하여 Gemini API 호출 api_key = os . environ . get ( " GEMINI_API_KEY " ) url = f " https://generativelanguage.googleapis.com/v1beta/models/gemini-3.5-flash:generateContent?key= { api_key } " payload = json . dumps ({ " contents " : [{ " parts " : [{ " text " : prompt }]}] }). encode ( " utf-8 " ) summary = None for attempt in range ( 3 ): try : req = urllib . request . Request ( url , data = payload , headers = { " Content-Type " : " application/json " }, method = " POST " ) with urllib . request . urlopen ( req ) as response : data = json . loads ( response . read ()) summary = data [ " candidates " ][ 0 ][ " content " ][ " parts " ][ 0 ][ " text " ] break except urllib . error . HTTPError as e : if e . code == 429 : print ( f " Rate limited, waiting 30 seconds... (attempt { attempt + 1 } /3) " ) time .
sleep(30)
else:
raise
if not summary:
print("3번의 시도 후 실패했습니다. 나중에 다시 시도하세요.")
exit(1)
iMessage를 통해 전송
imessage_target = "your-imessage-target" # 귀하의 전화번호 또는 Apple ID
applescript = f'''
tell application "Messages"
set targetService to 1st service whose service type = iMessage
set targetBuddy to buddy "{imessage_target}" of targetService
send "{summary}" to targetBuddy
end tell
'''
subprocess.run(["osascript", "-e", applescript])
print("iMessage로 요약본이 전송되었습니다!")
print(summary)
스케줄링을 위해 macOS의 내장 작업 스케줄러인 launchd를 사용했습니다. 실행할 스크립트, 실행 시간, 로그를 저장할 위치라는 세 가지 요소를 기술하는 .plist 파일을 작성하면 됩니다. 해당 파일을 launchd에 로드하면 그 이후의 모든 과정은 launchd가 처리합니다. 다음은 plist 파일입니다:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.
One problem: launchd runs at 8am but my Mac might still be asleep. So I used pmset to schedule an automatic wake at 7:55am every day: sudo pmset repeat wakeorpoweron MTWRFSU 07:55:00 One requirement — the Mac needs to be plugged in and in sleep mode, not fully shut down. Just close the lid at night and you're good. The interactive study agent For the interactive part, I used Antigravity CLI — Google's new agentic coding tool. The idea is simple: instead of asking AI generic questions about system design, I wanted it to know MY notes and quiz me on what I actually studied. Two files make this work. AGENTS.md sits at the root of my project folder. It tells the agent who I am and how to behave — think of it as a letter you write to the AI before the conversation starts. It loads automatically every time I open that folder. SKILL.md lives inside .agents/skills/system-design/
name: system-design-notes
description: 사용자가 시스템 디자인 (system design), HLD (High Level Design), LLD (Low Level Design), DDIA (Designing Data Intensive Applications), 분산 시스템 (distributed systems), 아키텍처 패턴 (architecture patterns)에 대해 묻거나, 공부한 시스템 디자인 주제에 대해 퀴즈를 풀고 싶어 할 때 이 스킬을 사용하세요.
당신은 소프트웨어 엔지니어링 면접을 준비하는 컴퓨터 과학 석사 (MSCS) 과정 학생을 위한 시스템 디자인 학습 파트너입니다. 사용자의 개인 Obsidian 노트는 references/ 폴더에 있습니다:
- references/HLD/ → High Level Design 노트
- references/LLD/ → Low Level Design 노트
- references/DDIA/ → Designing Data Intensive Applications 노트
당신의 일반적인 지식보다 이 노트들을 '진실의 원천 (source of truth)'으로 취급하세요. 퀴즈를 낼 때는:
- 한 번에 하나의 질문만 하세요
- 응답하기 전에 사용자의 답변을 기다리세요
- 사용자의 답변을 노트와 비교하여 구체적인 부족한 점을 지적하세요
- 답변이 어떤 노트/주제에서 나왔는지 알려주세요
부족한 부분을 채워줄 때는:
- 특정 주제에 대한 사용자의 노트에서 무엇이 누락되었거나 내용이 얕은지 지적하세요
- 무엇을 추가해야 할지 제안하세요
이것은 두 부분으로 구성됩니다. 에이전트에게 이 스킬을 언제 활성화해야 하는지 알려주는 '설명 (description)'과, 활성화된 후 어떻게 행동해야 하는지 알려주는 '본문 (body)'입니다. 제가 "consistent hashing에 대해 퀴즈를 내줘"라고 입력하면, Antigravity는 설명을 읽고 일치하는 항목을 찾아 제 노트를 자동으로 컨텍스트 (context)에 로드합니다. 저는 결코 스킬의 이름을 직접 호출하지 않습니다.
폴더 구조:
system-design-study/
├── AGENTS.md
└── .agents/
└── skills/
└── system-design/
├── SKILL.md
└── references/
├── HLD → Obsidian/HLD Concepts
├── LLD → Obsidian/LLD
└── DDIA → Obsidian/DDIA
노트 자체는 심볼릭 링크 (symlinks)를 통해 연결됩니다:
ln -s ~/Documents/Obsidian/Vault/HLD .agents/skills/system-design/references/HLD
이렇게 하면 프로젝트 내부에 실제 Obsidian 폴더를 가리키는 포인터 (pointer)가 생성됩니다. 에이전트는 이 포인터를 통해 내용을 읽습니다. 저는 Obsidian에서 편집합니다. 동일한 파일이며, 항상 최신 상태로 유지되고, 유지보수가 전혀 필요 없습니다. 이제 폴더를 열고 "HLD에 대해 퀴즈를 내줘"라고 입력하면, 일반적인 인터넷 지식이 아닌 저만의 노트를 사용하여 퀴즈를 냅니다.
문제가 된 점
세 가지 요소가 저를 가장 힘들게 했습니다.
첫째, Gemini API가 사용량이 전혀 없는 새 키를 사용했음에도 불구하고 계속해서 429 — Too Many Requests (너무 많은 요청) — 오류를 반환했습니다. 알고 보니 제 키가 Gemini 확장 프로그램이 백그라운드에서 조용히 소모하고 있는 VS Code 프로젝트에 연결되어 있었습니다. 별도의 프로젝트 아래에 새 키를 생성하자 즉시 해결되었습니다. 둘째, Mac의 깨우기(wake) 문제를 해결하는 것이었습니다. launchd를 통해 스크립트를 예약할 수는 있지만, Mac이 잠자기(sleep) 상태라면 실행되지 않습니다. 스크립트가 실행되기 전에 Mac을 깨우기 위해 pmset가 필요했습니다. 그리고 이는 전원이 연결되어 있을 때만 작동합니다. 노트북이 배터리 모드이고 덮개가 닫혀 있다면 아무것도 깨울 수 없습니다. 해결 방법은 간단합니다. 종료하지 말고 대신 덮개만 닫는 것입니다. 하지만 자동화가 왜 전혀 실행되지 않는지 알아내는 데 시간이 좀 걸렸습니다.
현재 저의 아침은 이렇습니다. 일어나서 iMessage를 확인하면 두 개의 요약본이 와 있습니다. 하나는 5개의 무작위 LeetCode 문제와 그 접근 방식이 담긴 것이고, 다른 하나는 제 Obsidian 노트에서 가져온 무작위 시스템 디자인 (System Design) 주제가 담긴 것입니다. 두 개를 모두 읽는 데 2분밖에 걸리지 않습니다. 저는 새로운 것을 배우는 것이 아니라, 이미 공부한 내용을 잊어버리지 않도록 유지하고 있을 뿐입니다. 그것이 핵심입니다.
대화형(interactive) 기능을 위해, 저는 터미널을 열고 다음과 같이 입력합니다: cd ~/Documents/system-design-study agy 그런 다음 그냥 대화하면 됩니다. "HLD(High-Level Design)에 대해 퀴즈를 내줘." "내 DDIA(Designing Data-Intensive Applications) 노트에 어떤 빈틈이 있지?"라고 말이죠. 그러면 에이전트는 실제 제 노트를 사용하여 응답합니다. 마치 제가 쓴 모든 것을 읽은 스터디 파트너가 있는 것과 같습니다.
그럴 만한 가치가 있었냐고요? 네. 하루가 걸렸습니다. 하지만 이 시스템은 제가 아무것도 하지 않아도 매일 아침 실행됩니다. 유일한 유지보수는 LeetCode 문제를 풀 때마다 텍스트 파일에 한 줄을 추가하는 것뿐입니다. 만약 여러분이 MSCS (컴퓨터 과학 석사) 학생이거나 인터뷰를 준비 중이라면, 이 설정은 충분히 가치가 있습니다. AI 에이전트나 macOS 자동화에 대한 사전 지식은 전혀 필요하지 않습니다. AI Studio에서 무료 Gemini API 키를 받고 몇 시간만 투자하면 됩니다. 코드는 매우 직관적이어서 여러분이 공부하는 무엇이든에 맞게 수정할 수 있습니다. Obsidian 보관함(vault)을 다른 마크다운 (markdown) 파일 폴더로 바꾸거나, iMessage 대상을 이메일이나 Telegram으로 변경할 수도 있습니다. 여러분에게 맞는 스케줄에 맞춰 실행해 보세요.
작성된 도구 목록:
- Antigravity 2.0 CLI
- Gemini API (무료 등급)
- Python
- launchd
- pmset
- AppleScript
- Obsidian
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기