feat(flutter): AI 코스 화면 8–10 과 기존 화면 시안 맞춤 #19

Open
ttipo wants to merge 3 commits from feat/ai-course-input into main
Owner

무엇을 · 왜

백엔드 AI 코스 API(#13–#16)를 앱에서 쓸 수 있게 화면 8–10 을 붙였다(설계 docs/design/ai-course.md §14 7단계).
휴대폰에서 확인하다 기존 화면도 디자인 캔버스와 다른 곳이 보여, 화면마다 시안과 대조해 맞췄다.

#18(공연·행사) 위에 쌓여 있다 — #18 을 먼저 머지해 주세요. 이 PR 의 커밋은 두 개다.

1. AI 코스 화면 8–10 (af1a0f2)

  • 기반
    • 첫 실행 때 만든 기기 ID 를 안전 저장소에 두고 X-Device-Id 로 보낸다(비로그인 하루 횟수 기준).
    • 앱 언어를 Accept-Language 로 보내 AI 문구 언어를 맞춘다.
  • 입력(8) — 홈 'AI에게 코스 맡기기'에서 연다.
    • 문장을 1초 멈추면 조건을 해석하고, 줄마다 고칠 수 있다(POST /api/course-conditions).
    • 서버와 같은 조건 규칙을 앱에서도 먼저 본다.
    • 하루 횟수를 다 썼으면 만들지 않고 안내한다(AI_001).
  • 만드는 중(9)
    • 1.5초마다 진행을 조회한다.
    • 나가면 취소한다(차감 없음).
    • 만들던 생성 id 를 기기에 남겨, 앱을 다시 켜거나 AI_004 를 받으면 이어 본다.
  • 결과(10)
    • 사실 값 · 경고 · 이동 · 출처와 AI 생성 표시를 보인다.
    • 바꾸기 후보로 바꿀 수 있다. 한 번에 한 곳만 바꾸고, 하루 횟수는 줄지 않는다.
    • 평가할 수 있다.
    • 다시 만들기는 확인한 뒤 진행하고 하루 횟수가 한 번 준다.
    • 요청 칸과 다시 만들기는 이 기기에서 입력한 생성일 때만 보인다.
  • 시안 맞춤
    • 결과의 코스 제목은 빼고 'AI 추천 코스'와 요약으로 시작한다(사용자 결정).
    • 마스코트 그림(시안 그림과 같은 character.png)을 홈 · 입력 · 만드는 중 · 결과 · 횟수 소진에 넣었다.
  • 공통 오류 화면: 화면 전체를 못 불러왔을 때 그림 · 다시 시도 · 오류 코드와 추적 ID 앞 8자를 보인다.

2. 기존 화면 시안 맞춤 (dd8218f)

  • 공통
    • 화면 제목을 17/24 w700 으로 바꿨다.
    • 전체를 못 불러온 화면(검색 · 행사 목록·상세 · 장소 상세)은 공통 오류 화면을 쓴다.
  • 홈: 카테고리 열 간격 8, '전체 보기' 누르는 칸 44, 반려 장소 줄 글자, 꼬리말 한 문단.
  • 첫 실행: 그림·제목 묶음을 세로 가운데로 옮겼다.
  • 검색: 뒤로 44, 지우기 원 크기·색, 결과 줄 높이, 빈 결과 아이콘 색.
  • 장소 상세
    • 뒤로 버튼 그림자를 없앴다.
    • 이용 안내 이름 칸을 한국어 56 으로 줄이고, 복사·링크를 오른쪽 끝에 붙였다.
    • 소개 '더 보기'와 근처 공연·행사 줄 끝에 꺾쇠를 넣었다.
    • 빠져 있던 단어 단위 줄바꿈을 넣었다.

일부러 다르게 둔 것

  • 예시 문장은 입력이 비었을 때만 보인다. 누르면 쓰던 문장을 바꾸기 때문이다.
  • 시안의 옅은 회색(#8A90A2)은 아이콘에만 쓴다. 글자는 대비 때문에 #6B7180 이다.
  • 강수 줄은 "토요일 비 60%"다(시안 "토요일 오후"). 오전·오후에 걸칠 때의 규칙을 정하면 붙인다.
  • 누르는 칸은 44 를 지킨다(시안 일부 40).

이번에 빼고 다음 PR 로 미룬 것(사용자 결정)

  • 스플래시 · 앱 아이콘(#FF5A60 단색 + 로고)
  • 장소 상세 '○○에서 시작하는 코스 만들기'와 길찾기(네이버 지도)
  • 영어 장소 상세: 1330 줄 · Copy Korean address · 기관명 · 날짜 · 거리 어순 · 언어 버튼
  • 기능이 생기면 붙일 것: 코스로 저장(로그인 뒤) · 지도 미리보기(지도 SDK 뒤) · 홈 비 소식 줄(홈 날씨 API 뒤) · 횟수 소진의 로그인 버튼

확인 방법

  • 커밋마다 따로 빌드했다. af1a0f2 · dd8218f 모두 flutter analyze 경고 0, flutter test 104개 통과.
    • 새 테스트: 화면 흐름(입력 → 만드는 중 → 결과, 바꾸기 · 평가 · 다시 만들기, 횟수 소진, 이어 보기, 실패 · 취소), 조건 규칙, 모델, 바꾸기 계산, 기기 ID, 공통 오류 화면 · 스위치
  • 휴대폰(SM S911N, 백엔드 AI_PROVIDER=fake)에서 모든 화면을 확인했다. 실제 AI 는 부르지 않았다.

영향 범위

  • backend
  • frontend
  • flutter
  • docker / 인프라
  • 규칙 문서(.claude/)

공유 계약: 바뀌지 않는다.

  • 기존 API(/api/course-conditions · /api/course-generations · 남은 횟수)를 그대로 쓴다.
  • 에러 코드도 #13 에서 등록한 AI_001–AI_004 를 그대로 쓴다.
  • 실패 문구는 사전에서만 오고, 화면 분기는 error.code 로 한다.

체크리스트

  • 린트/분석 통과 (Warning 0) · 변경 영역 테스트 통과
  • 주석 한국어, 매직 넘버·하드코딩 문자열 없음
  • 사용자 노출 실패는 모두 에러 코드와 함께 처리 — 문구는 에러 사전, 분기는 error.code(AI_001 · AI_004)
  • 에러 코드를 바꿨다면 npm run sync:error-codes 실행 후 생성 파일까지 커밋 — 바꾸지 않았다
  • 민감정보 미커밋 — 기기 ID 는 기기 안 안전 저장소에만 둔다
  • 로그에 비밀번호·토큰·요청 본문 전체가 남지 않음 — 해당 없음

🤖 Generated with Claude Code

## 무엇을 · 왜 백엔드 AI 코스 API(#13–#16)를 앱에서 쓸 수 있게 화면 8–10 을 붙였다(설계 `docs/design/ai-course.md` §14 7단계). 휴대폰에서 확인하다 기존 화면도 디자인 캔버스와 다른 곳이 보여, 화면마다 시안과 대조해 맞췄다. > **#18(공연·행사) 위에 쌓여 있다 — #18 을 먼저 머지해 주세요.** 이 PR 의 커밋은 두 개다. ### 1. AI 코스 화면 8–10 (`af1a0f2`) - **기반** - 첫 실행 때 만든 기기 ID 를 안전 저장소에 두고 `X-Device-Id` 로 보낸다(비로그인 하루 횟수 기준). - 앱 언어를 `Accept-Language` 로 보내 AI 문구 언어를 맞춘다. - **입력(8)** — 홈 'AI에게 코스 맡기기'에서 연다. - 문장을 1초 멈추면 조건을 해석하고, 줄마다 고칠 수 있다(`POST /api/course-conditions`). - 서버와 같은 조건 규칙을 앱에서도 먼저 본다. - 하루 횟수를 다 썼으면 만들지 않고 안내한다(AI_001). - **만드는 중(9)** - 1.5초마다 진행을 조회한다. - 나가면 취소한다(차감 없음). - 만들던 생성 id 를 기기에 남겨, 앱을 다시 켜거나 AI_004 를 받으면 이어 본다. - **결과(10)** - 사실 값 · 경고 · 이동 · 출처와 AI 생성 표시를 보인다. - 바꾸기 후보로 바꿀 수 있다. 한 번에 한 곳만 바꾸고, 하루 횟수는 줄지 않는다. - 평가할 수 있다. - 다시 만들기는 확인한 뒤 진행하고 하루 횟수가 한 번 준다. - 요청 칸과 다시 만들기는 이 기기에서 입력한 생성일 때만 보인다. - **시안 맞춤** - 결과의 코스 제목은 빼고 'AI 추천 코스'와 요약으로 시작한다(사용자 결정). - 마스코트 그림(시안 그림과 같은 `character.png`)을 홈 · 입력 · 만드는 중 · 결과 · 횟수 소진에 넣었다. - **공통 오류 화면**: 화면 전체를 못 불러왔을 때 그림 · 다시 시도 · 오류 코드와 추적 ID 앞 8자를 보인다. ### 2. 기존 화면 시안 맞춤 (`dd8218f`) - **공통** - 화면 제목을 17/24 w700 으로 바꿨다. - 전체를 못 불러온 화면(검색 · 행사 목록·상세 · 장소 상세)은 공통 오류 화면을 쓴다. - **홈**: 카테고리 열 간격 8, '전체 보기' 누르는 칸 44, 반려 장소 줄 글자, 꼬리말 한 문단. - **첫 실행**: 그림·제목 묶음을 세로 가운데로 옮겼다. - **검색**: 뒤로 44, 지우기 원 크기·색, 결과 줄 높이, 빈 결과 아이콘 색. - **장소 상세** - 뒤로 버튼 그림자를 없앴다. - 이용 안내 이름 칸을 한국어 56 으로 줄이고, 복사·링크를 오른쪽 끝에 붙였다. - 소개 '더 보기'와 근처 공연·행사 줄 끝에 꺾쇠를 넣었다. - 빠져 있던 단어 단위 줄바꿈을 넣었다. ### 일부러 다르게 둔 것 - 예시 문장은 입력이 비었을 때만 보인다. 누르면 쓰던 문장을 바꾸기 때문이다. - 시안의 옅은 회색(#8A90A2)은 아이콘에만 쓴다. 글자는 대비 때문에 #6B7180 이다. - 강수 줄은 "토요일 비 60%"다(시안 "토요일 오후"). 오전·오후에 걸칠 때의 규칙을 정하면 붙인다. - 누르는 칸은 44 를 지킨다(시안 일부 40). ### 이번에 빼고 다음 PR 로 미룬 것(사용자 결정) - 스플래시 · 앱 아이콘(#FF5A60 단색 + 로고) - 장소 상세 '○○에서 시작하는 코스 만들기'와 길찾기(네이버 지도) - 영어 장소 상세: 1330 줄 · Copy Korean address · 기관명 · 날짜 · 거리 어순 · 언어 버튼 - 기능이 생기면 붙일 것: 코스로 저장(로그인 뒤) · 지도 미리보기(지도 SDK 뒤) · 홈 비 소식 줄(홈 날씨 API 뒤) · 횟수 소진의 로그인 버튼 ## 확인 방법 - 커밋마다 따로 빌드했다. `af1a0f2` · `dd8218f` 모두 `flutter analyze` 경고 0, `flutter test` 104개 통과. - 새 테스트: 화면 흐름(입력 → 만드는 중 → 결과, 바꾸기 · 평가 · 다시 만들기, 횟수 소진, 이어 보기, 실패 · 취소), 조건 규칙, 모델, 바꾸기 계산, 기기 ID, 공통 오류 화면 · 스위치 - 휴대폰(SM S911N, 백엔드 `AI_PROVIDER=fake`)에서 모든 화면을 확인했다. 실제 AI 는 부르지 않았다. ## 영향 범위 - [ ] backend - [ ] frontend - [x] flutter - [ ] docker / 인프라 - [ ] 규칙 문서(.claude/) > **공유 계약**: 바뀌지 않는다. > - 기존 API(`/api/course-conditions` · `/api/course-generations` · 남은 횟수)를 그대로 쓴다. > - 에러 코드도 #13 에서 등록한 AI_001–AI_004 를 그대로 쓴다. > - 실패 문구는 사전에서만 오고, 화면 분기는 `error.code` 로 한다. ## 체크리스트 - [x] 린트/분석 통과 (Warning 0) · 변경 영역 테스트 통과 - [x] 주석 한국어, 매직 넘버·하드코딩 문자열 없음 - [x] 사용자 노출 실패는 모두 에러 코드와 함께 처리 — 문구는 에러 사전, 분기는 `error.code`(AI_001 · AI_004) - [ ] 에러 코드를 바꿨다면 `npm run sync:error-codes` 실행 후 생성 파일까지 커밋 — 바꾸지 않았다 - [x] 민감정보 미커밋 — 기기 ID 는 기기 안 안전 저장소에만 둔다 - [x] 로그에 비밀번호·토큰·요청 본문 전체가 남지 않음 — 해당 없음 🤖 Generated with [Claude Code](https://claude.com/claude-code)
ttipo added 3 commits 2026-11-12 15:57:21 +09:00
feat(flutter): 축제·행사 칸을 공연·행사로 바꾸고 카드에 종류와 세로 포스터를 보임
CI / Frontend (lint · type-check · test) (pull_request) Waiting to run
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Waiting to run
CI (Flutter) / Flutter (analyze · test) (pull_request) Failing after 22m20s
CI / Backend (lint · test · e2e · build) (pull_request) Has started running
8e53974c3f
KOPIS 공연이 들어온 뒤 홈 '이번 주말' 칸의 대부분이 공연이 되었다.
'축제·행사'라는 이름이면 축제 목록으로 오해하기 쉬워 '공연·행사'로 바꿨다
(이번 주말 · 다가오는 · 장소 상세 근처 · 빈 문구 · 홈 카테고리 칸, 영어 Shows & events).

- 카드 아래 줄 앞에 종류(공연 · 축제 · 행사 · 전시)를 굵게 보인다. 배지는 쓰지 않는다
- 포스터가 대부분 세로(A판)라 썸네일을 5:7 로 보인다(홈 120×168, 세로 목록 60×84).
  공공누리 3유형 사진은 그대로 자르지 않는다

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
백엔드 AI 코스 API(4–6단계)를 앱에서 쓸 수 있게 화면 8–10 을 붙였다(설계 ai-course §14 7단계).

- 기반: 첫 실행 때 만든 기기 ID 를 안전 저장소에 두고 X-Device-Id 로 보낸다(비로그인 하루 횟수 기준).
  앱 언어를 Accept-Language 로 보내 AI 문구 언어를 맞춘다
- 홈 'AI에게 코스 맡기기' → 입력(8): 문장을 1초 멈추면 조건을 해석해 줄마다 채우고 고칠 수 있다.
  서버와 같은 조건 규칙을 앱에서도 먼저 본다. 하루 횟수를 다 썼으면 만들지 않고 안내한다
- 만드는 중(9): 1.5초마다 진행을 조회한다. 나가면 취소하고(차감 없음), 만들던 생성 id 를 남겨
  앱을 다시 켜거나 AI_004 를 받으면 이어 본다
- 결과(10): 사실 값 · 경고 · 이동 · 바꾸기 후보(한 번에 한 곳, 횟수 안 듦) · 평가 · 다시 만들기(확인 뒤 차감) ·
  출처와 AI 생성 표시. 요청 칸과 다시 만들기는 이 기기에서 입력한 생성일 때만 보인다
- 디자인 캔버스와 맞춤: 결과의 코스 제목은 빼고 'AI 추천 코스'와 요약으로 시작한다(사용자 결정).
  마스코트 그림을 홈 · 입력 · 만드는 중 · 결과 · 횟수 소진에 넣었다
- 화면 전체를 못 불러왔을 때의 공통 오류 화면(그림 · 다시 시도 · 오류 코드와 추적 ID)을 만들어 만드는 중 화면에 쓴다

코스로 저장 · 지도 미리보기 · 홈의 비 소식 줄 · 횟수 소진의 로그인 버튼은 그 기능이 생기면 붙인다.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
style(flutter): 홈·검색·첫 실행·장소 상세를 디자인 시안에 맞춤
CI (Flutter) / Flutter (analyze · test) (pull_request) Waiting to run
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Waiting to run
CI / Backend (lint · test · e2e · build) (pull_request) Waiting to run
CI / Frontend (lint · type-check · test) (pull_request) Waiting to run
dd8218f428
휴대폰에서 시안과 다르게 보이는 곳이 있어 화면마다 디자인 캔버스와 대조했다.
데이터나 기능이 없는 칸(배너 · 검색 축제 탭 · 정렬 · 로그인 · 지도 등)은 그대로 두고, 지금 맞출 수 있는 것만 고쳤다.

- 공통: 화면 제목 17/24 w700. 전체를 못 불러온 화면(검색 · 행사 목록·상세 · 장소 상세)은 공통 오류 화면으로
- 홈: 카테고리 열 간격 8, '전체 보기' 누르는 칸 44, 반려 장소 줄 글자 크기, 꼬리말 출처와 안내를 한 문단으로
- 첫 실행: 그림·제목 묶음을 세로 가운데로, 언어 · 지역 고르기 버튼의 탭 영역을 보이는 크기로
- 검색: 뒤로 44, 지우기 원 크기·색, 결과 셋째 줄 높이, 빈 결과 아이콘 색
- 장소 상세: 뒤로 버튼 그림자 없음, 이용 안내 이름 칸(한국어 56), 복사·링크를 오른쪽 끝에,
  소개 '더 보기'에 꺾쇠, 근처 공연·행사 줄 끝 꺾쇠, 빠져 있던 단어 단위 줄바꿈(행사 이름 · 한눈에 보기)

누르는 칸은 44 를 지키고(시안 일부 40), 시안의 옅은 회색은 아이콘에만 쓴다(글자는 대비 때문에 한 단계 진하게).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Some checks are pending
CI (Flutter) / Flutter (analyze · test) (pull_request) Waiting to run
CI / 에러 코드 SSOT 동기화 검사 (pull_request) Waiting to run
CI / Backend (lint · test · e2e · build) (pull_request) Waiting to run
CI / Frontend (lint · type-check · test) (pull_request) Waiting to run
This pull request can be merged automatically.
You are not authorized to merge this pull request.
View command line instructions

Checkout

From your project repository, check out a new branch and test the changes.
git fetch -u origin feat/ai-course-input:feat/ai-course-input
git checkout feat/ai-course-input
Sign in to join this conversation.
No Reviewers
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: ttipo/wandergo#19