@serverkit-lib/runtime-package v0.0.45
@serverkit-lib/runtime-package
소개
이 모듈(@serverkit-lib/runtime-package
)은 서버키트로 생성된 서버에서 런타임 시 동적으로 사용 가능한 기능들을 제공합니다.
SCM
SCM은 .scm
파일 기반 데이터 구조의 유효성 검사를 처리하며, 데이터베이스 작업 전후로 데이터를 검증하는 데 최적화된 유틸리티를 제공합니다. 이 모듈은 다음과 같은 주요 기능을 제공합니다:
SCM 주요 기능
데이터 유효성 검사
- 특정 데이터의 전체 혹은 일부 유효성을 검사.
데이터 구조 기반 검증
- 초기화에서 등록된 사용자 정의 데이터 필드 리스트를 바탕으로 데이터 구조 검증.
Prisma 통합
- Prisma Middleware를 통해 자동 Validation 처리 지원.
주요 메서드
getInstance()
Scheme
클래스의 싱글턴 인스턴스를 반환합니다.
이 메서드로 이미 생성된 값을 참조할 수 있습니다. runtime-module의 scmInstance
객체를 참고해주세요. 이 객체는 Scheme 클래스의 모든 기능을 모두 사용할 수 있습니다.
validation(data: Record<string, any>): Promise<void>
- 주어진 데이터의 유효성을 검사합니다.
- data 파라미터로 넘어온 데이터만 유효성을 검사합니다. 전체 데이터를 기준으로 강한 검사를 원하면
fullValidation
을 참고해주세요. - 유효성 검사가 실패하면
SCMError
를 throw합니다.
fullValidation(data: any, scmId: string): Promise<void>
특정 scmId
에 대한 모든 필드의 유효성을 검사합니다.
- 모든 필드에 대한 데이터 유효성을 검증하므로 scmId가 가리키는 모든 필드를 기준으로 검사합니다. 즉, canBeNull이 false가 아닌 모든 필드에 대해 검사하므로 빠져있는 필드에 해당하는 값이 있을 경우 실패합니다.
- 하나라도 유효성 조건에 어긋나면
SCMError
를 throw합니다.
insertDataValidation(data: any, scmId: string): Promise<void>
prisma를 활용한 data Insert 작업 전에 유효성을 검사합니다.
- 유효성 검사가 실패하면
SCMError
를 throw합니다. - 이 함수는 initializeValidation에서 자동으로 처리됩니다. 별도로 검증을 원할 경우 사용해주세요.
updateDataValidation(data: any, scmId: string): Promise<void>
prisma를 활용한 data Update 작업 전에 유효성을 검사합니다.
- 유효성 검사가 실패하면
SCMError
를 throw합니다. - 이 함수는 initializeValidation에서 자동으로 처리됩니다. 별도로 검증을 원할 경우 사용해주세요.
getFieldTypeToInputType(fieldType: string): string
주어진 필드 타입에 대해 데이터베이스 입력 타입을 반환합니다.
SCM 주요 활용 예시
const { scmInstance } = require('@serverkit-lib/runtime-package'); // 런타임 모듈
const scmJson = require("./scm.json");
// SCM 애셋 JSON 포함.
scmInstance.scm = scmJson;
// Primsa Pre 이벤트를 지정하여 데이터가 Create/Update 시 Validation 처리되게 합니다.
const prisma = require("./vqm/prisma");
prisma.$use(async (params: any, next: any) => {
try {
// validation은 prisma에 설정한 모델 기준으로 작동하며 모델이 없을 경우 무시합니다.
const model = params.model ?? "";
if (model == "") {
return next(params); // Validation 대상이 아닌 DB작업이라 판단하며 실제 DB 작업 처리.
}
const findScm: ISCMRequest | undefined = this.scm.find((v) => {
return v.dbm.includes(model);
});
if (!findScm) {
return next(params); // Validation 대상이 아닌 DB작업이라 판단하며 실제 DB 작업 처리.
}
// 생성 작업 전처리
if (["create", "createMany"].includes(params.action)) {
if (params.action == "create") {
await this.insertDataValidation(params.args.data, findScm.id);
} else {
for (const d of params.args.data) {
await this.insertDataValidation(d, findScm.id);
}
}
console.log("Completely Data Validation (Create)");
}
// 수정 작업 전처리
else if (["update", "updateMany"].includes(params.action)) {
await this.updateDataValidation(params.args.data, findScm.id);
console.log("Completely Data Validation (Update)");
}
// 실제 DB 작업 개시.
return await next(params);
} catch (e) {
throw e;
}
});
SCMError
SCMError는 Node.js의 Error 클래스를 상속한 커스텀 Error 클래스로 Scheme 클래스 내에서 발생하는 모든 작업에 대한 예외상황 발생 시 반환되는 에러 형식입니다.
주요 속성
fields?: string[]
- 유효성 검사 중 실패한 필드 목록.
주요 메서드
info: { service, message, code, timestamp, fields }
- 에러 정보를 객체로 반환.
- fields 속성을 포함하여 유효성 검사 중 실패한 필드에 대한 정보를 제공합니다.
Drive
Drive 클래스는 싱글턴 패턴을 사용하여 인스턴스를 관리하며, 파일 저장소와 관련된 모든 작업을 수행합니다.
주요 기능
파일 저장소 설정
- 로컬 저장소 또는 클라우드 저장소(AWS S3 등)를 선택하여 사용할 수 있습니다.
- 저장소 유형에 따라 적절한 드라이버를 할당합니다.
파일 메타데이터 관리
- 특정 파일의 메타데이터를 조회할 수 있습니다.
파일 업로드 및 다운로드
- 임시 파일 업로드 핸들러 제공
- 정식 업로드 핸들러 제공
- 파일 다운로드 핸들러 제공
파일 삭제 기능
- 단일 파일 삭제
- 여러 파일 삭제
- 임시 파일만 삭제
- 고아 파일 정리 기능 (비활성화됨)
주요 클래스 및 메서드
getInstance()
싱글턴 인스턴스를 반환하는 정적 메서드입니다.
const drive = Drive.getInstance();
configs(options: DriveOptions)
드라이브의 설정을 변경하는 메서드입니다.
- 로컬 저장소 설정 시
localPath
필수 - 클라우드 저장소 설정 시
provider
옵션 필요
파일 작업 메서드
getMetadata(fileId: string): Promise<IFileMetadata | null>
특정 파일의 메타데이터를 가져옵니다.
const metadata = await drive.getMetadata("file123");
getBuffer(fileId: string): Promise<Buffer[] | null>
파일의 버퍼 데이터를 반환합니다.
const buffer = await drive.getBuffer("file123");
confirm(fileId: string): Promise<void>
임시 파일을 정식 파일로 승격합니다.
await drive.confirm("file123");
파일 업로드 및 다운로드 핸들러
uploadTmpHandler(): RequestHandler
→ 임시 파일 업로드 핸들러 반환uploadHandler(): RequestHandler
→ 정식 업로드 핸들러 반환downloadFileHandler(fileId: string): RequestHandler
→ 파일 다운로드 핸들러 반환
app.post("/upload", drive.uploadHandler());
파일 삭제 메서드
deleteOne(fileId: string): Promise<void>
→ 특정 파일 삭제deleteMany(fileIdList: string[]): Promise<number>
→ 여러 파일 삭제deleteTmp(req: Express.Request): Promise<number>
→ 임시 파일만 삭제 (Request Handler를 요구합니다. 내부에서 req 객체를 찾아 자동 삭제합니다.)
await drive.deleteOne("file123");
향후 개선 사항
- Google Cloud Storage 및 Azure Blob Storage 지원 추가
- 클라우드 파일 관리 로직 강화
- 미사용 파일 자동 정리 기능 추가
이 클래스는 파일 저장소 작업을 효율적으로 수행할 수 있도록 설계되었습니다. 프로젝트 내에서 파일 관리가 필요하다면 Drive 클래스를 활용하세요!
Filedrive.Drive 클래스 사용 예시
// package.json
{
"name": "test_runtime_drive",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "node app"
},
"description": "파일 드라이브 테스트",
"dependencies": {
"@serverkit-lib/runtime-package": 0.0.45,
"express": "^4.21.2"
}
}
// app.js
const { driveInstance } = require("@serverkit-lib/runtime-package");
const express = require("express");
const path = require("path");
// Logger: Info
function log(message) {
console.log(`\x1b[34m ℹ️ ${message}\x1b[0m`);
}
// Express 앱 초기화
const app = express();
app.use(express.urlencoded({ extended: true })); // URL-encoded 데이터 처리
app.use((err, req, res, next) => {
console.error("Global Error Handler:", err);
res.status(500).json({
error: err.message || "Internal Server Error",
details: err.details || "No additional details",
stack: err.stack || "No stack trace available"
});
});
// 파일 드라이브 설정 초기화 (선택 사항).
driveInstance.configs({
type: "local",
localPath: path.resolve(__dirname, "upload")
});
// tmp 파일 업로드 핸들러 설정
// ※ app.use(express.json()) 보다 먼저 호출해야 tmp 파일 업로드, 메타데이터를 추출하고
// req.body에 해당 키에 파일 키 매핑이 가능합니다.
app.use(driveInstance.uploadTmpHandler());
app.use(express.json());
// 메타데이터 가져오기
app.get("/file/metadata/:id", async (req: express.Request, res: express.Response) => {
try {
const param: string = req.params["id"] ?? "";
const files: IFileMetadata | null = await driveInstance.getMetadata(param);
res.send(files);
} catch (error) {
console.log(error);
res.status(500).json(error);
}
});
// 일반 파일 업로드
app.post("/file/upload", driveInstance.uploadHandler());
// tmp 파일 승격 처리
app.post("/file/confirm", async (req: express.Request, res: express.Response) => {
const id: string = req.body["id"] ?? "";
try {
await driveInstance.confirm(id);
res.send("정상 처리");
} catch (error) {
res.status(500).json(error);
}
});
// 파일 다운로드 처리.
app.get("/file/download/:fileId", driveInstance.downloadFileHandler());
// 서버 시작
const PORT = 7777;
app.listen(PORT, () => {
log(`Test server running at localhost:${PORT}`);
});
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
2 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
3 months ago
4 months ago
4 months ago
4 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
5 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago
6 months ago