create-entity-server 0.0.15 → 0.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/create.js +15 -7
- package/package.json +1 -1
- package/template/.env.example +8 -7
- package/template/configs/database.json +173 -10
- package/template/entities/Account/account_audit.json +4 -5
- package/template/entities/System/system_audit_log.json +14 -8
- package/template/samples/README.md +28 -22
- package/template/samples/browser/entity-server-client.js +453 -0
- package/template/samples/browser/example.html +498 -0
- package/template/samples/entities/02_types_and_defaults.json +15 -16
- package/template/samples/entities/04_fk_and_composite_unique.json +0 -2
- package/template/samples/entities/05_cache.json +9 -8
- package/template/samples/entities/06_history_and_hard_delete.json +27 -9
- package/template/samples/entities/07_license_scope.json +40 -31
- package/template/samples/entities/09_hook_entity.json +0 -6
- package/template/samples/entities/10_hook_submit_delete.json +5 -2
- package/template/samples/entities/11_hook_webhook.json +9 -7
- package/template/samples/entities/12_hook_push.json +3 -3
- package/template/samples/entities/13_read_only.json +13 -10
- package/template/samples/entities/15_reset_defaults.json +0 -1
- package/template/samples/entities/16_isolated_license.json +62 -0
- package/template/samples/entities/README.md +36 -39
- package/template/samples/flutter/lib/entity_server_client.dart +170 -48
- package/template/samples/java/EntityServerClient.java +208 -61
- package/template/samples/java/EntityServerExample.java +4 -3
- package/template/samples/kotlin/EntityServerClient.kt +175 -45
- package/template/samples/node/src/EntityServerClient.js +232 -59
- package/template/samples/node/src/example.js +9 -9
- package/template/samples/php/ci4/Config/EntityServer.php +0 -1
- package/template/samples/php/ci4/Libraries/EntityServer.php +206 -53
- package/template/samples/php/laravel/Services/EntityServerService.php +190 -41
- package/template/samples/python/entity_server.py +181 -68
- package/template/samples/python/example.py +7 -6
- package/template/samples/react/src/example.tsx +41 -25
- package/template/samples/swift/EntityServerClient.swift +143 -37
- package/template/scripts/run.ps1 +12 -3
- package/template/scripts/run.sh +12 -8
- package/template/scripts/update-server.ps1 +68 -2
- package/template/scripts/update-server.sh +59 -2
- package/template/samples/entities/order_notification.json +0 -51
- package/template/samples/react/src/api/entityServerClient.ts +0 -413
- package/template/samples/react/src/hooks/useEntity.ts +0 -173
package/bin/create.js
CHANGED
|
@@ -228,11 +228,14 @@ async function run() {
|
|
|
228
228
|
);
|
|
229
229
|
console.warn(` https://github.com/${REPO}/releases\n`);
|
|
230
230
|
} else {
|
|
231
|
+
const binDir = path.join(targetDir, "bin");
|
|
232
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
233
|
+
|
|
231
234
|
for (const bin of ["entity-server", "entity-cli"]) {
|
|
232
235
|
const ext = platform === "windows" ? ".exe" : "";
|
|
233
236
|
const fileName = `${bin}-${platform}-${arch}${ext}`;
|
|
234
237
|
const url = `https://github.com/${REPO}/releases/download/v${VERSION}/${fileName}`;
|
|
235
|
-
const dest = path.join(
|
|
238
|
+
const dest = path.join(binDir, bin + ext);
|
|
236
239
|
|
|
237
240
|
process.stdout.write(` ↓ ${fileName} 다운로드 중...`);
|
|
238
241
|
try {
|
|
@@ -253,8 +256,9 @@ async function run() {
|
|
|
253
256
|
// ── 3. 완료 안내 ─────────────────────────────────────────────────────────
|
|
254
257
|
|
|
255
258
|
const relDir = path.relative(process.cwd(), targetDir) || dirName;
|
|
256
|
-
const serverExe = isWin
|
|
257
|
-
|
|
259
|
+
const serverExe = isWin
|
|
260
|
+
? ".\\bin\\entity-server.exe"
|
|
261
|
+
: "./bin/entity-server";
|
|
258
262
|
const runScript = isWin
|
|
259
263
|
? ".\\scripts\\run.ps1 start"
|
|
260
264
|
: "./scripts/run.sh start";
|
|
@@ -264,8 +268,9 @@ async function run() {
|
|
|
264
268
|
✓ 완료!
|
|
265
269
|
|
|
266
270
|
${relDir}/
|
|
267
|
-
|
|
268
|
-
|
|
271
|
+
├── bin/
|
|
272
|
+
│ ├── entity-server${binExt} ← 서버 바이너리
|
|
273
|
+
│ └── entity-cli${binExt} ← CLI 도구
|
|
269
274
|
├── .env ← 환경 변수 설정 (여기를 먼저 수정하세요)
|
|
270
275
|
├── configs/ ← CORS, JWT 등 서버 설정
|
|
271
276
|
├── entities/ ← 엔티티 스키마 JSON (샘플 포함)
|
|
@@ -274,8 +279,11 @@ async function run() {
|
|
|
274
279
|
|
|
275
280
|
다음 단계:
|
|
276
281
|
${cdCmd ? ` ${cdCmd}` : ""}
|
|
277
|
-
|
|
278
|
-
|
|
282
|
+
./scripts/generate-env-keys${isWin ? ".ps1 -Apply" : ".sh --apply"} # ENCRYPTION_KEY/JWT_SECRET 생성 후 .env 반영
|
|
283
|
+
vim .env # PORT, DB_PATH 등 기본 환경값 확인/수정
|
|
284
|
+
vim configs/*.json # database/server/jwt 등 운영 설정
|
|
285
|
+
vim entities/*.json # 사용할 엔티티 스키마 정의
|
|
286
|
+
${serverExe} # 마지막: 서버 실행
|
|
279
287
|
|
|
280
288
|
서버마다 .env 의 PORT 와 DB_PATH 를 다르게 설정하면
|
|
281
289
|
같은 머신에서 여러 프로젝트를 동시에 운영할 수 있습니다.
|
package/package.json
CHANGED
package/template/.env.example
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# Entity Server 환경변수 설정 예시
|
|
2
2
|
# 실제 사용시 이 파일을 .env로 복사하고 값을 변경하세요: cp .env.example .env
|
|
3
|
+
# ./scripts/generate-env-keys.sh 를 사용하여 랜덤 시크릿을 생성할 수 있습니다.
|
|
3
4
|
|
|
4
|
-
# 기본 암복호화
|
|
5
|
-
#
|
|
5
|
+
# 기본 암복호화 마스터 시크릿 (license 엔티티 등 공통 fallback 키)
|
|
6
|
+
# HKDF-SHA256 으로 32바이트(256-bit) XChaCha20-Poly1305 키를 유도하는 마스터 시크릿입니다.
|
|
7
|
+
# 충분한 엔트로피를 가진 임의 문자열이면 됩니다 (예: openssl rand -hex 32 으로 생성).
|
|
6
8
|
ENCRYPTION_KEY=your-32-char-hex-encryption-key-here
|
|
7
9
|
|
|
8
10
|
# JWT 서명 키 (HS256)
|
|
@@ -13,18 +15,17 @@ JWT_SECRET=your-jwt-secret-here
|
|
|
13
15
|
SERVER_PORT=47200
|
|
14
16
|
|
|
15
17
|
# Database values (database.json의 ${ENV_VAR}와 매핑)
|
|
18
|
+
DB_HOST_DEVELOPMENT=127.0.0.1
|
|
19
|
+
DB_PORT_DEVELOPMENT=3306
|
|
16
20
|
DB_NAME_DEVELOPMENT=your-development-db-name
|
|
17
21
|
DB_USER_DEVELOPMENT=your-development-db-user
|
|
18
22
|
DB_PASSWORD_DEVELOPMENT=your-development-db-password
|
|
19
23
|
|
|
24
|
+
DB_HOST_PRODUCTION=127.0.0.1
|
|
25
|
+
DB_PORT_PRODUCTION=3306
|
|
20
26
|
DB_NAME_PRODUCTION=your-production-db-name
|
|
21
27
|
DB_USER_PRODUCTION=your-production-db-user
|
|
22
28
|
DB_PASSWORD_PRODUCTION=your-production-db-password
|
|
23
29
|
|
|
24
|
-
# PostgreSQL group (선택)
|
|
25
|
-
# DB_NAME_POSTGRESQL=your-postgresql-db-name
|
|
26
|
-
# DB_USER_POSTGRESQL=your-postgresql-db-user
|
|
27
|
-
# DB_PASSWORD_POSTGRESQL=your-postgresql-db-password
|
|
28
|
-
|
|
29
30
|
# 푸시 알림 (push.json에서 ${FCM_PROJECT_ID} 등으로 참조 가능)
|
|
30
31
|
# FCM_PROJECT_ID=your-firebase-project-id
|
|
@@ -1,23 +1,186 @@
|
|
|
1
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// database.json 설정 예시 (주석 포함 예시 전용 파일 — 실제 파일은 순수 JSON)
|
|
3
|
+
//
|
|
4
|
+
// "default" : 사용할 그룹 이름 (groups 키 중 하나)
|
|
5
|
+
// "groups" : 드라이버별 연결 설정 모음
|
|
6
|
+
// driver : "mysql" | "postgres" | "mongodb" | "dynamodb" |
|
|
7
|
+
// "firestore" | "scylladb" | "couchdb"
|
|
8
|
+
//
|
|
9
|
+
// 환경 변수 참조: "${ENV_VAR_NAME}" 형식으로 값을 주입합니다.
|
|
10
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
1
11
|
{
|
|
2
12
|
"default": "development",
|
|
3
13
|
"groups": {
|
|
14
|
+
// ── MySQL (SQL) ─────────────────────────────────────────────────
|
|
4
15
|
"development": {
|
|
5
16
|
"driver": "mysql",
|
|
6
|
-
"host": "
|
|
7
|
-
"port":
|
|
8
|
-
"database": "
|
|
9
|
-
"user": "
|
|
17
|
+
"host": "${DB_HOST_DEVELOPMENT}",
|
|
18
|
+
"port": "${DB_PORT_DEVELOPMENT}",
|
|
19
|
+
"database": "${DB_NAME_DEVELOPMENT}",
|
|
20
|
+
"user": "${DB_USER_DEVELOPMENT}",
|
|
10
21
|
"password": "${DB_PASSWORD_DEVELOPMENT}",
|
|
11
|
-
"maxOpenConns": 20
|
|
22
|
+
"maxOpenConns": 20,
|
|
23
|
+
"maxIdleConns": 10,
|
|
24
|
+
"connMaxLifetimeSec": 3600
|
|
12
25
|
},
|
|
13
26
|
"production": {
|
|
14
27
|
"driver": "mysql",
|
|
15
|
-
"host": "
|
|
16
|
-
"port":
|
|
17
|
-
"database": "
|
|
18
|
-
"user": "
|
|
28
|
+
"host": "${DB_HOST_PRODUCTION}",
|
|
29
|
+
"port": "${DB_PORT_PRODUCTION}",
|
|
30
|
+
"database": "${DB_NAME_PRODUCTION}",
|
|
31
|
+
"user": "${DB_USER_PRODUCTION}",
|
|
19
32
|
"password": "${DB_PASSWORD_PRODUCTION}",
|
|
20
|
-
"maxOpenConns": 50
|
|
33
|
+
"maxOpenConns": 50,
|
|
34
|
+
"maxIdleConns": 25,
|
|
35
|
+
"connMaxLifetimeSec": 3600
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
// ── MongoDB ─────────────────────────────────────────────────────
|
|
39
|
+
// URI 우선 사용. uri 가 없으면 host/port/database/username/password 조합.
|
|
40
|
+
"mongodb_dev": {
|
|
41
|
+
"driver": "mongodb",
|
|
42
|
+
"uri": "mongodb://localhost:27017/entity_dev",
|
|
43
|
+
"database": "entity_dev"
|
|
44
|
+
},
|
|
45
|
+
"mongodb_prod": {
|
|
46
|
+
"driver": "mongodb",
|
|
47
|
+
"host": "${MONGO_HOST}",
|
|
48
|
+
"port": 27017,
|
|
49
|
+
"database": "${MONGO_DB}",
|
|
50
|
+
"username": "${MONGO_USER}",
|
|
51
|
+
"password": "${MONGO_PASSWORD}",
|
|
52
|
+
"uri": ""
|
|
53
|
+
},
|
|
54
|
+
"mongodb_replica": {
|
|
55
|
+
"driver": "mongodb",
|
|
56
|
+
"uri": "mongodb://${MONGO_USER}:${MONGO_PASS}@mongo1:27017,mongo2:27017,mongo3:27017/${MONGO_DB}?replicaSet=rs0&authSource=admin",
|
|
57
|
+
"database": "${MONGO_DB}"
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
// ── Amazon DynamoDB ─────────────────────────────────────────────
|
|
61
|
+
// region 과 IAM 인증이 필요합니다.
|
|
62
|
+
// 로컬 테스트: endpoint 에 "http://localhost:8000" 지정.
|
|
63
|
+
"dynamodb_dev": {
|
|
64
|
+
"driver": "dynamodb",
|
|
65
|
+
"region": "ap-northeast-2",
|
|
66
|
+
"endpoint": "http://localhost:8000",
|
|
67
|
+
"access_key_id": "${AWS_ACCESS_KEY_ID}",
|
|
68
|
+
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}"
|
|
69
|
+
},
|
|
70
|
+
"dynamodb_prod": {
|
|
71
|
+
"driver": "dynamodb",
|
|
72
|
+
"region": "${AWS_REGION}",
|
|
73
|
+
"access_key_id": "${AWS_ACCESS_KEY_ID}",
|
|
74
|
+
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}"
|
|
75
|
+
},
|
|
76
|
+
|
|
77
|
+
// ── Google Cloud Firestore ──────────────────────────────────────
|
|
78
|
+
// GCP 프로젝트 ID 와 서비스 계정 JSON 파일(또는 ADC)이 필요합니다.
|
|
79
|
+
// credentials_file : 서비스 계정 키 파일 경로 (선택)
|
|
80
|
+
// ADC 자동 사용 시 credentials_file 생략 가능.
|
|
81
|
+
"firestore_dev": {
|
|
82
|
+
"driver": "firestore",
|
|
83
|
+
"project_id": "${GCP_PROJECT_ID}",
|
|
84
|
+
"credentials_file": "${GOOGLE_APPLICATION_CREDENTIALS}"
|
|
85
|
+
},
|
|
86
|
+
"firestore_prod": {
|
|
87
|
+
"driver": "firestore",
|
|
88
|
+
"project_id": "${GCP_PROJECT_ID}"
|
|
89
|
+
},
|
|
90
|
+
|
|
91
|
+
// ── ScyllaDB / Apache Cassandra ────────────────────────────────
|
|
92
|
+
// hosts 는 쉼표 구분 문자열 또는 배열 모두 허용합니다.
|
|
93
|
+
// keyspace 가 없으면 자동 생성됩니다.
|
|
94
|
+
"scylladb_dev": {
|
|
95
|
+
"driver": "scylladb",
|
|
96
|
+
"hosts": "localhost:9042",
|
|
97
|
+
"keyspace": "entity_dev",
|
|
98
|
+
"username": "",
|
|
99
|
+
"password": ""
|
|
100
|
+
},
|
|
101
|
+
"scylladb_prod": {
|
|
102
|
+
"driver": "scylladb",
|
|
103
|
+
"hosts": "${SCYLLA_HOSTS}",
|
|
104
|
+
"keyspace": "${SCYLLA_KEYSPACE}",
|
|
105
|
+
"username": "${SCYLLA_USER}",
|
|
106
|
+
"password": "${SCYLLA_PASSWORD}",
|
|
107
|
+
"consistency": "quorum",
|
|
108
|
+
"timeout": "10s"
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
// ── Apache CouchDB ──────────────────────────────────────────────
|
|
112
|
+
// URI 우선 사용. uri 가 없으면 host/port/username/password 조합.
|
|
113
|
+
// 포트 기본값: 5984
|
|
114
|
+
"couchdb_dev": {
|
|
115
|
+
"driver": "couchdb",
|
|
116
|
+
"host": "localhost",
|
|
117
|
+
"port": 5984,
|
|
118
|
+
"username": "admin",
|
|
119
|
+
"password": "password"
|
|
120
|
+
},
|
|
121
|
+
"couchdb_uri": {
|
|
122
|
+
"driver": "couchdb",
|
|
123
|
+
"uri": "http://admin:password@localhost:5984/"
|
|
124
|
+
},
|
|
125
|
+
"couchdb_prod": {
|
|
126
|
+
"driver": "couchdb",
|
|
127
|
+
"uri": "http://${COUCH_USER}:${COUCH_PASS}@${COUCH_HOST}:${COUCH_PORT}/"
|
|
21
128
|
}
|
|
22
129
|
}
|
|
23
130
|
}
|
|
131
|
+
|
|
132
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
133
|
+
// DataStore 단독 사용 — flat 형식 (groups 없이 최상위에 driver 직접 지정)
|
|
134
|
+
//
|
|
135
|
+
// SQL 없이 NoSQL DataStore만 단독으로 사용할 때는 groups 없이
|
|
136
|
+
// database.json 최상위에 driver 를 직접 지정합니다.
|
|
137
|
+
// store_loader.go 가 groups 키가 없고 NoSQL driver 인 경우에만 DataStore로 인식합니다.
|
|
138
|
+
// ──────────────────────────────────────────────────────────────────────────
|
|
139
|
+
|
|
140
|
+
// MongoDB flat 형식
|
|
141
|
+
{
|
|
142
|
+
"driver": "mongodb",
|
|
143
|
+
"uri": "mongodb://localhost:27017",
|
|
144
|
+
"database": "entity_server"
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// MongoDB — 환경변수 방식
|
|
148
|
+
{
|
|
149
|
+
"driver": "mongodb",
|
|
150
|
+
"host": "${MONGO_HOST}",
|
|
151
|
+
"port": "${MONGO_PORT}",
|
|
152
|
+
"username": "${MONGO_USER}",
|
|
153
|
+
"password": "${MONGO_PASSWORD}",
|
|
154
|
+
"database": "${MONGO_DATABASE}"
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// DynamoDB flat 형식
|
|
158
|
+
{
|
|
159
|
+
"driver": "dynamodb",
|
|
160
|
+
"region": "${AWS_REGION}",
|
|
161
|
+
"access_key_id": "${AWS_ACCESS_KEY_ID}",
|
|
162
|
+
"secret_access_key": "${AWS_SECRET_ACCESS_KEY}"
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Firestore flat 형식
|
|
166
|
+
{
|
|
167
|
+
"driver": "firestore",
|
|
168
|
+
"project_id": "${GCP_PROJECT_ID}",
|
|
169
|
+
"credentials_file": "${GOOGLE_APPLICATION_CREDENTIALS}"
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ScyllaDB flat 형식
|
|
173
|
+
{
|
|
174
|
+
"driver": "scylladb",
|
|
175
|
+
"host": "${SCYLLA_HOST}",
|
|
176
|
+
"port": 9042,
|
|
177
|
+
"database": "${SCYLLA_KEYSPACE}",
|
|
178
|
+
"username": "${SCYLLA_USER}",
|
|
179
|
+
"password": "${SCYLLA_PASSWORD}"
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// CouchDB flat 형식
|
|
183
|
+
{
|
|
184
|
+
"driver": "couchdb",
|
|
185
|
+
"uri": "http://${COUCH_USER}:${COUCH_PASS}@${COUCH_HOST}:5984/"
|
|
186
|
+
}
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "account_audit",
|
|
3
|
-
"description": "
|
|
3
|
+
"description": "account 감사 로그. JWT 인증 시에만 account_seq는 required",
|
|
4
4
|
"index": {
|
|
5
5
|
"account_seq": {
|
|
6
|
-
"comment": "계정 seq",
|
|
6
|
+
"comment": "계정 seq (JWT 인증 시 account.seq 참조. HMAC은 nullable)",
|
|
7
7
|
"type": "bigint",
|
|
8
|
-
"
|
|
8
|
+
"nullable": true
|
|
9
9
|
},
|
|
10
10
|
"action": {
|
|
11
11
|
"comment": "작업 유형",
|
|
12
12
|
"type": ["INSERT", "UPDATE", "DELETE", "LOGIN", "LOGOUT"],
|
|
13
13
|
"required": true
|
|
14
14
|
}
|
|
15
|
-
}
|
|
16
|
-
"license_scope": false
|
|
15
|
+
}
|
|
17
16
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "system_audit_log",
|
|
3
|
-
"description": "시스템 감사 로그. 서버 레벨에서 자동 기록되며 API를 통한 직접 수정은 허용되지 않습니다.",
|
|
3
|
+
"description": "시스템 감사 로그. 서버 레벨에서 자동 기록되며 API를 통한 직접 수정은 허용되지 않습니다. JWT 인증 시에만 account_seq 기록",
|
|
4
4
|
"db_group": "system",
|
|
5
5
|
"hard_delete": true,
|
|
6
6
|
"history_ttl": 0,
|
|
@@ -18,7 +18,8 @@
|
|
|
18
18
|
},
|
|
19
19
|
"entity_seq": {
|
|
20
20
|
"comment": "대상 엔티티 레코드 seq. 로그인/로그아웃 등 레코드 없는 경우 NULL",
|
|
21
|
-
"type": "bigint"
|
|
21
|
+
"type": "bigint",
|
|
22
|
+
"nullable": true
|
|
22
23
|
},
|
|
23
24
|
"action": {
|
|
24
25
|
"comment": "수행된 작업 유형",
|
|
@@ -34,16 +35,19 @@
|
|
|
34
35
|
"required": true
|
|
35
36
|
},
|
|
36
37
|
"account_seq": {
|
|
37
|
-
"comment": "작업을 수행한 계정 seq.
|
|
38
|
-
"type": "bigint"
|
|
38
|
+
"comment": "작업을 수행한 계정 seq. JWT 인증 요청은 account.seq, 비인증/HMAC 요청은 NULL",
|
|
39
|
+
"type": "bigint",
|
|
40
|
+
"nullable": true
|
|
39
41
|
},
|
|
40
42
|
"ip_address": {
|
|
41
43
|
"comment": "요청 IP 주소 (IPv4/IPv6)",
|
|
42
|
-
"type": "varchar(45)"
|
|
44
|
+
"type": "varchar(45)",
|
|
45
|
+
"nullable": true
|
|
43
46
|
},
|
|
44
47
|
"endpoint": {
|
|
45
48
|
"comment": "요청 API 엔드포인트",
|
|
46
|
-
"type": "varchar(200)"
|
|
49
|
+
"type": "varchar(200)",
|
|
50
|
+
"nullable": true
|
|
47
51
|
},
|
|
48
52
|
"request_method": {
|
|
49
53
|
"comment": "HTTP 메서드 (GET/POST/PUT/DELETE 등)",
|
|
@@ -51,7 +55,8 @@
|
|
|
51
55
|
},
|
|
52
56
|
"request_payload": {
|
|
53
57
|
"comment": "요청 본문 JSON. 민감 필드(password, token 등) 자동 마스킹 후 저장. ServerConfig.AuditLogPayload = true 일 때만 기록",
|
|
54
|
-
"type": "text"
|
|
58
|
+
"type": "text",
|
|
59
|
+
"nullable": true
|
|
55
60
|
},
|
|
56
61
|
"result_code": {
|
|
57
62
|
"comment": "HTTP 응답 코드 (200, 400, 401, 403, 500 등)",
|
|
@@ -59,7 +64,8 @@
|
|
|
59
64
|
},
|
|
60
65
|
"error_message": {
|
|
61
66
|
"comment": "실패 시 오류 메시지 요약",
|
|
62
|
-
"type": "varchar(500)"
|
|
67
|
+
"type": "varchar(500)",
|
|
68
|
+
"nullable": true
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
71
|
}
|
|
@@ -15,11 +15,12 @@ Client / Browser
|
|
|
15
15
|
Backend Server ←── 이 샘플이 구현하는 부분
|
|
16
16
|
│
|
|
17
17
|
▼ HMAC 서명 (서버 간 통신)
|
|
18
|
-
Entity Server
|
|
18
|
+
Entity Server
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
>
|
|
22
|
-
>
|
|
21
|
+
> **브라우저(React·Vanilla)** 환경에서도 HMAC / JWT 모두 사용 가능합니다.
|
|
22
|
+
> 단, 브라우저에서 HMAC을 사용하면 `hmacSecret`이 클라이언트에 노출되므로,
|
|
23
|
+
> **프론트엔드 프로덕션 환경에서는 JWT 사용을 권장합니다.**
|
|
23
24
|
|
|
24
25
|
## HMAC 서명 공식
|
|
25
26
|
|
|
@@ -39,31 +40,36 @@ signature = HMAC-SHA256(hmacSecret, payload) → hex
|
|
|
39
40
|
|
|
40
41
|
## API 엔드포인트
|
|
41
42
|
|
|
42
|
-
| 동작
|
|
43
|
-
|
|
|
44
|
-
| 단건 조회
|
|
45
|
-
|
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
43
|
+
| 동작 | 메서드 | 경로 |
|
|
44
|
+
| -------------- | ------ | ---------------------------------- |
|
|
45
|
+
| 단건 조회 | GET | `/v1/entity/{name}/{seq}` |
|
|
46
|
+
| 조건 단건 조회 | POST | `/v1/entity/{name}/find` |
|
|
47
|
+
| 목록 조회 | POST | `/v1/entity/{name}/list` |
|
|
48
|
+
| 필터 검색 | POST | `/v1/entity/{name}/query` |
|
|
49
|
+
| 건수 조회 | POST | `/v1/entity/{name}/count` |
|
|
50
|
+
| 생성/수정 | POST | `/v1/entity/{name}/submit` |
|
|
51
|
+
| 삭제 | POST | `/v1/entity/{name}/delete/{seq}` |
|
|
52
|
+
| 이력 조회 | GET | `/v1/entity/{name}/history/{seq}` |
|
|
53
|
+
| 롤백 | POST | `/v1/entity/{name}/rollback/{seq}` |
|
|
52
54
|
|
|
53
55
|
- `list` 쿼리 파라미터: `?page=1&limit=20&order_by=<field>`
|
|
54
56
|
- `submit` — body에 `seq` 포함 시 수정, 없으면 생성
|
|
55
57
|
|
|
56
58
|
## 샘플 목록
|
|
57
59
|
|
|
58
|
-
| 디렉토리 | 프레임워크
|
|
59
|
-
| -------------- |
|
|
60
|
-
| `entities/` | 엔티티 설정 예제
|
|
61
|
-
| `
|
|
62
|
-
| `php/
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
60
|
+
| 디렉토리 | 프레임워크 | 인증 방식 |
|
|
61
|
+
| -------------- | ---------------------------------------------- | ---------- |
|
|
62
|
+
| `entities/` | 엔티티 설정 예제 | — |
|
|
63
|
+
| `browser/` | 브라우저 (Vanilla ES Module, 빌드 도구 불필요) | HMAC / JWT |
|
|
64
|
+
| `php/ci4/` | CodeIgniter 4 | HMAC / JWT |
|
|
65
|
+
| `php/laravel/` | Laravel | HMAC / JWT |
|
|
66
|
+
| `java/` | Java (표준 라이브러리) | HMAC / JWT |
|
|
67
|
+
| `kotlin/` | Kotlin (표준 라이브러리) | HMAC / JWT |
|
|
68
|
+
| `swift/` | Swift (URLSession) | HMAC / JWT |
|
|
69
|
+
| `flutter/` | Flutter (Dart) | HMAC / JWT |
|
|
70
|
+
| `node/` | Node.js (fetch) | HMAC / JWT |
|
|
71
|
+
| `python/` | Python (requests) | HMAC / JWT |
|
|
72
|
+
| `react/` | React + TypeScript | HMAC / JWT |
|
|
67
73
|
|
|
68
74
|
### CI4 설정 방식
|
|
69
75
|
|