# AI로 FONUMA 웹앱 개발하기 — Application 0.2

이 문서는 `fonuma-app 0.2.0-dev.3`와 `fonuma.web-project/0.2` 전용이다. 공식 beta basic-0.1의 문법·CLI와 혼합하지 않는다. 별도의 유료 AI API는 필요하지 않다. 현재 사용하는 AI에게 아래 자료와 프로젝트를 제공할 수 있다.

## AI에게 제공할 지시 예

> 이 프로젝트는 FONUMA Application 0.2다. `fonuma.app.json`의 소스와 API 경로, `fonuma-app inspect .`의 타입을 먼저 확인하라. 업무 규칙은 `.fonuma`에, 화면은 pure `screen() -> List<List<String>>`에 작성하라. Rust 호스트에 앱별 규칙을 넣지 말라. Int의 JSON 표현은 십진 문자열이다. 업무 오류에는 Result<T>를 사용하고 저장 변경 전에 입력을 검사하라. 변경 후 check/test를 실행하고 실제 HTTP 호출로 정상·잘못된 입력·권한·재시작을 확인하라. 인증 비밀·실사용 DB를 소스나 프롬프트에 넣지 말라. 이 프로필에 없는 기능은 임의 문법으로 만들어내지 말고 필요한 확장을 설명하라.

## 작업 순서

1. `new DIR --template taskboard|inventory|booking|operations|commerce|community`으로 목적에 가까운 앱을 만든다. storage_scope가 personal인지 shared인지 확인한다. shared에서는 actor:true, 첫 Actor 인자와 소유자 검사를 함께 작성한다.
2. `inspect DIR`로 API·매개변수·결과 타입·레코드·프로젝트 SHA-256을 읽는다. hash가 바뀌면 다른 소스/manifest에 대한 결과다.
3. `src/models.fonuma`에 데이터, `src/main.fonuma`에 규칙을 정의한다. `use app.models as models;`와 `models.Record`/`models.function`을 사용한다. 파일 이름보다 선언된 module 이름이 import 기준이다.
4. 새 외부 함수는 manifest routes에 명시한다. 쓰기는 `write:true`, 사용자 정보는 `access:user` 또는 admin이다. `public` storage는 허용되지 않는다.
5. 화면에 view·group·폼·표·동작을 연결한다. table은 인자 없는 List<Record>, collection은 query/offset/limit을 받는 Page 레코드다. lookup은 읽기 전용 경로에서 다른 레코드를 선택한다. 임의 HTML 대신 screen 요소를 사용한다.
6. tests.json에 정상 결과와 오류 결과를 기록하고 `check`, `test`를 실행한다. 테스트의 저장은 메모리에서 격리되며 실사용 DB를 변경하지 않는다.
7. 별도 테스트 데이터 폴더에서 serve를 실행하고 두 계정의 개인 분리 또는 공유 권한, actor 위조 거부, 경쟁 요청, 재시작을 확인한다. 실제 브라우저에서 작은 화면·키보드·오류 표시도 확인한다.
8. 저장 형태를 바꾸면 이전 타입을 받는 pure migration을 작성하고 백업→이전→재시작한다. UI·로직만 바뀌어도 서버 재시작이 필요하다.

## 오류를 값으로 처리하기

```fonuma
fn positive(value: Int) -> Result<Int> effects [pure] {
    if (value <= 0) { return err("양수가 필요합니다."); }
    return ok(value);
}
fn example(value: Int) -> Result<Int> effects [pure] {
    let checked: Result<Int> = positive(value);
    if (!is_ok(checked)) { return err(error_message(checked)); }
    return ok(result_value(checked) + 1);
}
```

`result_value(Err)`는 런타임 오류다. `unwrap_or(result, default)`의 default는 먼저 평가된다. 최상위 저장 함수가 Err를 반환하면 그 호출의 저장을 취소한다. 중첩 Err의 자동 전파나 예외 catch는 없다.

## 회귀 시험

```json
[
  {"entry":"create","args":["첫 작업"],"expected":{"ok":true,"value":"1"}},
  {"entry":"complete","args":["1",true],"expected":{"ok":true,"value":true}},
  {"entry":"list","args":[],"expected":[{"id":"1","title":"첫 작업","done":true}]}
]
```

시험은 한 빈 저장에서 순서대로 실행한다. 실행 오류 또는 결과 불일치에서 종료 코드 1을 반환한다. 최대 256개다. 이것은 업무 함수 시험이며 HTTP·계정 보안·시각 검증을 모두 포함하는 명령은 아니다. 변경 내용에 맞는 별도 시험을 추가한다.

## 현재 프로필을 선택하는 기준

개인 업무관리와 회원용 공유 쇼핑·예약·커뮤니티의 제한된 흐름은 새 템플릿으로 시작할 수 있다. 다중 조직·결제·업로드·실시간·외부 연동·임의 프런트엔드 컴포넌트는 추가 확장이 필요하다. 범위를 먼저 명시하고 없는 기능을 이미 완성된 기능으로 설명하지 않는다. AI가 이 가이드로 개발할 수 있는 구조가 마련되었다는 사실과 독립 사용자 재현·AI 모델별 개발 효율이 입증되었다는 주장은 구분한다.

## 프로젝트별 타입 SDK

`fonuma-app sdk PROJECT --output NEW_DIRECTORY`는 검증된 프로젝트에서 JS 어댑터, TypeScript 선언과 schema.json을 만든다. 기존 폴더를 덮어쓰지 않는다. `.mjs`와 `.d.mts`를 함께 사용한다. `connect(client)`는 프로젝트 hash를 확인하고 actor 인자는 클라이언트에 노출하지 않는다. 소스/manifest 변경 후 재생성하고 서버 배포 후 다시 연결한다. 개별 함수 시험의 Actor 값은 시험 데이터이며 실제 API에서는 actor를 보내지 않는다. 자세한 계약은 [고급 가이드](APPLICATION_WEB_ADVANCED_0.2.md)를 따른다.


## dev.4 웹 연동 확장

파일·변경 감지·고정 외부 JSON 조회·서명 웹훅과 integrations 템플릿은 [웹 연동 확장 가이드](APPLICATION_WEB_EXTENSIONS_0.2.md)를 따른다. 모든 기능은 명시적으로 켜며 비밀값을 소스에 넣지 않는다. 변경 감지는 polling이고, 결제 예제는 결과 검증/상태 반영이며 실제 청구가 아니다. 확장 DB를 열기 전 백업하고 과거 dev.3과 DB 호환 경계를 확인한다.
