# 개발용 서버 연동 계약 인증·행별 권한이 없는 개발용 예제입니다. 회사 인증 정보는 포함하지 않습니다. 운영 환경의 인증, CSRF, 행별 권한, 감사로그, 저장 멱등키, DB 트랜잭션은 별도로 구현해야 합니다. ## 조회 POST /api/query, Content-Type: application/json **필수값 — 조회 요청:** `page`, `size`, `sort`, `filters`, `search`. 빈 정렬/필터는 `[]`, 빈 검색어는 `""`로 전달합니다. `filterTree`는 선택입니다. 그리드의 server.fetch가 받은 request에는 이 항목들이 이미 들어 있습니다. **필수값 — 조회 응답:** `rows`(배열), `total`(정수), `hasMore`(boolean). 빈 결과도 `{ "rows": [], "total": 0, "hasMore": false }`로 모두 반환합니다. 각 행에는 고유한 rowKey 값이 필요합니다. 요청 전체 예: ```json {"page":0,"size":2,"sort":[{"field":"id","dir":"asc"}],"filters":[],"filterTree":{"op":"and","rules":[{"field":"quantity","op":"gte","value":0}]},"search":"서버"} ``` 응답 전체 예: ```json {"rows":[{"id":1,"name":"서버 행 1","quantity":0,"price":1000,"date":"2026-09-18","choice":"A","active":true},{"id":2,"name":"서버 행 2","quantity":1,"price":1001,"date":"2026-09-18","choice":"A","active":true}],"total":20000,"hasMore":true} ``` page는 0부터 시작, size는 1~1000. sort는 최대 8개. filters는 AND로 결합, filterTree는 중첩 AND/OR. 필터 깊이 8, 총 노드 100, 그룹당 50개, in 최대 100값. search는 200자 이하. 서버 모드에서 변경이 존재하면 검색·정렬·필터 변경을 거부한다. 저장 또는 원복 후 재조회한다. 조건 변경은 이전 요청을 취소하고 세대 번호가 다른 응답을 폐기한다. 중복 행 ID가 있는 추가 페이지는 전체 거부한다. 초기 조회 실패는 기존 데이터, 추가 실패는 이전 페이지를 유지한다. retry는 실패한 page와 append 값을 다시 사용한다. Infinite Scroll은 viewport 끝 150px 이내에서 다음 페이지를 요청한다. ## 저장 POST /api/save **필수값 — 저장 요청:** `insert`, `update`, `delete` 배열. 변경이 없는 종류도 `[]`로 전달하며 각 행의 `id`는 필수값입니다. **필수값 — 저장 성공 응답:** `success: true`. `affected`는 그리드의 성공 판정 필수값이 아닙니다. ```json {"insert":[{"id":20001,"name":"신규","quantity":1,"price":1000,"date":"2026-09-18","choice":"A","active":true}],"update":[{"id":1,"name":"수정","quantity":2,"price":1000,"date":"2026-09-18","choice":"B","active":true}],"delete":[{"id":2}]} ``` 성공: HTTP 200 ```json {"success":true,"affected":3} ``` 검증 실패: HTTP 400 ```json {"success":false,"message":"타입 오류: quantity"} ``` ID 충돌/없는 행: HTTP 409. 요청 크기 초과: HTTP 413. 일회 모의 장애: HTTP 503. 모든 저장 검증 후 메모리 Map을 교체해 원자적으로 적용한다. 저장 배치 총 1000행, 요청 최대 1MiB. 허용 필드: id/name/quantity/price/date/choice/active/parentId. 계산 필드(total)는 저장 전에 제거해야 한다. 클라이언트 save의 failure 기본값 keep: 실패하면 변경 상태를 유지. rollback: 마지막 서버 확정 상태로 돌아감. optimistic:true는 응답 전 표시 상태를 확정하고, 실패 시 선택한 정책으로 복구. 저장 중 편집을 차단한다. retry는 실패 후 데이터가 바뀌지 않았을 때 당시 배치를 복원해 동일 작업을 수행한다. 서버가 저장했지만 응답이 유실된 경우 멱등성이 보장되지 않으므로 운영 서버에 요청 ID를 추가해야 한다. ## 행 순서 저장 (rowReorder) rowReorder:true에서 순서가 바뀌면 저장 배치에 선택 항목 `order`가 추가된다. 값은 현재 적재된 모든 행의 키 배열이며 숫자 키와 문자열 키를 구분한다. 예: `{insert:[], update:[], delete:[], order:[3,1,2]}`. 서버는 배열의 순서를 저장해야 하며 일반 CRUD만 처리하면 순서는 보존되지 않는다. 이 개발 서버는 정수 id만 지원하고 order를 처리해 DB의 해당 행 위치를 교체한다. 미조회 행의 상대 위치는 유지한다. 누락 ID·중복·잘못된 키는 CRUD와 함께 원자적으로 거부한다. 실제 DB에서는 순번 컬럼·트랜잭션으로 영속화해야 한다. 성공 저장은 success:true를 반환하며 order도 새 기준 상태로 확정한다. 기존 배치의 order 생략은 허용한다.