Janela: 로컬 Gemma가 외출하기 좋은 시간과 이유를 알려줍니다
요약
Janela는 사용자에게 최적의 야외 활동 시간대를 알려주는 앱입니다. UV 지수, 체감 온도, 강우 확률 등 다양한 날씨 데이터를 종합하여 0~100점 점수로 '가장 좋은 창문(시간대)'을 제시합니다. Gemma를 활용해 해당 시간대가 왜 최적인지 설명하고 맞춤형 활동 과제까지 제공하는 것이 특징입니다.
핵심 포인트
- UV 지수, 체감 온도 등 복합 데이터를 분석하여 최적의 야외 활동 시간을 제안합니다.
- 하루의 컨디션 변화를 조석처럼 그래프로 시각화하여 직관적으로 보여줍니다.
- Gemma가 해당 시간대의 최적 이유와 '풀밭에 발 디디기' 도전 과제를 제공합니다.
- 달리기, 피크닉 등 다양한 활동별 맞춤형 가이드라인을 제공하는 앱입니다.
이 내용은 Hacktoberfest 2026 오픈소스 AI 챌린지, 1주차: "풀밭에 발을 디디다" 제출물입니다.
내가 만든 것 (What I Built)
브라질 대부분 지역에서 "나중에 달리러 갈게"라는 말은 서리나 눈 때문이 아닙니다. 그것은 정오의 UV 지수 11을 피하고, 오후 2시의 체감 온도 38 °C를 피하며, 거의 매년 여름 오후에 나타나는 오후 5시의 천둥번개를 피하는 것에 관한 것입니다. 날씨 앱에는 이 모든 데이터가 있습니다. 단지 언제 가야 하는지는 알려주지 않습니다.
애니메이션 《너의 초탈한 날씨(Weathering With You)》의 히나는 화창한 창문을 기도할 수 있을지도 모릅니다. 나머지 우리들은 예보를 읽어야 합니다.
Janela (포르투갈어로 '창문'을 의미함)가 이 역할을 해줍니다. 사용자에게 도시, 활동(달리기, 걷기, 자전거 타기, 피크닉, 원예, 또는 광장 체육관에서의 야외 운동), 외부에 머물고 싶은 시간, 그리고 얼마나 많은 날짜를 미리 볼지 입력하면 다음과 같은 답변을 제공합니다:
- 가장 좋은 시간대 창문, 그리고 두 가지 대안이 제시되며, 각각 0–100점 사이의 점수와 체감 온도, UV 지수, 강우 확률 및 풍속으로 평가됩니다.
- 하루의 컨디션 변화를 조석(tide)처럼 그래프로 표시하여, 하루가 언제 열리고 언제 닫히는지 한눈에 볼 수 있습니다.
- 제 개인 노트북에서 구동되는 Gemma가 작성한 짧은 설명이 해당 시간대가 왜 최적인지 알려주며, 밖에 나갔을 때를 위한 작은 "풀밭에 발 디디기(touch grass)" 도전 과제도 제공합니다.
이 앱은 포르투갈어와 영어(영어의 경우 °F 및 mph 사용)로 작동하며, 검색 결과는 공유 가능한 링크가 됩니다.
애니메이션 용어로 본 모든 활동
| 🏃 달리기 (Run) | 🚶 산책 (Walk) | 🚴 자전거 타기 (Bike) |
|---|---|---|
![]() | ![]() | ![]() |
| 체감 온도 10–22 °C. 복장 정보는 포함되지 않음. | Janela가 최적의 시간대를 찾아줍니다. 공원을 찾는 것은 사용자에게 달려 있습니다. | 시원한 시간을 고른 후, 친구들 뒤를 따라 페달을 밟으세요. |
| 🧺 피크닉 (Picnic) | 🌱 원예 (Gardening) | 💪 광장 체육관 (Square gym) |
|---|---|---|
![]() | ![]() | ![]() |
| 체감 온도 18–28 °C. 고쿠가 먹을 만큼 충분히 가져오세요. | 영역 전개(Domain Expansion): 채소 정원. | 청춘의 봄은 06:00부터 시작됩니다. |
라인은 와이어드에 살았습니다. Janela는 가끔 로그아웃이 필요한 나머지 우리들을 위한 것입니다.
데모 (Demo)
제작 과정 (How I Built It)
city + activity ──▶ Spring Boot API ──▶ Open-Meteo (geocoding + hourly forecast)
│
▼
...
Java가 계산하고, Gemma가 설명합니다
코드를 작성하기 전에 제가 세운 규칙은 하나였습니다. 모델이 절대로 시간이나 수학적 계산을 하지 않도록 하는 것입니다. 자바(Java)는 센쿠(Senku)와 같습니다. 과학적인 계산을 담당하죠. Gemma는 그저 결과를 제시할 뿐입니다.
작은 모델들(저는 gemma3:4b를 사용합니다)은 데이터를 친근한 문장으로 바꾸는 데 능숙하지만, 산수 계산에는 약합니다. 만약 제가 Gemma에게
가장 흥미로웠던 부분은 작은 모델이 무엇을 '만들어내지 않도록' 하는 방법을 배우는 것이었습니다. 제가 처음 프롬프트를 보냈을 때 ISO 타임스탬프와 원시 숫자들을 전송했고, Gemma는 2026-10-07T17:00과 같은 형식으로 답했으며, UV 0.6을 "높음(high)"이라고 부르고 창문 #2를 칭찬했습니다.

gemma3:4b가 제가 페이로드(payload)를 사전 처리하기 전에 UV 0.6을 보고 있는 모습.
문제를 해결한 것은 Java에서 해석(interpreting)을 수행하고 모델에게 단순히 재구성(reword)만 하도록 허용한 것이었습니다.
{
"best": {
"rating": "great",
...
- 요일 이름과 시간은 이미 독자의 언어로 형식화되어 있습니다.
- 숫자는 UI에 표시되는 방식대로 반올림되고 변환됩니다(영어의 °F/mph).
- 창문의 품질, 온도, UV, 비는 단어와 함께 제공됩니다(
rating은 점수 옆 화면에 표시되는 것과 같은 단어이며, 여기에comfort, WHO UV 카테고리,rainLevel이 추가됨). 따라서 Gemma가 "더움(hot)", "낮은 확률(low chance)" 또는 "이상적(ideal)"이 무엇을 의미하는지 임의로 결정하지 않습니다. reasons는 그날 전망에 따라 Java에서 이미 계산된 창문의 장점입니다. 프롬프트는 Gemma에게 이 내용을 재구성하도록 지시하며, 자체적인 결론을 내리지 않도록 합니다.- 모델이 점수를 인용하는 경향이 있어 의도적으로 점수는 제외했습니다.
- 순위가 없습니다: 최고의 창문과 하나의 대안은 이름으로 언급됩니다. 왜냐하면 세 개의 순위 목록이 주어졌을 때, Gemma가 순서를 혼동하고 잘못된 것을 칭찬하며 텍스트에 "Rank 2"라고 적었기 때문입니다.
그 후 프롬프트는 제가 테스트에서 목격했던 구체적인 실패 사례들(해변이나 공원을 지어내거나, 이틀 뒤의 창문에 대해 "오늘(today)"이라고 말하거나, JSON 필드 이름을 텍스트에 쓰거나, 33°C 오후를 "쾌적하다(pleasant)"고 묘사하는 것)을 금지했습니다.
프롬프트는 보장이 아닌 요청이므로, Java가 답변을 읽은 후 보여줍니다. 어떤 경우든 12시간 시계, 필드 이름, 가상의 해변, 더운 시간대의 '쾌적함', 좋은 날씨의 '이상적' 등의 조건이나 누락된 🌿 라인이 있으면 답변이 거부되고, Gemma는 오류가 발생한 문제로 다시 시도합니다. 보통은 수정하며, 제 노트북에서는 재시도에 2~4초가 소요됩니다.
만약 두 번째 시도에서도 규칙을 위반하거나, Ollama가 꺼져 있거나 느릴 경우(30초 타임아웃), 템플릿이 텍스트를 작성하고 UI는 이를 가장하는 대신 그렇게 표시합니다.
스택 (Stack)
- 백엔드: Java 21, Spring Boot 4, Ollama 스타터가 적용된 Spring AI 2.0, 클린 아키텍처(사용 사례는 프레임워크 독립적), Spring Framework 7을 사용한 API 버전 관리, Caffeine 캐시, OpenAPI 문서
- 모델: Ollama를 통한
gemma3:4b, 환경 변수 하나로 교체 가능 - 날씨: Open-Meteo 예보 및 지오코딩(개방 데이터, 키 불필요)
- 프론트엔드: React 19, TypeScript, Vite, TanStack Query, Tailwind 4, Base UI의 shadcn/ui, 손으로 그린 SVG 조수 간만
오픈 혁신이 여기서 중요한 이유 (Why open innovation matters here)
- 노트북에서 실행됩니다. API 키도, 계정도, 질문당 비용도 없습니다. 누구나 클론하여 세 개의 명령어로 작동시킬 수 있습니다.
- 일상생활 패턴은 사용자에게 머무릅니다. 어디에 살고 언제 외출하는지는 제가 AI 클라우드에 보내고 싶지 않은 바로 그 종류의 데이터입니다. Gemma 로컬을 사용하면 이 데이터가 기기를 벗어나지 않습니다. 솔직히 말하자면: 예보는 Open-Meteo의 개방 API에서 나오기 때문에, 그 요청은 나갑니다(좌표만, 프로필 정보 없음).
- 변수 하나로 모델 교체 가능.
OLLAMA_MODEL=gemma3:12b를 설정하면 끝입니다. 오픈 웨이트는 앱이 특정 공급업체의 가격 책정이나 지원 중단 일정에 묶이지 않음을 의미합니다. - AI 없이도 작동합니다. AI가 설명만 할 뿐 결정하지 않기 때문에, AI 기능을 끄더라도 답변 자체를 잃지는 않습니다. 단지 멋진 문장들만 사라질 뿐입니다.
경품 카테고리 (Prize Categories)
Gemma의 최적 활용 사례. Gemma 3 (4B)는 Ollama를 통해 로컬에서 실행되며, 포르투갈어 또는 영어로 모든 추천 내용을 작성합니다. 이 프로젝트는 작은 오픈 모델이 잘하는 것(언어)에 초점을 맞추고, 그렇지 않은 것(수학 및 의사 결정)과는 거리를 둡니다.
코드
GitHub logo mauricioandrade / janela
🌿 풀밭에 손을 대는 당신의 시간(window)을 찾으세요. 열, 자외선 지수, 비를 기반으로 달리기, 산책 또는 사이클링에 가장 좋은 야외 시간을 추천해 주며 — 로컬 오픈 가중치 모델(Ollama를 통한 Gemma)이 설명합니다. Java 21 + Spring AI. Hacktoberfest 2026을 위해 제작되었습니다.
🌿 Janela
풀밭에 손을 대는 당신의 시간(window)을 찾으세요.
Janela (포르투갈어로 '창문'이라는 뜻)는 열대 기후에서 실제로 중요한 요소들, 즉 열, 자외선 지수, 오후 폭풍우, 바람 등을 기반으로 향후 며칠 동안 야외 활동(달리기, 산책, 사이클링, 피크닉, 원예 작업, 광장의 야외 체육관 운동 등)에 가장 좋은 시간대를 찾아줍니다.
그리고 **로컬 오픈 가중치 모델(Ollama를 통한 Gemma)**이 이 수치들을 짧고 인간적인 추천 내용과 작은
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기





