찾다
웹 프론트엔드JS 튜토리얼js를 사용하여 데이터베이스 개발

js를 사용하여 데이터베이스 개발

Apr 26, 2018 pm 02:36 PM
javascript데이터 베이스

프런트엔드에서는 여전히 일부 데이터를 저장해야 합니다. 여기서 보존은 장기 저장을 의미합니다. 이 글에서는 데이터베이스를 개발하기 위해 js를 사용하는 방법을 공유합니다.

프론트 -end는 여전히 저장이 필요한 경우가 많습니다. 일부 데이터를 저장하려면 여기서 보존이란 장기 보존을 의미합니다. 이전 아이디어는 데이터를 쿠키에 저장하거나, 키를 쿠키에 저장하고, 다른 데이터는 서버에 저장하는 것이었습니다.

이 장면은 용도가 다양하며 매우 성숙하고 사용하기 쉽습니다. 하지만 저는 여전히 데이터베이스나 웹 SQL처럼 로컬에 장기간 저장할 수 있는 데이터를 원합니다.

신세대 브라우저는 기본적으로 로컬 데이터베이스를 지원하므로 필요할 때 직접 사용하세요. 작동하지 않으면 Storage를 사용하여 작업을 수행할 수 있습니다.

데이터베이스 같은 기능이 필요한데 호환되는 저장 방법이 없다면 어떻게 하나요? 이러한 항목을 로컬로 암호화하고 저장해야 합니까? 나는 많은 것을 저장하고 싶다?

현재 ReactNative를 사용할 때 이런 상황이 발생했습니다. 많은 양의 데이터를 로컬에 저장해야 합니다. 누군가는 SQLite를 직접 사용하는 것이 더 좋지 않을까요?

알겠습니다. 전혀 괜찮습니다. 저는 여기서 프론트 엔드 태도로 개발하고 있습니다. 일부 학생에게 SQLite는 필요하지 않지만 대량의 데이터를 저장하는 간단한 방법만 필요한 경우 어떻게 해야 합니까?

사용 시나리오는 다양할 수 있으며, 구현의 맨 아래 레이어를 마음대로 교체할 수 있고, 구현 방법도 마음대로 작성할 수 있습니다. 여기서 나는 세상을 창조하는 프런트엔드의 태도를 바탕으로 비공식적이고 프런트엔드 친화적인 데이터 저장소를 구축하고 있습니다.

기본 스토리지

여기 사용 시나리오는 ReactNative이므로 RN의 AsyncStorage를 사용합니다.

저장할 모든 데이터를 객체와 문자열로 변환합니다. 여기서 핵심 아이디어는 직렬화입니다. 모든 데이터를 문자열로 저장합니다.

import { AsyncStorage } from 'react-native';

exports.setItem = async (key, value) => {    let item = JSON.stringify({
        v: value
    });    return await AsyncStorage.setItem(key, item);
}

읽을 때 문자열을 원래 저장된 데이터로 변환하려면 변환도 해야 합니다.

exports.getItem = async (key) => {    let item = await AsyncStorage.getItem(key);    if (!item) {        return null;
    }    return JSON.parse(item).v || null;
}

특별한 처리가 필요한 것은 목록 획득입니다. RN에는 여러 키를 기반으로 여러 데이터 조각을 반환하는 API가 있습니다. 배열 객체를 반환합니다. 배열 번호 0은 데이터 저장의 키 값이고 시퀀스 번호 1은 데이터 저장의 특정 문자열입니다.

exports.getlist = async (keys) => {    let list = await AsyncStorage.multiGet(keys);
    list = list.map(item => JSON.parse(item[1]).v || null);    return list;
}

그 밖에도 사용된 몇 가지 방법도 꺼내보겠습니다. 위와 동일한 구성을 유지하면서 여기에 레이어를 하나 더 중첩합니다.

exports.removeItem = async (key) => await AsyncStorage.removeItem(key);

exports.removeItems = async (keys) => await AsyncStorage.multiRemove(keys);

exports.allKeys = async () => await AsyncStorage.getAllKeys();

기본 최적화

위는 단순한 구현일 뿐 특별한 요구 사항이 없다면 거의 동일합니다. 그러나 더 나아가고 싶은 사람들은 최적화 시작을 고려할 수 있습니다.

예를 들어 json 변환 속도를 최적화하세요. JSON 객체 방식을 사용하여 변환할 때 실제로 숫자형을 결정하는 과정이 있습니다. 데이터 유형을 미리 정의하는 경우. 변환할 때 다시 판단할 필요가 없습니다.

모델 객체를 정의하고 이 테이블에 필요한 필드를 미리 정의할 수 있습니다. Sequelize가 어떻게 정의되어 있는지 확인할 수 있습니다. 관계형 행 데이터베이스의 방식에 따라 이를 수행하는 것은 매우 간단합니다.

//用户对象const users = db.define('t_users', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
    },    //用户名
    username: {
        type: Sequelize.STRING
    },    //密码
    pwd: {
        type: Sequelize.STRING
    },    //状态
    status: {
        type: Sequelize.INTEGER
    },    //昵称
    nickname: {
        type: Sequelize.STRING
    },    //token
    token: {
        type: Sequelize.STRING
    },
    create_time: {
        type: Sequelize.TIME
    }
}, {
    freezeTableName: true,
    timestamps: false,
});

스토리지 구현

여기서는 관계형 데이터베이스 구현을 참고하겠습니다.

우선 테이블과 데이터베이스를 나누어야 합니다. 이렇게 하면 데이터를 저장할 때 이 정보에 덜 주의를 기울이고 데이터 작업에 집중할 수 있습니다.

constructor(tableName = "table", db = "db") {        //检查库,表是否存在
        //初始化索引表
        this.db = db;        this.tableName = tableName;        this.tableKey = db + "_" + tableName;        this.init();
    }

현재 객체 내부에 별도로 저장하세요. 객체 생성 시 다양한 라이브러리와 테이블을 기반으로 다양한 작업 방법을 생성할 수 있습니다. 여기서는 클래스가 사용되며 각 테이블은 별도의 개체에 해당합니다.

RN에서 제공하는 저장 방식을 사용하고 있기 때문에 여기서 추가와 업데이트는 사실 동일한 방식입니다. 추가 시 현재 타임스탬프를 기준으로 고유한 ID가 생성되며, 이 ID는 데이터베이스에 저장하기 위한 키로 사용됩니다. 따라서 사용시 ID를 별도로 저장할 필요는 없습니다. 다만, 필요한 ID와 다르다고 생각되면 직접 ID를 정의하여 키 값을 저장할 수도 있습니다.

//添加和更新
    async add(data = {}) {        if (data.constructor !== Object) return;        if (!data._id)data._id = uuid();
        await setItem(this.tableKey + "_" + data._id, data);        return data;
    }

획득 시 ID별로 획득 방법을 별도로 제공하고 있습니다. 여기서 고려되는 점은 ID로 얻는 것이 매우 간단하고 편리하다는 것입니다. 일부 데이터는 빠르게 읽을 수 있으며 한 줄씩 쿼리할 필요가 없습니다.

/**
 * 通过id查询
 * @param {*} id 
 */async getById(id) {    if (!id) return {};    return await getItem(this.tableKey + "_" + id);
}

ID 기반 쿼리에 비해 퍼지 쿼리는 실제로 매우 느립니다. 실제로 필요하지 않은 경우에는 이 퍼지 쿼리를 사용하지 않는 것이 좋습니다. 다음은 반환된 개체를 기반으로 이 데이터 행이 필요한지 여부를 결정할 수 있는 사용자 지정 쿼리 메서드입니다. 반환되는 수를 제한하기 위해 top 매개변수를 추가할 수도 있습니다. 이 매개변수를 사용하면 데이터가 많을 때 성능이 향상될 수도 있습니다.

/**
 * 通过过滤方法查询
 * @param {*} fn 
 */async get(fn, top = 0) {    let keys = await allKeys();    if (keys.length == 0) return [];    if (top > 0 && keys.length > top) keys.length = top;    const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0);    if (listkey.length == 0) return [];    let list = await getlist(listkey);
    list = list.filter(item => fn(item));    return list;
}

드디어 삭제, 삭제 메소드를 추가하면 간단한 삭제 라이브러리가 완성됩니다.

 /**
 * 删除
 * @param {*} id 
 */async delete(id) {    if (!id) return {};
    await removeItem(this.tableKey + "_" + id);
}/**
 * 清空表
 */async clear() {    let keys = await allKeys();    const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0);    if (listkey.length == 0) return;
    removeItems(listkey);
}

사용시에는 객체를 생성한 후 필요한 곳에 호출하기만 하면 됩니다. 사용이 간단하고 편리하며, 최적화 후에는 클라이언트측 Redis로도 사용할 수 있습니다.

//初始化数据库let db=new JSDB();//添加一个自定义数据db.add({name:"test",key:"abc"});//根据id获取数据db.getById("1223467890");//根据条件查询数据db.get(d=>d.name==="test");//删除对应的数据db.delete("1223467890");//情况所有数据db.clear()

생성 최적화

최초로 최적화해야 할 것은 객체 생성입니다. 각 객체 생성에는 실제로 많은 돈이 소비됩니다. 이 소비를 줄일 수 있다면 좋지 않을까요?

여기에서는 데이터베이스 풀의 개념을 배우고 개체 풀 방법을 구현합니다. 객체가 생성된 후에는 직접적인 반환이 없으며 풀 작업을 거쳐야 합니다.

将对象放入池内,并在页面销毁的时候重置为一个空对象。下次请求创建的时候就不必再创建新的了。直接赋值表、库的名称就可以使用了。内存毫无变化,并且有点想笑。

优化查询

每次查询都需要去读Stroage还是很麻烦的,尤其这个操作是异步操作,是需要发消息到native端的。

我们可以将上次读取的数据先存在一个变量中,如果下次还需要使用这行数据,就完全不需要再去读取了。这样就可以很简单的提供读取速度。

这个方式还可以继续优化。将变量中保存的数据限制数量,防止数量太多超过了APP的限制。还可以将这个保存的时限做一个逻辑判断,常使用的数据放在里面,不常用的就找机会删除。

使用这种方式也可以优化变量中数据的有效性,减少变量占用内存的大小。不过实现的方式尽量不要使用定时器的形式,可以考虑使用触发式的。在条件满足的时候再触发删除动作。

优化写入

上面提到读取的时候需要放入变量来提高读取速度。我们顺便想到写入的速度是不是也可以提高啊?

我们将要存的数据放在临时的变量里,如果查过我们设置的时间或者数据长度查过我们设置的数量就触发一次保存操作。

这里要注意,保存数据的变量和存入时候使用的变量要交替使用,防止出现丢数据的情况。

比如:存的时候使用变量1,在写到数据库之前,将要存的对象改成变量2,然后读取变量1的数据并存入数据库中。这就是双缓存写入。

当然还是要判断一次APP的退出事件的,如果APP退出了,请一定要把变量中的内容保存一次,不然你的心血就全丢了。


好了,一个简单的数据库就完成了。想要使用的可以先在npm上搜索react-native-jsdb这个库。我已经将第一部分实现放在了npm上,后续的优化也会满满的开源出来的。

npm仓库地址

文章地址

前端很多时候还是需要保存一些数据的,这里的保存指的是长久的保存。以前的思想是把数据保存在cookie中,或者将key保存在cookie中,将其他数据保存在服务器上。

这几个场景用处很多,也非常的成熟好用。但是我还是想要一种能够长久的保存在本地的数据,类似数据库或者类似web sql。

新一代浏览器基本都支持了本地数据库,需要用的时候直接使用就好了。实在不行还可以使用Storage将就一下。

假如我需要的是一个数据库那种功能并且没有兼容的存储方式呢?加入我还要加密存储这些东西在本地呢?加入我要存的东西非常多呢?

目前我在使用ReactNative的时候确实遇到了这种情况。我需要将非常多的数据存在本地。有人说了,直接使用sqlite不就好了么?

好啊,完全可以啊。我这里仅仅是本着前端的态度去开发而已。假如有的同学不需要sqlite呢,只需要一个简单的,能够存储一些大量数据的方式呢?

使用场景可能有很多,实现的底层也可以随便替换,甚至实现方式都可以随便写写。这里我本着前端创造世界的态度来做一个非正式的、前端好使的数据存储库。

底层存储

这里的使用场景是ReactNative,所以我使用的是RN的AsyncStorage。

将所有要保存的数据转成对象,并转化为字符串。这里的核心思想就是序列化。将所有数据当成字符串来存。

import { AsyncStorage } from 'react-native';

exports.setItem = async (key, value) => {    let item = JSON.stringify({
        v: value
    });    return await AsyncStorage.setItem(key, item);
}

当读取的时候也需要做一次转化,将字符串转成当初存入的数据。

exports.getItem = async (key) => {    let item = await AsyncStorage.getItem(key);    if (!item) {        return null;
    }    return JSON.parse(item).v || null;
}

需要特殊处理的是列表的获取。RN有一个根据多个key返回多条数据的api。它返回的是一个数组对象,数组序号0是数据存储的key值,序号1才是数据存储的具体字符串。

exports.getlist = async (keys) => {    let list = await AsyncStorage.multiGet(keys);
    list = list.map(item => JSON.parse(item[1]).v || null);    return list;
}

其他用到的几个方法也顺便拿出来吧。这里多嵌套一层,跟上面的保持队形。

exports.removeItem = async (key) => await AsyncStorage.removeItem(key);

exports.removeItems = async (keys) => await AsyncStorage.multiRemove(keys);

exports.allKeys = async () => await AsyncStorage.getAllKeys();

底层优化

上面只是简单的实现,如果没有特殊需求也就差不多了。但是,想要更进一步的可以考虑开始优化了。

比如,优化json转化的速度。我们使用JSON对象的方法去转化的时候其实还有一个判断数值类型的过程。如果我们把数据的类型提前定义好。再转化的时候就不需要再判断了。

可以定义一个model对象,将这个表需要的字段预先定义好。可以查看一下Sequelize的定义方式。按照关系行数据库的方式来搞这个事情就很简单了。

//用户对象const users = db.define('t_users', {
    id: {
        type: Sequelize.INTEGER,
        primaryKey: true,
    },    //用户名
    username: {
        type: Sequelize.STRING
    },    //密码
    pwd: {
        type: Sequelize.STRING
    },    //状态
    status: {
        type: Sequelize.INTEGER
    },    //昵称
    nickname: {
        type: Sequelize.STRING
    },    //token
    token: {
        type: Sequelize.STRING
    },
    create_time: {
        type: Sequelize.TIME
    }
}, {
    freezeTableName: true,
    timestamps: false,
});

实现存储

我们这里参考一下关系型数据库的实现。

首先需要分表和分库。这样在存入数据的时候可以更少的关注这方面的信息,将主要精力放在数据操作上。

constructor(tableName = "table", db = "db") {        //检查库,表是否存在
        //初始化索引表
        this.db = db;        this.tableName = tableName;        this.tableKey = db + "_" + tableName;        this.init();
    }

将它们分开存储在当前对象内部,在创建对象的时候就可以根据不同的库、表创建不同的操作方法。这里使用的是class,每个表都对应一个单独的对象。

由于我们使用的是RN提供的存储方法,所以这里的添加和更新其实是一个方法。在添加的时候会根据当前时间戳创建一个唯一id,使用这个id作为key存储在数据库中。所以在使用的时候不需要再单独存入id,不过如果你觉得这个id跟你需要的有差别也可以自己定义一个id来作为key值存储。

//添加和更新
    async add(data = {}) {        if (data.constructor !== Object) return;        if (!data._id)data._id = uuid();
        await setItem(this.tableKey + "_" + data._id, data);        return data;
    }

在获取的时候单独提供了一个根据id获取的方式。这里考虑的是通过id获取非常的简单方便,对于某些数据完全可以快速读取,没必要一行一行的去查询。

/**
 * 通过id查询
 * @param {*} id 
 */async getById(id) {    if (!id) return {};    return await getItem(this.tableKey + "_" + id);
}

相对于根据id查询来说,模糊查询确实很慢,如果不是真实需要,还是不要使用这种模糊查询的好。这里提供了一个自定义查询的方法,可以根据返回的对象判断是否需要这行数据。同时也可以添加top参数来限制返回的数量。使用这个参数也可以在数据很多的时候提高性能。

/**
 * 通过过滤方法查询
 * @param {*} fn 
 */async get(fn, top = 0) {    let keys = await allKeys();    if (keys.length == 0) return [];    if (top > 0 && keys.length > top) keys.length = top;    const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0);    if (listkey.length == 0) return [];    let list = await getlist(listkey);
    list = list.filter(item => fn(item));    return list;
}

最后把删除和清空的方法加上,这样一个简单的删除库就完成了。

 /**
 * 删除
 * @param {*} id 
 */async delete(id) {    if (!id) return {};
    await removeItem(this.tableKey + "_" + id);
}/**
 * 清空表
 */async clear() {    let keys = await allKeys();    const listkey = keys.filter(item => item.indexOf(this.tableKey + "_") === 0);    if (listkey.length == 0) return;
    removeItems(listkey);
}

使用的时候只需要创建对象,然后在需要的地方调用即可。使用起来简单又方便,再加上优化之后的情况甚至可以当成客户端的redis来使用。

//初始化数据库let db=new JSDB();//添加一个自定义数据db.add({name:"test",key:"abc"});//根据id获取数据db.getById("1223467890");//根据条件查询数据db.get(d=>d.name==="test");//删除对应的数据db.delete("1223467890");//情况所有数据db.clear()

优化创建

首先要优化的就是对象的创建。每个对象创建其实都是一个很大的消耗,如果能把这个消耗降低岂不是美滋滋!

这里我们借鉴数据库池的概念,实现一个对象池的方法。在对象创建之后并没有直接返回,要在经过池的操作。

将对象放入池内,并在页面销毁的时候重置为一个空对象。下次请求创建的时候就不必再创建新的了。直接赋值表、库的名称就可以使用了。内存毫无变化,并且有点想笑。

优化查询

每次查询都需要去读Stroage还是很麻烦的,尤其这个操作是异步操作,是需要发消息到native端的。

我们可以将上次读取的数据先存在一个变量中,如果下次还需要使用这行数据,就完全不需要再去读取了。这样就可以很简单的提供读取速度。

这个方式还可以继续优化。将变量中保存的数据限制数量,防止数量太多超过了APP的限制。还可以将这个保存的时限做一个逻辑判断,常使用的数据放在里面,不常用的就找机会删除。

使用这种方式也可以优化变量中数据的有效性,减少变量占用内存的大小。不过实现的方式尽量不要使用定时器的形式,可以考虑使用触发式的。在条件满足的时候再触发删除动作。

优化写入

上面提到读取的时候需要放入变量来提高读取速度。我们顺便想到写入的速度是不是也可以提高啊?

我们将要存的数据放在临时的变量里,如果查过我们设置的时间或者数据长度查过我们设置的数量就触发一次保存操作。

这里要注意,保存数据的变量和存入时候使用的变量要交替使用,防止出现丢数据的情况。

比如:存的时候使用变量1,在写到数据库之前,将要存的对象改成变量2,然后读取变量1的数据并存入数据库中。这就是双缓存写入。

当然还是要判断一次APP的退出事件的,如果APP退出了,请一定要把变量中的内容保存一次,不然你的心血就全丢了。


好了,一个简单的数据库就完成了。想要使用的可以先在npm上搜索react-native-jsdb这个库。我已经将第一部分实现放在了npm上,后续的优化也会满满的开源出来的。

相关推荐:

npm仓库地址

文章地址

위 내용은 js를 사용하여 데이터베이스 개발의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
JavaScript 엔진 이해 : 구현 세부 사항JavaScript 엔진 이해 : 구현 세부 사항Apr 17, 2025 am 12:05 AM

보다 효율적인 코드를 작성하고 성능 병목 현상 및 최적화 전략을 이해하는 데 도움이되기 때문에 JavaScript 엔진이 내부적으로 작동하는 방식을 이해하는 것은 개발자에게 중요합니다. 1) 엔진의 워크 플로에는 구문 분석, 컴파일 및 실행; 2) 실행 프로세스 중에 엔진은 인라인 캐시 및 숨겨진 클래스와 같은 동적 최적화를 수행합니다. 3) 모범 사례에는 글로벌 변수를 피하고 루프 최적화, Const 및 Lets 사용 및 과도한 폐쇄 사용을 피하는 것이 포함됩니다.

Python vs. JavaScript : 학습 곡선 및 사용 편의성Python vs. JavaScript : 학습 곡선 및 사용 편의성Apr 16, 2025 am 12:12 AM

Python은 부드러운 학습 곡선과 간결한 구문으로 초보자에게 더 적합합니다. JavaScript는 가파른 학습 곡선과 유연한 구문으로 프론트 엔드 개발에 적합합니다. 1. Python Syntax는 직관적이며 데이터 과학 및 백엔드 개발에 적합합니다. 2. JavaScript는 유연하며 프론트 엔드 및 서버 측 프로그래밍에서 널리 사용됩니다.

Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Python vs. JavaScript : 커뮤니티, 라이브러리 및 리소스Apr 15, 2025 am 12:16 AM

Python과 JavaScript는 커뮤니티, 라이브러리 및 리소스 측면에서 고유 한 장점과 단점이 있습니다. 1) Python 커뮤니티는 친절하고 초보자에게 적합하지만 프론트 엔드 개발 리소스는 JavaScript만큼 풍부하지 않습니다. 2) Python은 데이터 과학 및 기계 학습 라이브러리에서 강력하며 JavaScript는 프론트 엔드 개발 라이브러리 및 프레임 워크에서 더 좋습니다. 3) 둘 다 풍부한 학습 리소스를 가지고 있지만 Python은 공식 문서로 시작하는 데 적합하지만 JavaScript는 MDNWebDocs에서 더 좋습니다. 선택은 프로젝트 요구와 개인적인 이익을 기반으로해야합니다.

C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지C/C에서 JavaScript까지 : 모든 것이 어떻게 작동하는지Apr 14, 2025 am 12:05 AM

C/C에서 JavaScript로 전환하려면 동적 타이핑, 쓰레기 수집 및 비동기 프로그래밍으로 적응해야합니다. 1) C/C는 수동 메모리 관리가 필요한 정적으로 입력 한 언어이며 JavaScript는 동적으로 입력하고 쓰레기 수집이 자동으로 처리됩니다. 2) C/C를 기계 코드로 컴파일 해야하는 반면 JavaScript는 해석 된 언어입니다. 3) JavaScript는 폐쇄, 프로토 타입 체인 및 약속과 같은 개념을 소개하여 유연성과 비동기 프로그래밍 기능을 향상시킵니다.

JavaScript 엔진 : 구현 비교JavaScript 엔진 : 구현 비교Apr 13, 2025 am 12:05 AM

각각의 엔진의 구현 원리 및 최적화 전략이 다르기 때문에 JavaScript 엔진은 JavaScript 코드를 구문 분석하고 실행할 때 다른 영향을 미칩니다. 1. 어휘 분석 : 소스 코드를 어휘 단위로 변환합니다. 2. 문법 분석 : 추상 구문 트리를 생성합니다. 3. 최적화 및 컴파일 : JIT 컴파일러를 통해 기계 코드를 생성합니다. 4. 실행 : 기계 코드를 실행하십시오. V8 엔진은 즉각적인 컴파일 및 숨겨진 클래스를 통해 최적화하여 Spidermonkey는 유형 추론 시스템을 사용하여 동일한 코드에서 성능이 다른 성능을 제공합니다.

브라우저 너머 : 실제 세계의 JavaScript브라우저 너머 : 실제 세계의 JavaScriptApr 12, 2025 am 12:06 AM

실제 세계에서 JavaScript의 응용 프로그램에는 서버 측 프로그래밍, 모바일 애플리케이션 개발 및 사물 인터넷 제어가 포함됩니다. 1. 서버 측 프로그래밍은 Node.js를 통해 실현되며 동시 요청 처리에 적합합니다. 2. 모바일 애플리케이션 개발은 재교육을 통해 수행되며 크로스 플랫폼 배포를 지원합니다. 3. Johnny-Five 라이브러리를 통한 IoT 장치 제어에 사용되며 하드웨어 상호 작용에 적합합니다.

Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Next.js (백엔드 통합)로 멀티 테넌트 SAAS 애플리케이션 구축Apr 11, 2025 am 08:23 AM

일상적인 기술 도구를 사용하여 기능적 다중 테넌트 SaaS 응용 프로그램 (Edtech 앱)을 구축했으며 동일한 작업을 수행 할 수 있습니다. 먼저, 다중 테넌트 SaaS 응용 프로그램은 무엇입니까? 멀티 테넌트 SAAS 응용 프로그램은 노래에서 여러 고객에게 서비스를 제공 할 수 있습니다.

Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Next.js (Frontend Integration)를 사용하여 멀티 테넌트 SaaS 응용 프로그램을 구축하는 방법Apr 11, 2025 am 08:22 AM

이 기사에서는 Contrim에 의해 확보 된 백엔드와의 프론트 엔드 통합을 보여 주며 Next.js를 사용하여 기능적인 Edtech SaaS 응용 프로그램을 구축합니다. Frontend는 UI 가시성을 제어하기 위해 사용자 권한을 가져오고 API가 역할 기반을 준수하도록합니다.

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 채팅 명령 및 사용 방법
1 몇 달 전By尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

SecList

SecList

SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

VSCode Windows 64비트 다운로드

VSCode Windows 64비트 다운로드

Microsoft에서 출시한 강력한 무료 IDE 편집기