날씨 앱이 하루 종일 '비 60%'라고 하길래, TabPFN으로 잔디밭에 나갈 최적의 시간을 알려주는 앱을 만들었습니다.
요약
사용자가 원하는 활동을 기반으로 오늘 외출하기 가장 좋은 시간을 알려주는 'Touch Grass' 앱을 개발했습니다. TabPFN으로 날씨 데이터를 예측하고, 코드가 최적의 시간대를 계산하며, Ollama와 ElevenLabs를 이용해 음성 브리핑을 생성합니다.
핵심 포인트
- TabPFN을 활용하여 12시간 동안의 강우 확률과 기온을 예측함.
- 사용자 활동에 맞춰 최적/최악 시간을 알려주는 아침 브리핑 기능을 구현함.
- Ollama와 ElevenLabs를 결합해 음성 기반의 직관적인 사용자 경험을 제공함.
이것은 Hacktoberfest Open-Source AI Challenge: Touch Grass에 제출하는 작품입니다.

제가 만든 것 (What I Built)
라가스(Lagos)에서 휴대폰 날씨 앱을 보면 하루 종일 "비 60%"라고 표시되다가, 오후 4시까지는 햇볕이 비치고 5시부터는 폭우가 쏟아집니다. 그래서 하루 종일 집에 머물거나, 밖에 나가서 흠뻑 젖거나 둘 중 하나를 선택해야 합니다.
오늘 외출할까요? (Go Out Today?) 는 단 하나의 질문에 답하는 아침 브리핑입니다: 내가 하고 싶은 활동을 위해 오늘 가장 좋은 시간은 언제인가? 사용자는 활동(산책, 달리기, 축구, 시장 구경, 빨래 건조, 통근, 피크닉, 만남)을 선택하고 큰 재생 버튼을 누르면, 음성으로 다음과 같은 내용이 전달됩니다.
"피크닉하기 가장 좋은 시간은 오후 3시부터 6시 사이이며 비가 올 확률은 최대 29%입니다. 이 시간을 벗어나면 정오 무렵에 비가 올 확률이 54%로 최고조에 달합니다."
그리고는 노트북을 닫고 나갑니다. 이것이 바로 "Touch Grass"의 전체 아이디어입니다: 화면 시간이 가장 짧아야 합니다. 오전 5시 45분에 예약된 작업(scheduled job)이 브리핑을 생성하므로, 아침 6시에 바로 재생됩니다.
작동 방식은 다음과 같습니다:
- TabPFN은 지난 3년간의 시간별 라가스 날씨 데이터를 분석하여 향후 12시간 동안의 강우 확률과 기온을 예측합니다.
- **코드(Code)**는 사실 관계를 계산해냅니다: 최적의 시간대, 피해야 할 시간대, 그리고 더위 여부 등을 파악합니다.
- Ollama를 통한 로컬 Qwen 모델은 이 사실들을 두세 개의 평이한 문장으로 변환합니다.
- ElevenLabs가 이를 소리 내어 읽어주며, 단어 단위로 하이라이트되는 자막을 제공합니다.
TabPFN과 모델은 제 노트북(Intel UHD 620, RAM 16GB, GPU 없음)에서 실행됩니다.
이 앱은 오늘 스크린에서 벗어나 잔디밭에 나가고 싶은 모든 사람을 위한 것입니다. 산책, 달리기, 소풍, 친구들과의 만남 또는 남자들끼리의 축구 등 어떤 활동이든 상관없습니다. 날씨 차트를 읽거나 '비 60%'가 무엇을 의미하는지 추측할 필요가 없습니다. 재생 버튼을 누르고 몇 초 동안 듣기만 하면, 외출하기 가장 좋은 시간과 피해야 할 시간을 알려줍니다. 그리고 노트북을 닫고 나갑니다.
저는 이 앱을 저 자신을 위해 먼저 만들었습니다. 앱이 '60%'라고 말했기 때문에 하루 종일 집에 머무는 사람이 바로 저였거든요.
데모 (Demo)
영상 초반부(cold-start part)는 속도 조절되어 있습니다(화면에 표시됨). 음성 부분은 실시간이며, 소리를 켜고 들어보세요.
하늘은 하루의 실제 시간에 맞춰 변화합니다: 일출 때는 주황색, 낮에는 파란색, 밤에는 달과 별이 있는 어두운 색입니다. 잔디밭에 있는 캐릭터는 활동에 따라 바뀝니다. 그래서 건조한 옷을 널면 빨랫줄이 생기고, 소풍 장소에서는 담요가 깔립니다.

야외 활동하기 (Taking it outside)
10월 10일 토요일. 친구가 생일을 기념해서 파티에 가야 했습니다. 아침에 저는 **만남(Hangout)**을 선택하고 재생 버튼을 눌렀습니다:
하루가 좋다는 것이 증거는 아닙니다. 9월 30일(아래)은 그렇지 않았습니다. 하지만 토요일에는, 추측하는 대신 가장 적절한 두 시간대에 외출할 이유를 제공했습니다.
동료의 의견
아직 아무도 사용해 보지 않았지만, 직장 동료에게 보여주었습니다. 그녀는 침대에서 제대로 일어나기도 전에 하루 일과에 대한 정보를 듣는 아이디어가 마음에 들었다고 했습니다. 앱을 열지 않고도 예보와 외출할 수 있는 시간을 알게 되는 것이요.
그러다 그녀는 진짜 기능을 발견했습니다. 만약 밖에 나가기 싫은 기분이거나, '오늘 외출하기?'가 계획했던 시간에 비를 보여준다면, 그것만으로 완벽한 핑계가 됩니다. 저는 그 부분을 설계하지 않았지만, 솔직히 말해서: 이 간결한 아이디어는 양방향으로 작동합니다.
코드
GitHub logo G00dS0ul-Hackerton / w1-go-out-today
라고스(Lagos) 사람들에게 오늘 외부에 있을 최적의 시간을 알려주는 지역 기반, 음성 우선 아침 브리핑.
w1-go-out-today
라고스(Lagos) 사람들에게 오늘 외부에 있을 최적의 시간을 알려주는 지역 기반, 음성 우선 아침 브리핑.


빠른 시작 (Quick Start)
1. 전제 조건 (Prerequisites)
2. 설정 (Setup)
저장소(repository)를 복제하고 의존성을 설치합니다:
git clone https://github.com/G00dS0ul-Hackerton/w1-go-out-today.git
cd w1-go-out-today
uv sync
.env.example를 .env로 복사하고 설정을 구성합니다:
cp .env.example .env
주요 설정 (Key settings):
ELEVENLABS_API_KEY: ElevenLabs API 키입니다. (오디오에 필요하며, 텍스트만 사용하려면--no-voice를 전달하세요).ELEVENLABS_VOICE_ID: 음성 ID입니다. (기본값:JBFqnCBsd6RMkjVDRZzb- George).ELEVENLABS_MODEL_ID: 모델 ID입니다. (기본값:eleven_flash_v2_5- 무료 티어에서 문자당 0.5 크레딧).TABPFN_TOKEN: TabPFN 토큰입니다. (Windows에서 브라우저 인증 프롬프트를 방지하기 위해 필요합니다).OLLAMA_BASE_URL: Ollama API 엔드포인트입니다. (기본값:http://localhost:11434).OLLAMA_MODEL: 선택된 Ollama 모델입니다. (기본값:qwen2.5-coder:7b).
(참고: 3년간의 시간별 Lagos 날씨 데이터가 data/lagos_weather.csv에 사전 포함되어 있습니다).
3. 아침 브리핑 실행하기 (CLI)
12시간 동안의 데이터를 생성합니다...
Python 3.12를 사용했으며, uv, FastAPI, 그리고 빌드 단계가 없는 순수 HTML/CSS/JS로 구현했습니다. 총 64개의 테스트 케이스가 있으며, 모두 오프라인에서 실행됩니다: TabPFN, Ollama, ElevenLabs는 목업(stubbed) 처리되었습니다.
제작 과정 (How I Built It)
전체 파이프라인은 다음과 같습니다. 최신 날씨 정보와 음성만 인터넷 연결이 필요합니다.
05:45 스케줄 작업 (또는 재생 버튼을 누름)
│
▼
...
1. 데이터: 3년간의 Lagos 날씨
Open-Meteo 아카이브에서 Lagos의 시간별 날씨 데이터를 가져왔습니다(CC BY 4.0): 2023년 10월 1일부터 2026년 9월 30일까지 26,304개 행입니다. 이 데이터에는 온도, 습도, 이슬점, 강수량, 구름 덮개, 기압, 풍속이 포함되어 있습니다. 실제 아침의 경우, CSV 파일이 9월 말에 끝나기 때문에 Open-Meteo의 예보 API에서 최근 몇 일간의 데이터를 추가로 가져옵니다.
2. TabPFN: 모델 학습 없이 예측하기
TabPFN은 테이블을 위한 파운데이션 모델(foundation model)입니다. 행(rows)을 입력하면 예측값(predictions)을 제공하며, 별도로 모델을 학습할 필요가 없습니다. 저는 하나의 분류기(이 시간에 비가 올까?)와 하나의 회귀기(온도)를 사용했으며, '시간 경과'를 특징(feature)으로 사용하여 단일 모델로 12시간 전체를 커버하도록 했습니다.
스스로 점검하기 위해 마지막 30일 (오전 6시에 발행된, 12시간 후의 예보, 360개 행)을 따로 분리하여 두 가지 간단한 추측과 비교했습니다:
- 기후학적 분석 (Climatology): "이 달과 시간대에 정상적인 것은 무엇인가"<br>- 지속성 (Persistence): "다음 몇 시간은 지금과 같을 것이다"
| Model | Temp error (MAE) | Rain AUC (higher is better) | Rain Brier (lower is better) |
|---|---|---|---|
| TabPFN | 0.71 °C | 0.733 | 0.205 |
| ... |
TabPFN은 모든 수치에서 단순한 추측을 능가합니다. 그래서 포스팅 전날, 제가 가장 먼저 실행했어야 할 테스트를 추가했습니다: scikit-learn의 그래디언트 부스트 트리(gradient-boosted trees)를 기본 설정으로, 정확히 동일한 3,000개 행과 같은 특징(feature)을 사용하여 학습시킨 것입니다. 이 트리가 세 수치 모두에서 TabPFN을 근소하게 앞섰습니다. 차이는 30번의 아침에만 (0.02 °C, 0.015 AUC, 0.006 Brier) 작았기 때문에, 저는 패배라기보다는 비김(tie)이라고 부르겠지만, 제가 기대했던 승리는 아니었습니다.
그럼에도 불구하고 TabPFN을 유지하는 이유는 무엇일까요? 아무것도 조정하지 않았습니다. 하이퍼파라미터도 없고, 학습 루프도 없습니다: 한 번의 적합화(fit)만으로 처음부터 강력한 트리 모델에 근접한 성능을 보여주었습니다. 또한 즉시 확률을 제공하며, 이 프로젝트는
실제 하루를 확인해 봤습니다. 9월 30일에는 오전 10시부터 오후 2시까지 습한 날씨(72–81%)라고 했지만 실제로 오지 않았고, 비는 오후 5시에만 내렸는데 이때는 23%라고 되어 있었습니다. 기온도 평균적으로 0.8 °C 정도 틀렸습니다. 바로 이런 이유 때문에 예보는 항상 '강수 확률'이라고 하고 절대 '비가 올 것이다'라고 하지 않습니다.
Windows에서 문제가 발생한 부분: 제 Windows 사용자 이름에 이모지가 포함되어 있습니다(묻지 마세요). 그 이모지가 TabPFN이 OpenBLAS 의존성을 로드하는 방식을 망가뜨렸습니다. 그러자 TabPFN의 첫 실행 라이선스 로그인이 WinError 10038로 충돌했는데, 이는 Mac과 Linux에서만 작동하는 방식으로 키보드를 읽기 때문입니다. 해결책은 .env 파일에 TABPFN_TOKEN을 넣고 TabPFN이 시작되기 전에 로드하는 것이었습니다.
3. Ollama: 코드가 사실을 결정하고, 모델은 문장으로만 말한다
저는 두 개의 로컬 모델인 qwen2.5:7b와 qwen2.5-coder:7b를 테스트하며, 각각에게 동일한 실제 예보 데이터를 6번씩 제공했습니다. 저는 모든 답변을 가드(guard)로 검사했는데, 숫자는 반드시 예보에서 나와야 하고, '강수 확률'이라고 말해야 하며('비가 올 것이다'는 안 되고), 길이가 2~3문장이어야 했습니다.
qwen2.5:7b는 6번 중 2번 통과했습니다. 대부분의 답변은 한 문장이었고, 프롬프트에서 제시한 열(heat) 임계값인
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기