image
Akan.js
Docs
문서컨벤션레퍼런스Cheatsheet
한국어
image
Akan.js
Akan.js v2 문서가 새로 나왔습니다.v1 문서 보기
문서컨벤션레퍼런스Cheatsheet
MIT 라이선스 하에 배포되었습니다.
Akan.js 공식 컨설팅 서비스Akansoft
Copyright © 2026 Akan.js 모든 권리 보유.
시스템 관리자bassman
일반
• 인증
• 스키마 설계
• 엣지 컴퓨팅
• 파일 관리
• Single Sign-On
• DataList & Enum
인터페이스
• CRUD
• Endpoint
• Form
관측성
• 로깅
• 의존성 주입
• 에러 처리
• 메트릭
성능
• 캐싱
• 이미지 최적화
• 지연 로딩
• 쿼리
• 변경
• 큐
• 실시간
개발
• 문서화
• 스크립트
• 콘솔
• 모바일
• 도커
• 쿠버네티스
• PWA
일반
• 인증
• 스키마 설계
• 엣지 컴퓨팅
• 파일 관리
• Single Sign-On
• DataList & Enum
인터페이스
• CRUD
• Endpoint
• Form
관측성
• 로깅
• 의존성 주입
• 에러 처리
• 메트릭
성능
• 캐싱
• 이미지 최적화
• 지연 로딩
• 쿼리
• 변경
• 큐
• 실시간
개발
• 문서화
• 스크립트
• 콘솔
• 모바일
• 도커
• 쿠버네티스
• PWA
이전
쿼리
다음
큐

변경

Akan에는 저장된 데이터를 바꾸는 두 가지 방법이 있습니다. 하나의 로드된 document를 수정할 때는 document method를, 조건에 맞는 행을 데이터베이스에서 직접 바꿀 때는 query update를 사용합니다.
  • Document method(`.set().save()`, `Model.update`, `Model.remove`)는 document를 로드해 save/update/remove hook을 실행한 뒤 저장합니다.
  • Query update(`updateOne`, `updateMany`, `deleteMany`, `bulkWrite`)는 하나의 원자적 SQL 문으로 컴파일되며 document를 로드하지 않습니다.
  • query 조건에 `q`를 쓰듯, 변경 연산에는 `u` update helper를 사용합니다.

두 가지 작성법

단순 값 대입은 plain object로, operator가 필요하면 helper가 콜사이트 스코프로 주입되는 builder 함수로 넘깁니다. 값을 그대로 쓰면 `set`의 축약입니다.
Object 형태 (값 = set)
Builder 형태 (operator)
builder는 동기로 실행됩니다. await가 필요한 값(예: 비밀번호 해시)은 호출 전에 계산해 builder 안에서 참조하세요.

카운터와 집합

숫자 operator(`inc`, `mul`, `min`, `max`)와 배열 operator(`push`, `addToSet`, `pull`)는 데이터베이스 안에서 실행되므로, 동시에 쓰는 요청끼리 서로의 변경을 잃지 않습니다.
원자적 카운터
`addToSet`과 `pull`은 배열 요소를 값으로 매칭하며 스칼라 집합(id, 문자열, 숫자)에서 신뢰성 있게 동작합니다.

Upsert

`{ upsert: true }`를 주면 매칭이 없을 때 새 행을 삽입합니다. filter의 값이 document의 기본이 되고, operator는 빈 기본값에서 적용되며, `setOnInsert`는 이 삽입 때만 적용됩니다.
삽입 또는 증가

SQL로 바뀌는 방식

adaptor는 모든 operator를 `_doc` 컬럼 위의 하나의 중첩 JSON 표현식으로 접고 항상 `updatedAt`을 갱신합니다. 전체 update는 데이터베이스가 원자적으로 적용하는 단일 문입니다.
Update helperDocument updateSQL 조각
plain value (set)
{ status: "done" }
json_set(_doc, '$.status', json(?))
u.set
({ set }) => ({ status: set("done") })
json_set(_doc, '$.status', json(?))
u.unset
({ unset }) => ({ draft: unset() })
json_remove(_doc, '$.draft')
u.inc
({ inc }) => ({ views: inc(1) })
json_set(_doc, '$.views', COALESCE(json_extract(_doc, '$.views'), 0) + ?)
u.mul
({ mul }) => ({ price: mul(1.1) })
json_set(_doc, '$.price', COALESCE(json_extract(_doc, '$.price'), 0) * ?)
u.min
({ min }) => ({ lowest: min(10) })
json_set(_doc, '$.lowest', MIN(COALESCE(json_extract(_doc, '$.lowest'), ?), ?))
u.max
({ max }) => ({ highest: max(90) })
json_set(_doc, '$.highest', MAX(COALESCE(json_extract(_doc, '$.highest'), ?), ?))
u.push
({ push }) => ({ logs: push(entry) })
json_set(_doc, '$.logs', json_insert(COALESCE(json_extract(_doc, '$.logs'), json('[]')), '$[#]', json(?)))
u.addToSet
({ addToSet }) => ({ tags: addToSet("urgent") })
json_set(_doc, '$.tags', CASE WHEN EXISTS (SELECT 1 FROM json_each(...) WHERE value = ?) THEN ... ELSE json_insert(..., '$[#]', json(?)) END)
u.pull
({ pull }) => ({ tags: pull("urgent") })
json_set(_doc, '$.tags', (SELECT json_group_array(value) FROM json_each(...) WHERE value <> ?))
u.setOnInsert
({ setOnInsert }) => ({ status: setOnInsert("new") })
applied only when upsert inserts a new row
nested path
({ set }) => ({ "profile.city": set("Seoul") })
json_set(_doc, '$.profile.city', json(?))
combined
({ inc, addToSet }) => ({ views: inc(1), tags: addToSet("hot") })
json_set(json_set(_doc, '$.views', ... + ?), '$.tags', ...)
이 SQL 조각들은 개념을 보여주기 위해 단순화한 예시이며 SQLite/libsql dialect 기준입니다. Postgres는 동등한 jsonb 함수를 사용합니다. 모든 operator는 갱신 전 document를 읽으므로, 한 호출 안의 모든 변경은 같은 원본 값을 봅니다.
Query update는 document hook을 실행하지 않습니다.
  • `updateOne`, `updateMany`, `deleteMany`, `bulkWrite`는 데이터베이스에 직접 쓰며 save/update/remove hook을 발화하지 않습니다.
  • document마다 항상 실행되어야 하는 규칙이 있다면 document 경로를 사용하세요: `Model.update(id, patch)`, `Model.remove(id)`, 또는 `doc.set(...).save()`.

꿀팁

  • 카운터나 대량 상태 변경에는 query update를, hook이나 풍부한 도메인 로직이 필요할 때는 document method를 선호하세요.
  • update helper를 module scope에서 import하지 말고 builder 형태를 사용하세요.
  • 변경이 반드시 어떤 행에 적용되어야 한다면 결과의 `modifiedCount`를 확인하세요.
변경
두 가지 작성법
카운터와 집합
Upsert
SQL로 바뀌는 방식
꿀팁