
- kakago: 3000
- connect-b: 3001

## 인프라 스택

Cloudflare → Caddy (자동 인증서) → PM2 (fork mode) → Node.js standalone → PostgreSQL native (앱별 user/db 분리).

## 새 프로젝트 추가 시 적용

새 풀스택 앱을 같은 서버에 올릴 때 이 패턴을 그대로 복제: `<app>/`, `<app>-shared/`, `<app>-releases/` 3중 구조 + 신규 포트 + Caddy 블록 + PostgreSQL 별도 user/db.

## 관련 메모

- [[user-lucas-connect-b]]
- [[project-connect-b]]
---
name: project-sea-and-catch
description: Sea & Catch (낚시가자) — 조석·물때·바다날씨 낚시 정보 안드로이드 앱 (신규)
metadata: 
  node_type: memory
  type: project
  originSessionId: da0c2b9e-e298-45b5-b639-4b08f1603a96
---

낚시인용 조석예보·물때표·바다날씨 앱. 참고 앱은 "물때표"(`kr.co.atcultures.moontides`).

- 영문 **Sea & Catch** / 국문 **낚시가자**. 목표: 플레이스토어 정식 출시.
- 위치: `~/Android-app/SeaAndCatch`. 2026-06-05 브레인스토밍→설계→Phase 0 시작.
- GitHub: `https://github.com/Lucas-boy-ai/-SeaAndCatch` (origin/main, 저장소명 앞에 하이픈 `-` 주의). credential store 토큰으로 push. **사용자 요청: 커밋할 때 함께 push해 백업 동기화.**
- 스택: **Capacitor 7 + React/TS** (사용자 선택, DailyPiece 패턴 재사용). 백엔드는 **경량 Node 프록시**(예정 `sea.lucas-ai.cc`, 로컬 포트 8097). Express 5.2.1 + TS 6.0.3 + undici + vitest.
- MVP 범위: 조석·물때·바다날씨 4탭(오늘/물때표/바다날씨/내 지점). **조황정보는 제외**(공공 API 없음, 출시 후 크라우드소싱/제휴 결정).
- 데이터 소스: KHOA 바다누리(조석/조위/수온) + 기상청 공공데이터포털(풍속/파고 예보). **API 키는 프록시 .env에만**, 앱에 미포함.

**핵심 리스크(설계 §5)**: R1 물때는 단일 음력 공식이 아니라 지역별 체계차(서해식/남해식)가 있어 KHOA 고조/저조·조차에서 도출해 교정해야 함. R2 낚시인은 관측이 아니라 예보를 원함 — 기상청 단기예보 파고(WAV) 외해 커버리지 검증 필요. R3 웹 검증 도구가 세션에서 죽어 실제 KHOA/기상청 응답 스키마 미확인 → Phase 0 Task 6~7에서 실데이터로 확정(추측 필드명 금지).

**진행 상태(2026-06-05)**: Phase 0 Task 1~5 완료. 7/7 vitest 통과. **프록시 배포 완료** — `sea.lucas-ai.cc`(Caddy 자동 TLS) → pm2 `sea-proxy`(fork, 포트 8097), cwd `~/Android-app/SeaAndCatch/proxy`, `.env`에 data.go.kr 키. `/health` 200 확인. 배포절차는 `proxy/DEPLOY.md`.

**API 작동 확정(2026-06-05)**: data.go.kr 일반 인증키 1개(계정당 1개, 조석·기상청 **공용**) = `4947cc...4c89f4`(서버 `proxy/.env`). 조석 2종 + 기상청 단기예보 모두 **활용신청 승인 + 실호출 200 확인**.
- **HTTP 500 "Unexpected errors"의 원인 = 엔드포인트 경로 누락**(백엔드 장애 아님). data.go.kr 화면의 "End Point"는 base만; 실제 호출은 **base + 오퍼레이션 경로** 필수. 공식 활용가이드(HWP/docx)의 서비스URL이 정답.
- 조석 고저조: `apis.data.go.kr/1192136/tideFcstHghLw/GetTideFcstHghLwApiService` (params: serviceKey, obsCode 예 DT_0018=군산, reqDate YYYYMMDD, type json/xml).
- 조석 시계열: base `apis.data.go.kr/1192136/tideFcstTime` + 오퍼레이션 경로(가이드 확인). param에 min(분간격).
- 기상청 단기예보: `apis.data.go.kr/1360000/VilageFcstInfoService_2.0/getVilageFcst` (params: serviceKey, base_date, base_time 02/05/08/11/14/17/20/23시, nx, ny, dataType=JSON).
- **응답 스키마 확정**: 조석=obsvtrNm/lot/lat/predcDt("YYYY-MM-DD HH:MM")/predcTdlvVl(조위cm)/extrSe(1오전고조2오전저조3오후고조4오후저조). 기상청=category(TMP/WSD풍속/WAV파고/VEC풍향/SKY...)/fcstDate/fcstTime/fcstValue. 픽스처 `proxy/test/fixtures/khoa-tide-hghlw.json`.
- **R2 확인**: 군산 해안 격자(53,92)에서 WAV(파고)+WSD(풍속) 예보 옴. **수온은 단기예보에 없음**(추후 보완). grid.ts 공식 정확(서울60,127/부산98,76/군산53,92).
- 관측소 목록: HWP에 60+개(DT_0001 인천~). `/api/stations` 정적 소스로 사용. 서해/남해/동해/제주 분류 필요(물때 보정용).

**구현 완료(2026-06-05)**: KHOA·기상청 어댑터 + `/api/tide`(조석 events, multtae는 optional/provisional)·`/api/weather`(base_time 자동선택) 라우트 배포·실호출 검증. 앱 오늘/바다날씨 탭에 실데이터 연결(군산 기본 지점, recharts 그래프). 15/15 테스트. 커밋 073877c, GitHub 백업됨.

**지점검색+디자인 완료(2026-06-05, 커밋 377f830)**: `/api/stations`(관측소 61곳, `proxy/src/data/stations.ts` 좌표 포함). 앱 내지점 탭(이름검색+GPS거리순 Haversine+즐겨찾기), 전역 지점상태(`app/src/lib/store.ts` SpotContext, @capacitor/preferences 영속) → 오늘/바다날씨가 선택지점 추종. **디자인 "Deep Marine"**: Pretendard, 바다 그라데이션 배경, blur depth 카드, 그라데이션 헤딩, 페이지로드 stagger 모션. 사용자 강조: "기존 앱보다 더 좋고 보기 좋게"가 차별화 핵심.

**배포/업데이트 인프라(2026-06-05)**: 테스트 APK는 `https://sea.lucas-ai.cc/dl/seacatch.apk`(프록시 express.static `/dl` → `/home/lucas/.www/sea-dl/`). **앱 내 업데이트 기능**(autoGPS 방식): 매니페스트 `/dl/version.json`{versionCode,versionName,apkUrl,notes,mandatory}, `app/src/lib/version.ts`의 APP_VERSION_CODE와 비교, UpdateBanner가 @capacitor/browser로 APK 열기. **릴리스 절차는 proxy/DEPLOY.md** (build.gradle+version.ts versionCode 동시 증가 → build+sync+assembleDebug → cp APK → version.json 갱신). 현재 **v0.2.0(versionCode 2)**. Android: Java21, SDK `~/Android/Sdk`, `./gradlew assembleDebug`.

**천문/물때/타임라인 완료(2026-06-05, v0.3.0 커밋 2487de7)**: KASI 정부 API는 Forbidden(미신청) → **자체 계산**으로 대체(suncalc 일출몰/월출몰/달위상 + korean-lunar-calendar 음력). 프록시 `/api/astro?lat&lon&date`, `/api/tide`에 물때 주입. **R1 물때 해결**: 표준 물때표 **음력9=1물** 체계, 군산 한 달치 조차로 캘리브레이션(조금=음력7~8·22~23, 사리=삭망 직후), 참고앱과 일치(음력20=12물). 초기 7물때식(음력1=7물)은 틀렸었음. 앱: 오늘 탭=세로 SVG 타임라인(조위곡선+만조/간조+일출몰/월출몰+현재시각+물때/음력/달, 날짜네비), 물때표 탭=월간 달력(사리/조금 색, 클라이언트 음력계산 `app/src/lib/multtae.ts`). 18/18 테스트.

**백로그(`docs/BACKLOG.md`, 2026-06-05)**: 나중에 넣을 것 정리됨. 핵심: ①**낚시지수/낚시하기좋은곳**(사용자 요청) — KHOA 웹 내부 API `khoa.go.kr/khoa/lifeforecast/getFishing2.do?areaCode=1~12&date=YYYYMMDD`, 응답 selectFishing[]{pointName,srtPoint,fishingIndex,fishName,currentSpeed,tideTime,waveHeight,waterTemp,windSpeed}, 좌표없음(기준항 매핑), **비공식API라 리스크**(캐싱+graceful로 부가기능만). ②조류세기%(행안부 실시간조석/조류예보 API). ③**1500 부속항 = 공개 불가**(KHOA 조석표 책자, 공개API 최대 87개 조화상수). ④수온(단기예보 없음). 참고: **KHOA(khoa.go.kr)는 이 서버에서 접속 가능, data.go.kr www는 차단**.

**임의좌표 조석 완료(2026-06-05, v0.4.0 versionCode 6)**: 사용자 핵심 니즈 "내 근처 항" 해결. KHOA 오션그리드 비공식 내부 API(`oceangrid/cmm/chart/pre/selectListModelTableDayData.json`, body `obs_lon/obs_lat/obsCheck=EYS/pre_date`)로 임의 경위도 시간별 zeta→고저조 도출. **`pre_date`는 날짜문자열 아닌 일자-인덱스(0=anchor일 …오늘=index3, +3일 forward)** — 페이지 JS `pre_date:index`로 확인(이전 "6/2 고정"은 index 0이었던 것). **게이트 통과(advisor 요구)**: 12관측소 공식 고저조 vs 모델 zeta 시각, 서·남·제주 대조차(조차≳1.5m) 중앙Δ 12~30분=공식 수준 ✅, 동해 소조차(묵호24cm/후포20cm/포항17cm) Δ94~138분·모델극값 12~17개=노이즈지배 ❌(모델 노이즈바닥 ±0.3m). **전략**: 공식 61항=절대조위(cm,DL)·진실원천, 모델=확장레이어(시각·물때만, zeta는 MSL상대m라 절대cm 미신뢰). **노이즈 가드**(극값>6개 또는 일조차<0.3m → noisy) 발동 시 최근접 공식항 fallback. 프록시 `proxy/src/domain/tideExtrema.ts`(극값+가드)·`adapters/khoaModel.ts`·`domain/nearest.ts`, `/api/tide?lat&lon`(1km격자+6h캐시), TideDay에 source/datum/relativeLevel/noisy/fallbackFrom. 앱 내지점 "📍 현재 위치 조석 보기"(GPS→좌표spot), 오늘탭 출처배지. 24/24 테스트, 라이브확인(인천=model, 묵호=fallback). **부가**: 7일 엔드포인트 조류/수온/염분 forward → 백로그 조류세기·수온 가능. 다음: 국가어항113 지오코딩으로 명명된 항목록(좌표경로 재사용).

**v0.4.1 시각패스(2026-06-05, versionCode 7)**: 사용자 UI 피드백 반영. 테마 밝기 한 단계 업(#06141c→#0b2532, 라이트 전환 아님, "Deep Marine" 유지), **상단 고정 검색바**(`components/TopSearch.tsx`, 모든 탭 sticky — 61관측소 항·지역 검색 + 📍현재위치 GPS좌표 조석), 탭 아이콘 확대(20→27px)+활성 pop, 페이지/드롭 모션·달 floaty·focus glow(prefers-reduced-motion 존중). Playwright 모바일뷰 검증. **참고: 사용자 "끔직하게"=advisor 판독 "큼직하게"(크게), "방패제"=방파제.**

**v0.4.2 조류세기·수온(2026-06-05, versionCode 8)**: KHOA 7일 모델 엔드포인트(`oceangrid/cmm/chart/tidal/selectListModelTableData.json`, zeta 없고 168행=anchor~+6일, current_speed_ms/kn·current_direct(deg)·current_direct_16dir(한글방위)·temperature·salinity). 프록시 `adapters/khoaMarine.ts`(buildMarineDay 순수변환, 쿠키는 khoaModel서 공유)·`routes/current.ts`(`/api/current?lat&lon&date`, 1km격자+6h캐시, 실패시 502→앱 graceful 숨김). 앱 오늘탭 날씨카드에 🌡수온·🌀조류(kn+방위)+조류세기 게이지(그날 max 대비 %, 참고앱 37%식). 26/26 테스트. **MarineHour/MarineDay 타입** proxy↔app 공유.

**방파제 이름 검색(미완, 카카오 토글 대기)**: 사용자가 "방파제 검색" 원함. 경로=카카오 로컬 키워드검색(`dapi.kakao.com/v2/local/search/keyword.json`, `Authorization: KakaoAK {REST_KEY}`)→place_name+좌표→기존 임의좌표 조석경로 재사용. **막힘**: kakago 앱키가 `OPEN_MAP_AND_LOCAL service disabled` → 사용자가 콘솔서 카카오맵/로컬 서비스 ON 하거나 Sea&Catch 전용 REST키 발급 필요. 키 위치: `~/.www/kakago-shared/.env` KAKAO_CLIENT_ID(=REST키, 단 서비스 꺼짐). 입수시 프록시 `/api/place?query=` 라우트(키 은닉+캐싱) 추가. BACKLOG §0.

**v0.5.0 전국 장소검색(2026-06-06, versionCode 9)**: 사용자 핵심 불만 "61개뿐, 1,559개 부속항 따라잡기" 해결. **카카오 로컬 키워드검색**으로 방파제·항·낚시터 이름→좌표→임의좌표 조석. 프록시 `/api/place?query=`(`adapters/kakaoPlaces.ts`, 키 은닉+1h캐시, **공백 AND 폴백**: "고마도 방파제"→0건이면 공백제거→첫단어 재시도). **카카오 키 = connect-b 앱 REST 키 재사용**(kakago 키는 `OPEN_MAP_AND_LOCAL disabled`, connect-b는 켜져있음. 사용자 자기자원, 무료 30만/일, `proxy/.env` KAKAO_REST_KEY, **앱/git 미포함**). 앱 TopSearch가 디바운스 300ms로 호출, 공식항(⚓관측소 태그, 정확 datum) 먼저+카카오 장소(주소) 아래. 28/28 테스트. **탭 아이콘 27→34px(tabbar 74px)** — 사용자 "아직 작음". **내지점 "🔄 업데이트 확인" 버튼**(checkUpdate 수동, "최신입니다✓"/"새버전 받기") — 자동체크는 정상이나 최신이라 배너 안떠서 사용자가 "기능 빠졌나" 오해→상시 가시화. Place 타입 proxy↔app 공유.

**v0.6.0 자동업데이트+조석수치+품질(2026-06-06, versionCode 10)**: ①**autoGPS식 자동 업데이트** — Capacitor 커스텀 네이티브 플러그인 `UpdaterPlugin.java`(cc.lucasai.seacatch, MainActivity registerPlugin, manifest REQUEST_INSTALL_PACKAGES, FileProvider 기존). `downloadAndInstall(url)`이 cacheDir로 APK 스트리밍+`progress` 이벤트(퍼센트)→FileProvider `ACTION_VIEW` 설치 인텐트. `canInstall()`/`openInstallSettings()`(Android8+ 알수없는출처). 앱 `lib/updater.ts`+UpdateBanner: shimmer 진행바+퍼센트+완료시 자동설치, 웹은 Browser.open 폴백, 권한없으면 설정화면. **실기기 검증 필요(설치흐름)**. ②**조석 수치 표시**(사용자 요청): 타임라인 배지에 변화량 ▲/▼(delta), 공식항은 절대cm, 오늘화면 "조차 NNNcm". 모델은 상대(변화량·조차만, datum무관). `domain/levels.ts annotateLevels`, TideEvent.delta+TideDay.rangeCm. ③**조석 품질 개선**: `tideExtrema.cleanExtrema`(prominence<max(0.15,0.12*range) 잔극값 제거+같은타입 합침), `fetchModelTideDay` ±1일 zeta stitch(자정 만조 복구), noisy는 당일구간만 판정. 장환 검증: 6/5 잔극값(14시) 제거+만조00:22 복구, 조차318cm. 28/28 테스트.

**v0.6.1 글씨확대+정확도(2026-06-06, versionCode 11)**: ①전역 글씨 +1.5px(45곳, sed 큰값부터). ②**조석 편향 보정은 근거상 폐기** — advisor 지시로 부호있는 Δ(모델−공식) 8개 대조차항 측정: −68(완도,빠름)~+23(인천,늦음) 흩어짐, 중앙±5분(공식 오라클 대비 이미 양호). 일정 시간보정 불가/과적합(물때표는 ground truth 아님=KHOA 조시차, 추격은 순환논리). 시간미만 간격 파라미터도 미지원(24행 고정=±10~20분 바닥). 대신 ③**공식항 ≤6km snap**(routes/tide: 근접 좌표는 공식 실측 사용, 통영 00:06 만조 복구), ④cleanExtrema prominence 완화(0.12→0.09*range, 과다제거 방지), ⑤**야간 월출 fallback**(astro: 그날 월출 null이면 다음날 첫 월출 표시, 군산 6/6 월출 00:05). 28/28.

**v0.7.0 전국 방파제 데이터셋(2026-06-06, versionCode 12)**: 사용자가 직접 제공한 전국 방파제/선착장 **249곳** 주소를 카카오로 지오코딩(키워드+시군구 매칭으로 동명 오매칭 방지, 13곳은 주소/읍면중심 폴백). `proxy/src/data/breakwaters.ts`(id/name/region/lat/lon/address, 강원49 경북75 울산10 부산16 경남22 전남24 전북9 충남10 경기4 인천12 제주18), `/api/breakwaters?region=`. 앱: TopSearch 즉시 로컬매칭(🛟, 관측소⚓·카카오📍 위), 내지점 "방파제 전체보기" 지역별 collapsible(참고앱 전체지역보기). 좌표→기존 모델 조석 경로. Breakwater 타입 공유.

**v0.7.1 타임라인 자정연결(versionCode 13)**: TideDay에 prevEvent(전날 마지막)·nextEvent(다음날 첫) 극값 추가, 곡선을 [전날→오늘→다음날]로 그려 자정에서 안 끊김 + "어제/내일 HH:MM" 흐린 라벨. 모델은 stitch서, 공식은 이웃일 조회.

**v0.8.0 전국 1,555 지점(2026-06-06, versionCode 14)**: 사용자가 참고앱(물때표 3.3.8) APK를 `/up` 업로드 페이지로 전송 → `res/raw/defaults.json`의 `locations` 1559개 발견(name/name_en/section/lat/lng/tsid/calculated). **IP 고려**: 이름·좌표·지역은 공개 사실 정보라 사용, name_en(영문표기)·tsid는 복제 회피로 제외, 일본 4개 제외 → **1,555개**(서해540 남해814 동해105 제주96). `proxy/src/data/locations.json`(데이터, process.cwd() 로드), `breakwaters.ts`는 로더로 교체. 좌표는 모델 조석 경로. 앱 지역브라우즈를 **해안(서해/남해/동해/제주)**으로 재편, TopSearch 큐레이트🛟 우선+큐레이트≥3이면 카카오 숨김(노이즈 컷). 고마도 34.41(우리 카카오 34.415와 일치)로 검증. 원산/청진(북한) 포함.

**APK 업로드 유틸**: 프록시 `/up?t=토큰`(busboy, 60MB, 진행률 XHR+끊김감지). `.www/sea-dl`엔 없고 `/home/lucas/uploads/`에 저장. **임시** — 전송 끝나면 라우트·파일 제거 예정. 참고앱 APK는 `/home/lucas/uploads/...3.3.8.apk.zip`+`apkx/`에 추출됨.

**v0.9.0 지도 탭(2026-06-06, versionCode 15)**: Leaflet+OSM(키 불필요) `pages/MapView.tsx`. 📍내위치(GPS center), 주변 지점 청록 깃발(circleMarker, 뷰포트 내 최대 300개, 1,553서) 클릭→즉시 선택, 지도 아무곳 탭→임시핀+"이 위치 조석 보기" 확인버튼(임의좌표 경로). TabBar **5탭**(오늘/물때표/지도/바다날씨/내지점, 아이콘 34→29px). map-wrap `isolation:isolate`로 leaflet z-index 가둬 상단검색 안 가림, invalidateSize(120ms). **북한(원산·청진) 제외 → 1,553개**(동해103). circleMarker라 leaflet 아이콘에셋 이슈 없음.

**v0.10.0 타임라인 가독성+초성검색(2026-06-06, versionCode 16)**: ①TideTimeline 천문마커(일출/일몰/월출/월몰)를 **오른쪽**으로 모아 큰글씨(아이콘20px) 카드, 만조/간조 배지는 **왼쪽 두 줄**(시각18px, 레벨/델타15px)로 좌우 분리(겹침 방지). 타임라인 H 520→620. ②**초성 검색** `app/src/lib/hangul.ts`(chosung: 0xAC00 기준 (code-0xAC00)/588, isJamoQuery /^[ㄱ-ㅎ]+$/, matchName=부분일치 또는 초성일치). TopSearch·MySpots에 연결. 위치검색 포커스 시 등록 1,553곳 미리보기(상단 60곳, BROWSE_CAP), 검색 시 초성/부분일치(HIT_CAP 40), 드롭다운 max-height 62vh 스크롤.

**v0.11.0 스크롤 날짜이동+0시구분선(2026-06-06, versionCode 17)**: 사용자 "오늘/내일 버튼 대신 화면 내리며 다음날 이동, 0시에 조차/물때". **오늘 탭을 DaySection 스크롤 리스트로 재구조화**. `components/DaySection.tsx`(지점+날짜 받아 자체 tide/astro fetch, sticky 헤더=0시 구분선에 날짜·요일·물때·음력·조차, 그 아래 TideTimeline, nowHour는 오늘만). `pages/Today.tsx`는 상단 현재 날씨/조류 카드 + DaySection 리스트(초기 3일, IntersectionObserver 센티넬로 1일씩 추가 최대 14일). 어제/오늘/내일 datenav 버튼 제거. **예보 윈도우 실측(advisor 요구)**: data.go.kr tideFcstHghLw는 **1년+ 깊이**(인천 2027-06도 극값4 정상응답) = 공식항 사실상 무제한, **모델(임의좌표)은 pre_date 0~7 = 약 7일**. 모델 지점이 윈도우 초과 시 "모델 예보는 약 7일까지" 인라인 안내. now 라벨 right→center(오른쪽 천문 겹침 회피). Playwright 모바일뷰로 오늘+6/7→6/8 경계(곡선 자정연결) 확인. **실기기 검증 필요**: IntersectionObserver 스크롤/sticky 헤더 webview 동작.

**기록 — 바다낚시지수 공식 API 승인(2026-06-06, 미구현/논의대기)**: 사용자가 data.go.kr **해양수산부 국립해양조사원_바다낚시지수 조회** API를 활용신청→자동승인. 활용기간 2026-06-06~2028-06-06. 이전 BACKLOG의 비공식 KHOA `getFishing2.do` 대신 **공식 안정 API**로 낚시지수 기능 구현 가능. Endpoint base `https://apis.data.go.kr/1192136/fcstFishingv2` + 오퍼레이션 경로(오퍼레이션명 "바다낚시지수", 가이드 HWP 확인 필요 — 조석 API와 같은 1192136 기관이라 base+operation 패턴 동일). 파라미터: serviceKey(URLEncode), type(json), reqDate(YYYYMMDD), gubun(갯바위/선상/방파제 등 구분), pageNo, numOfRows, include, exclude, placeName(지점명 필터). 포맷 JSON+XML. **인증키는 기존 data.go.kr 공용키와 동일**(4947cc...68252d0..., proxy/.env KHOA_SERVICE_KEY, 1192136 기관 공용). 사용자: "지금(예약기능) 작업 끝나면 이야기해보자, 기록만." → 예약 기능 완료 후 별도 논의. 등록 1,553지점과 placeName 매칭 전략 필요. **블로커(2026-06-06)**: 서비스 `1192136/fcstFishingv2`는 살아있음(base 직접호출 404 아닌 500="Unexpected errors"=operation경로 누락 패턴, 조석 API와 동일). 정확한 **오퍼레이션 경로 미상** — Get/get 12개 후보 전부 404. HWP 활용가이드("오픈API 활용가이드_바다낚시지수.hwp")에 있으나 읽기 불가. **이 세션 WebSearch/WebFetch 둘 다 고장**("API Error 400 effort parameter"). → 사용자가 data.go.kr 페이지 "미리보기" 클릭해 생성되는 **샘플 요청 URL**(operation+응답스키마)을 제공해야 진행 가능. 받으면 proxy adapter+route(`/api/fishing`)는 tide/current와 동일 패턴으로 즉시 구현. **해결(2026-06-06)**: 사용자가 HWP 가이드+스크린샷으로 경로 제공 → 오퍼레이션 `GetFcstFishingApiServicev2`(내 추측 GetFcstFishingv2ApiService와 어순 다름). 전체경로 `https://apis.data.go.kr/1192136/fcstFishingv2/GetFcstFishingApiServicev2`. 파라미터: serviceKey, type=json, reqDate(YYYYMMDD), gubun(갯바위/선상 택1), pageNo, numOfRows(max300), include/exclude, placeName(선택). **응답스키마**: body.items.item[]{seafsPstnNm(지점명), lat, lot(경도), predcYmd, predcNoonSeCd(오전/오후), seafsTgfshNm(대상어종: 감성돔/농어/돌돔/우럭/참돔/벵에돔/기타어종/-), tdlvHrCn(물때 예 중조기), min/maxWvhgt(파고m), min/maxWtem(수온℃), min/maxArtmp(기온), min/maxCrsp(조류m/s), min/maxWspd(풍속), totalIndex(5단계: 매우좋음/좋음/보통/나쁨/매우나쁨)}. 갯바위·선상 각 totalCount~1720행/날(약120포인트×어종×오전오후), 7일예측. **통합방식**: 포인트마다 좌표 있으니 사용자 지점 최근접 포인트 매칭. 키=기존 data.go.kr 공용(KHOA_SERVICE_KEY).

**v0.15.0 미뤘던 항목 1·2·3 배포(2026-06-06, versionCode 21)**: ①예약 폼 **지점 검색**(장소 입력→등록1,553 초성/부분일치 드롭다운→선택 시 place+spotId+lat+lon 자동채움→물때 미리보기·조석점프 활성, onFocus로 열림). ②**어종 금어기·금지체장 경고**(`lib/regulations.ts` 큐레이트 24종, 별칭+초성 lookup, REG_DISCLAIMER 참고용 명시, 예약날짜 금어기月이면 🚫배너. 보수적=금지체장 위주, 금어기는 주꾸미/살오징어/대게/꽃게/감성돔/대구/쏘가리만. 웹검색 불가로 법령 미대조=참고용). ③**지도 마커 클러스터링**(leaflet.markercluster, MapView 뷰포트300캡 제거→1,553 전부 줌별 그룹핑, 전국축소 시 지역버블 370/271/143…="여기물때"식). Playwright 웹검증 통과. APK 26.4→26.4MB. **남은 미뤘던 것: ④바다낚시지수(operation경로 블로커) ⑤TTS 음성알람**.

**기록 — TTS 음성알람(항목⑤) 기술제약(2026-06-06)**: 사용자가 "여기물때처럼 알람 음성" 원함. **제약**: @capacitor/local-notifications는 앱 종료 상태서 발화 시각에 JS 미실행 → TTS로 말하기 불가. 가능한 범위: @capacitor-community/text-to-speech로 (a)알림 탭→앱 열릴 때 예약요약 음성, (b)포그라운드 알람 시각 발화, (c)예약 상세에 "음성으로 듣기" 버튼. 완전한 백그라운드 음성알람은 foreground service 등 네이티브 추가작업 필요. → 사용자에게 제약 설명+가능안 선택 받아야 함.

**기록 — "여기물때" 앱 벤치마크 기능(2026-06-06, 예약기능 후 구현 예정)**: 사용자가 경쟁/참고 앱 "여기물때" 스크린샷 4장 제공. 구현 요청 기능: ①**줌 의존 마커 클러스터링** — 지도 축소 시 낚시포인트가 지역별 버블로 그룹핑(개수 표시: 서해380·남해993·동해15 등 색상=빨강 많음/주황 적음), 확대하면 개별 포인트(방파제·선착장명)로 분할. 네이버맵 기반. → 우리 MapView(현재 Leaflet+OSM, 뷰포트 300개 캡)에 **leaflet.markercluster** 적용하면 1,553지점 전부 클러스터로 표현+캡 제거 가능. ②**음성 알람(TTS)** — 알람이 소리내어 읽어줌. → 우리 예약 알람(@capacitor/local-notifications)에 TTS(@capacitor-community/text-to-speech 등) 결합 검토. ③위성/포인트/북마크 레이어 토글. 사용자: "이 기능도 구현하자 작업끝나면" → 예약 기능 완료 후. [[project_sea_and_catch]] 바다낚시지수 공식 API 기록과 함께 후속 논의 대상.

**기록 — 금어기 기능 + nakgo-algo 참고(2026-06-06, 후속 논의)**: 사용자가 GitHub org `https://github.com/orgs/nakgo-algo/repositories` 공유("낚시 금어기능 관련, 좋은거 있으면 우리앱에 추가하자"). 금어기=어종별 법정 포획금지 기간(수산자원관리법). 활용처: 예약 폼에서 어종 선택 시 그 날짜가 금어기면 경고, 또는 어종별 금어기 캘린더 표시. **레포 확인 완료(2026-06-06)**: nakgo-algo=낚고알고, **낚시 규제정보 통합 서비스**(FE React/Vite/Tailwind+Vercel, RN Expo, BE FastAPI/Python). 기능: ①금지구역 지도(폴리곤) ②위반판단(어종+크기→포획가능) ③AI 어종인식(TF.js/MobileNet 사진→어종) ④어종별 금어기·금지체장 ⑤벌금안내 ⑥오류제보 ⑦커뮤니티(posts/comments). **재사용 핵심=규제 데이터셋**(`nakgo-algo-BE/app/services/seed.py`, 공개 수산자원관리법 별표 기반 사실). 데이터모델: FishSpecies{name, min_length(금지체장cm), banned_months(int[]=금어기월), category(바다/민물), fine(벌금)}, Zone{name,type,coordinates(폴리곤 list[list[float]]),period}, Regulation(지역별 오버라이드). 시드 샘플 23종: 우럭23cm[1,2,12] 광어35cm[1,2,3,4,11,12] 감성돔25cm[5,6] 참돔24cm[5,6] 농어30cm[5,6,7] 볼락15cm[4,5] 조피볼락23cm[12,1,2] 놀래미20cm[11,12] 도다리15cm[12,1,2] 대구35cm[1,2,3] 방어30cm[] 갈치18cm[7,8] 고등어21cm[] 삼치30cm[] 참조기15cm[5,6,7] 전갱이15cm[] 문어0[5,6] 쭈꾸미0[5,6,7,8] 배스/붕어/쏘가리/메기/잉어(민물). **차용방침**: seed.py 통째 복사 말고 수산자원관리법 시행령 별표에서 자체 표 작성+이 리스트로 교차검증(물때표 위치데이터와 동일 원칙=공개사실 OK). **우리앱 연계**: 예약 폼 species 필드에 금어기 경고가 최고 적합(저비용·고가치), 지도탭에 금지구역 오버레이, AI어종인식은 차별화되나 고비용(후순위).

**v0.14.0 낚시 예약+알람 완료(2026-06-06, versionCode 20)**: 사용자 요청 신규 기능. 물때표 달력 날짜 탭→하단 시트→예약 폼(어종·장소·출조시각·형태[선상/갯바위/워킹]·금액·선사·연락처·상태[예정/완료/취소]·메모·알람[시각+1주전/3일전/전날/당일 토글]). **SQLite 저장**(@capacitor-community/sqlite 8.1.0, 사용자가 JSON 대신 선택), 웹폴백 jeep-sqlite(2.8.0이 sql.js ^1.11.0로 빌드 → sql.js 1.11.0 핀+`app/public/assets/sql-wasm.wasm` 서빙, 버전 불일치 시 LinkError). **로컬 알림**(@capacitor/local-notifications 8.2.0, POST_NOTIFICATIONS 권한, 예약별 결정적 notifId, 과거 리드 스킵, 수정/삭제 시 취소+재스케줄). 예약 날짜 물때 자동 미리보기, 선사 tel: 전화, 좌표 있으면 "조석 보기" 점프. 파일: `lib/reservationTypes.ts`(순수 헬퍼+vitest 5개)·`lib/db.ts`·`lib/reservations.ts`(리포지토리)·`lib/alarms.ts`·`components/Reservation{Sheet,Form,Detail}.tsx`·`pages/TideTable.tsx`(달력 🎣 인디케이터+날짜탭). 서브에이전트 4그룹 위임. Playwright 웹검증: 생성→영속(새로고침 후 잔존)→상세 통과. **앱에 vitest 도입**(이전엔 proxy만). **APK 5.2MB→26.4MB**(sqlite ABI별 네이티브 .so) — Play Store 출시 전 ABI분할/AAB 필요. **미구현(다음)**: 폼에서 등록지점 검색→좌표 자동채움(현재 장소 자유텍스트라 물때미리보기·조석점프는 좌표 있을 때만), 조과기록. **실기기 검증 필요**: 알림 권한+실제 알람 발화, 네이티브 SQLite 영속, 전화 인텐트.

**여기물때 APK 추출(2026-06-06, `/home/lucas/uploads/yeogi/`)**: 사용자가 "여기물때"(네이티브 Kotlin, Firebase, NaverMap) APK를 /up 업로드(`1780723556593-...100015.apk.zip`). assets에 풍부한 데이터. ①**낚시포인트 확장 완료**: `fishingaddr.json`(2,568 {province,spot,lat,lon}) 중 깔끔한 지명만 필터(UGC/유튜버핸들"...TV"/"(어종)"/주소조각 171개 제외, 0.3km 중복 845 제외, 북한0) → 신규 1,552 병합 → **locations.json 1,553→3,105**(해안은 기존 NN상속, /api/breakwaters 라이브 3105 확인, 앱 재빌드 불필요). 커밋 452ef71. ②**`nofishing.json`=실제 "2026 금어기/금지체장" 36종**{name,ban_period"7.1~7.31",limit_size"18cm",note"항문장"} — **항목2 금어기 데이터 업그레이드 소스**(법령 공개사실, 내 손큐레이트보다 정확). ③**`species.json`=낚시지수 모델 25종**(scoringRules: region매치+1, monthScores[월]0~3, waterTempC범위+1; per-species regions/monthScores/waterTempC/strategy텍스트) — **항목4 대안**(막힌 data.go.kr API 없이 로컬 점수계산 가능, 우리 marine수온 활용). ④**`res/raw/*.m4a`=사전녹음 음성**(tide_high/low, tide_in/out 1~3, sunrise/sunset, _30min/_1hour) — **항목5 음성알람 정체=TTS아닌 알림 커스텀사운드 녹음재생**(앱 꺼져도 동작). 기타: stations/cctv/fishingspots(2518, species포함)/speciesregion. **IP경계**: 금어기(②)=수산자원관리법 공개사실→사용OK. species 점수모델(③ monthScores/strategy)·음성파일(④)=여기물때 독자 콘텐츠→복제 금지, 개념만 차용해 자체 데이터/자체녹음(또는 TTS생성)으로 재구현.

**v0.16.0~0.18.0 미뤘던 5개 처리(2026-06-06)**: ①예약폼 지점검색(v0.15) ②금어기(v0.15→v0.16 2026표 36종 프록시 `/api/regulations`로 이전→v0.18 물때표 달력 아래 "이번달 금어기 N종" 카드로 이동, 예약폼에도 유지) ③지도 클러스터링(v0.15) ④**바다낚시지수 완료(v0.18, versionCode24)**: 프록시 `/api/fishing?lat&lon&date&gubun`(adapters/fishingIndex.ts 페이지네이션+6h캐시, domain/fishing.ts 포인트그룹+최근접+오전오후슬롯+어종중복제거 최고등급, routes/fishing.ts). 앱 DaySection에 날짜별 🎣낚시지수 라인(오전/오후 5단계 색칩 best/good/ok/bad/worst + 최근접포인트명·거리, 7일범위). 군산→신시도20km 검증. ⑤TTS음성알람=**사용자 보류**. 기타 같은 기간: 버그수정(예약시트 하단버튼 safe-area, DaySection 로딩 스켈레톤), 뒤로가기2회 종료모달(ExitGate, 광고자리), 업데이트를 상단배너→차단형 모달(다운로드+업데이트/종료)로 변경(UpdateBanner 항상 모달), 낚시포인트 3,105.

**주소 추가+내륙정리(v0.20.0, 2026-06-06)**: 사용자 피드백 "검색에 주소 없어 어디인지 모호"+"바다앱인데 내륙 점". **카카오 coord2regioncode로 3,105개 역지오코딩**→`address`(시군구 읍면동) 추가(육지 2,385개, 해상 711개는 주소없음=섬·갯바위). **내륙/오좌표 9개 제거**(안동시·청송군·문경시·부산진구·연제구·남동구내륙·미추홀구내륙 시군구 + 충남금산군: 임하리/축산항(오좌표,실제 영덕)/사근리/작약도방파제(오좌표)/건평나루(오좌표)/금산/부산·인천 vague점) → **3,105→3,096**. **지도 내륙 점 대부분은 leaflet.markercluster 중심점 아티팩트**(해안 점들 묶을 때 버블이 평균위치=내륙에 찍힘)였고 실제 내륙 데이터는 ~9개뿐. maxClusterRadius 55→38(촘촘하게=중심점 해안에 근접). 앱 TopSearch/MySpots/MapView툴팁에 주소 표시(신지도→완도군 신지면). Breakwater.address optional. locations.json은 프록시 라이브.

**웹앱 PC 접근(2026-06-06)**: 빌드된 웹앱을 `~/.www/sea-app`에 두고 프록시 루트 정적서빙 → **https://sea.lucas-ai.cc/** PC 브라우저서 열림(HashRouter라 SPA fallback 불필요, /assets/sql-wasm.wasm=application/wasm으로 웹 SQLite 동작, /api 영향없음). `.app` max-width:480px 가운데정렬(폰엔 무영향, PC선 폰폭 컬럼). **배포 시 `cp app/dist/* ~/.www/sea-app/`도 해야 웹 최신유지**. 공개 URL.

**NIFS OpenAPI(국립수산과학원, 2026-06-06)**: 신청링크 `https://www.nifs.go.kr/openApi/actionOpenapiInfoList.do`. **실시간어장정보** 승인(~2027-06-06, 만료시 재신청 필요), 키는 `proxy/.env` NIFS_REALTIME_FISHERY_KEY(=qPwO...1626), JSON/XML, 필드=관측소코드/소명/수온/관측일자. 용도: 현장 실시간 수온(바다날씨 보강). **추천 추가신청**: ⭐**생물종정보**(생물종ID/분류/학명/국명/영명/일명/서식수종/어종코드 — 도감 데이터 보강에 최적), 해파리정보·적조정보(안전 주의보 기능 가능), 어장환경관측자료·정선/연안 관측(수온·염분 등 해양관측, 우리 KHOA와 중복). 도감은 우선 수기 조사로 진행(낚시법/제철 포함), 생물종정보 신청되면 학명/분류 보강.

**위치데이터 롤백(v0.24.0, 2026-06-06)**: 여기물때 fishingaddr 병합분(1,545)이 **섬·외해 지점을 내륙 면 중심으로 오좌표**(예: 상낙월도가 영광군 묘량면 16km 내륙=정확한 외해 원본의 잘못된 중복)한 게 많아 사용자가 "지도 위치 오류 너무 많다" 지적. 멀리 떨어진 정상 섬(백령도 등)과 거리만으로 구분 불가 → **검증된 원본 1,551곳(L0001~1553 중 내륙 제거분)으로 롤백**. locations.json은 프록시 라이브(앱 재빌드 불필요). 향후 확장은 **at-sea 검증된 좌표 소스만**(지오코딩 센트로이드 금지). 역지오코딩 주소(시군구 읍면동)는 원본에도 유지(1,210곳). **도감/낚시지수/금어기는 그대로**. + 상단 검색 드롭다운 닫기 버그 수정(열렸을 때 ✕ 상시 + blur 닫힘).

**도감 사진 큐레이션 주의**: 위키 pageimages는 동명이의(예 "대구"=도시 사진, "넙치"는 OK)로 오매칭 가능 → 학명(영문위키)이나 Commons generator search로 받는 게 안전. 27종 전부 사진 확보(대구만 저해상 삽화). 이미지는 `/home/lucas/.www/sea-app/fish/{id}.jpg` 호스팅, fishbook.json에 절대 URL.

**관리자 페이지(2026-06-06)**: `https://sea.lucas-ai.cc/admin?t=<ADMIN_TOKEN>` — 토큰은 `proxy/.env` ADMIN_TOKEN(=5b9f...0b36, git 미포함, HTML에 런타임 주입). leaflet 지도 기반. **포인트**: 지도클릭/GPS로 추가(해안 자동=최근접, 주소 자동=카카오 역지오), 삭제, 검색, **CSV 일괄추가**(removed-points.csv 형식 호환). **도감사진**: 어종별 사진 교체(업로드→`/fish/<id>.jpg`+?v 버전증가). 쓰기는 `data/breakwaters.ts saveBreakwaters`/`data/fishbook.ts saveFishbook`로 메모리배열 제자리갱신+파일기록 → **/api 즉시 반영, 앱 재빌드 불필요**. routes/admin.ts + admin-page.ts. **제거된 포인트 리스트**: `https://sea.lucas-ai.cc/dl/removed-points.csv`(1,545곳, 해안거리km 정렬, 사용자가 걸러 재등록 예정). 도감 사진 캐시 이슈→URL ?v= 버전으로 무효화(교체 시 자동 증가).

**남은 작업**: 깊은 재디자인, 부속항 정확 조석매칭은 KHOA 조시차표(비공개) 필요 — 모델 ±15~30분 근사. 지도 타일 Kakao/Naver 업그레이드 후보(현 OSM, 키 불필요). 실기기: **자동설치 흐름**(v0.6.0~)·GPS·지도/마커탭·**스크롤날짜이동(v0.11)** 검증. **`/up` 임시유틸 + `/home/lucas/uploads` APK는 마무리 시 제거**(사용자 요청).

**남은 폴리시(과거)**: 조위곡선 자정 보간(완료). ~~조류세기%~~·~~수온~~·~~방파제검색~~·~~지점확대~~·~~조석수치~~·~~자동업데이트~~·~~잔극값/자정~~ 완료. (1) ~~R1 물때~~ 완료. 이하 기존 항목 일부 완료:

**(과거 계획, 일부 완료)**: (1) ~~**R1 물때**~~ — advisor 권고: 음력 테이블 하드코딩 금지, **한 달치 KHOA 조차로 캘리브레이션**(조금=최소조차, 사리=최대조차, age-of-tide 1~2일 lag). KASI 음양력 API(승인됨) 또는 검증 라이브러리. 서해/남해 관측소 각각 검증. (2) `/api/stations` — 관측소 60+개 좌표 배치 수집 + 서해/남해/동해/제주 분류. (3) 지점 선택 UI(내 지점 탭, GPS+검색+즐겨찾기 @capacitor/geolocation·preferences). (4) 물때표 탭(월간 달력). (5) 수온 보완(단기예보 미제공). (6) Android 플랫폼 추가(`cap add android`)+실기기. 설계/플랜은 `docs/superpowers/specs|plans/2026-06-05-*`.

관련: [[project_dailypiece]] (동일 Capacitor 스택), [[reference_www_layout]] (lucas-ai.cc 인프라).
