여러 고객을위한 API를 만들고 있습니다. 핵심 엔드 포인트 /users
는 모든 고객이 사용하지만 일부 엔드 포인트는 개별 사용자 지정에 의존합니다. 따라서 사용자 A 가 특별한 엔드 포인트를 원하고 /groups
다른 고객은 해당 기능을 갖지 않을 수 있습니다. 각주 와 마찬가지로 각 고객은 이러한 추가 기능 때문에 자체 데이터베이스 스키마를 사용하게됩니다.
나는 개인적으로 NestJ를 사용합니다 (후드에서 표현). 따라서 app.module
현재 모든 핵심 모듈을 자체 엔드 포인트 등으로 등록합니다.
import { Module } from '@nestjs/common';
import { UsersModule } from './users/users.module'; // core module
@Module({
imports: [UsersModule]
})
export class AppModule {}
나는이 문제가 NestJ와 관련이 없다고 생각하므로 이론적으로 어떻게 처리 할 것입니까?
기본적으로 기본 시스템을 제공 할 수있는 인프라가 필요합니다. 각 확장이 고유하고 여러 개이기 때문에 더 이상 핵심 엔드 포인트가 없습니다./users
구현이 가능 . 새로운 기능을 개발할 때 핵심 애플리케이션을 건드리지 않아야합니다. 확장 기능은 자체 통합되거나 시작시 통합되어야합니다. 코어 시스템은 엔드 포인트가없는 상태로 제공되지만 이러한 외부 파일에서 확장됩니다.
몇 가지 아이디어가 떠오른다
첫 번째 접근법 :
각 확장은 새로운 저장소를 나타냅니다. 해당 확장 프로젝트를 모두 포함하는 사용자 지정 외부 폴더의 경로를 정의하십시오. 이 사용자 정의 디렉토리 폴더 포함됩니다 groups
A를을groups.module
import { Module } from '@nestjs/common';
import { GroupsController } from './groups.controller';
@Module({
controllers: [GroupsController],
})
export class GroupsModule {}
내 API는 해당 디렉토리를 반복하고 각 모듈 파일을 가져 오려고 시도 할 수 있습니다.
-
찬성 :
- 사용자 정의 코드는 핵심 저장소에서 멀리 떨어져 있습니다.
-
단점 :
-
NestJ는 Typescript를 사용하므로 먼저 코드를 컴파일해야합니다. API 빌드 및 사용자 정의 앱의 빌드를 어떻게 관리합니까? (플러그 앤 플레이 시스템)
-
사용자 정의 확장자는 일부 유형 스크립트 파일 만 포함하므로 매우 느슨합니다. API의 node_modules 디렉토리에 액세스 할 수 없기 때문에 외부 패키지 종속성을 해결할 수 없으므로 편집기에 오류가 표시됩니다.
-
일부 확장은 다른 확장에서 데이터를 가져올 수 있습니다. 그룹 서비스가 사용자 서비스에 액세스해야 할 수도 있습니다. 여기가 까다로울 수 있습니다.
-
두 번째 방법 :
각 확장을 API src 폴더의 하위 폴더 안에 보관하십시오. 그러나이 하위 폴더를 .gitignore 파일에 추가하십시오. 이제 확장을 API 안에 유지할 수 있습니다.
-
찬성 :
-
편집자가 종속성을 해결할 수 있습니다
-
코드를 배포하기 전에 build 명령을 실행할 수 있으며 단일 배포가 가능합니다
-
다른 서비스에 쉽게 액세스 할 수 있습니다 (
/groups
ID별로 사용자를 찾아야 함)
-
-
단점 :
- 개발할 때 해당 하위 폴더 안에 리포지토리 파일을 복사해야합니다. 무언가를 변경 한 후에는 이러한 파일을 다시 복사하고 업데이트 된 파일로 저장소 파일을 대체해야합니다.
세 번째 접근 방식 :
외부 사용자 정의 폴더 내에서 모든 확장은 완전한 독립형 API입니다. 기본 API는 인증 기능을 제공하고 들어오는 요청을 대상 API로 리디렉션하는 프록시 역할을 할 수 있습니다.
-
찬성 :
- 새로운 확장 기능을 쉽게 개발하고 테스트 할 수 있습니다
-
단점 :
-
배포가 까다로울 것입니다. 자체 프로세스를 시작하고 포트를 수신 하는 기본 API 및 n 개의 확장 API가 있습니다.
-
프록시 시스템은 까다로울 수 있습니다. 클라이언트가 요청한
/users
프록시가 해당 엔드 포인트를 수신하는 확장 API를 알아야하는 경우 해당 API를 호출하고 해당 응답을 클라이언트에 다시 전달합니다. -
확장 API를 보호하려면 (기본 API에서 인증을 처리 함) 프록시가 해당 API와 비밀을 공유해야합니다. 따라서 확장 API는 일치하는 비밀이 프록시에서 제공되는 경우에만 들어오는 요청을 전달합니다.
-
네 번째 접근 방식 :
마이크로 서비스가 도움이 될 수 있습니다. 나는 여기에서 가이드를했다 https://docs.nestjs.com/microservices/basics
사용자 관리, 그룹 관리 등에 대한 마이크로 서비스를 가질 수 있으며 마이크로 서비스를 호출하는 작은 API / 게이트웨이 / 프록시를 만들어 해당 서비스를 사용할 수 있습니다.
-
찬성 :
-
새로운 확장 기능을 쉽게 개발하고 테스트 할 수 있습니다
-
분리 된 우려
-
-
단점 :
-
배포가 까다로울 것입니다. 자체 프로세스를 시작하고 포트를 수신 하는 기본 API와 n 개의 마이크로 서비스가 있습니다.
-
커스터마이징 가능하게하려면 각 고객에 대해 새 게이트웨이 API를 만들어야 할 것 같습니다. 따라서 응용 프로그램을 확장하는 대신 매번 사용자 정의 된 Comsuming API를 작성해야합니다. 문제가 해결되지 않습니다.
-
확장 API를 보호하려면 (기본 API에서 인증을 처리 함) 프록시가 해당 API와 비밀을 공유해야합니다. 따라서 확장 API는 일치하는 비밀이 프록시에서 제공되는 경우에만 들어오는 요청을 전달합니다.
-
답변
이에 대한 몇 가지 접근법이 있습니다. 팀, 조직 및 고객에게 가장 적합한 워크 플로를 파악해야합니다.
이것이 나에게 달려 있다면 모듈 당 하나의 저장소를 사용하고 개인 또는 조직 범위의 패키지와 함께 NPM과 같은 패키지 관리자를 사용하여 구성을 처리하는 것이 좋습니다. 그런 다음 새 빌드에서 패키지 저장소로 푸시하는 빌드 릴리스 파이프 라인을 설정하십시오.
이 방법으로 주 파일과 사용자 정의 설치마다 패키지 매니페스트 파일 만 있으면됩니다. 독립적으로 새 버전을 개발하고 배포 할 수 있으며 클라이언트 측에서 필요할 때 새 버전을로드 할 수 있습니다.
유연성을 높이기 위해 구성 파일을 사용하여 모듈을 라우트에 매핑하고 대부분의 부트 스트랩을 수행하는 일반 라우트 생성기 스크립트를 작성할 수 있습니다.
패키지는 무엇이든 될 수 있으므로 패키지 내의 상호 종속성은 번거 로움없이 작동합니다. 변경 및 버전 관리와 관련하여 훈련을 받아야합니다.
개인 패키지에 대한 자세한 내용은 여기를 참조하십시오.
개인 패키지 NPM을 참조
이제 개인 NPM 레지스트리에 비용이 발생하지만 문제가되는 경우 다른 옵션도 있습니다. 무료 및 유료의 다른 대안에 대해서는이 기사를 검토하십시오.
이제 자신의 관리자를 롤링하려면 간단한 서비스 로케이터를 작성하면 필요한 정보가 포함 된 구성 파일을 작성하여 저장소에서 코드를 가져 와서로드 한 다음 일종의 메소드를 제공 할 수 있습니다. 그것에 인스턴스.
그러한 시스템에 대한 간단한 참조 구현을 작성했습니다.
프레임 워크 : 운동 서비스 로케이터
회문을 확인하는 플러그인 예제 : locomotion 플러그인 예제
프레임 워크를 사용하여 플러그인을 찾는 애플리케이션 : locomotion 앱 예제
npm에서 가져 와서이 문제를 해결할 수 있습니다 . 다음 스키마 npm install -s locomotion
를 사용하여 plugins.json
파일 을 지정해야합니다 .
{
"path": "relative path where plugins should be stored",
"plugins": [
{
"module":"name of service",
"dir":"location within plugin folder",
"source":"link to git repository"
}
]
}
예:
{
"path": "./plugins",
"plugins": [
{
"module": "palindrome",
"dir": "locomotion-plugin-example",
"source": "https://github.com/drcircuit/locomotion-plugin-example.git"
}
]
}
다음과 같이로드하십시오 : const loco = require ( “locomotion”);
그런 다음 서비스 로케이터 객체가있는 서비스 로케이터 객체를 해결하는 약속을 반환합니다.
loco.then((svc) => {
let pal = svc.locate("palindrome"); //get the palindrome service
if (pal) {
console.log("Is: no X in Nixon! a palindrome? ", (pal.isPalindrome("no X in Nixon!")) ? "Yes" : "no"); // test if it works :)
}
}).catch((err) => {
console.error(err);
});
이것은 단지 참조 구현 일 뿐이며 심각한 응용 프로그램에는 충분하지 않습니다. 그러나 패턴은 여전히 유효하며 이러한 종류의 프레임 워크를 작성하는 요점을 보여줍니다.
이제 플러그인 구성, 초기화, 오류 검사, 의존성 주입 지원 등을 지원하여 확장해야합니다.
답변
외부 패키지 옵션을 선택합니다.
packages
폴더 를 갖도록 앱을 구성 할 수 있습니다 . 해당 폴더에 외부 패키지의 UMD 컴파일 빌드가 있으므로 컴파일 된 유형 스크립트에 패키지 관련 문제가 없습니다. 모든 패키지에는 index.js
각 패키지의 루트 폴더에 파일이 있어야 합니다.
그리고 앱 사용하여 폴더 패키지를 통해 루프를 실행 fs
하고 require
모든 패키지index.js
귀하의 응용 프로그램에.
그런 다음 다시 종속성 설치가 처리해야합니다. 각 패키지의 구성 파일도 해결할 수 있다고 생각합니다. npm
응용 프로그램을 시작하기 전에 기본 응용 프로그램에 사용자 지정 스크립트를 사용하여 모든 패키지 종속성을 설치할 수 있습니다 .
이렇게하면 패키지를 패키지 폴더에 붙여넣고 앱을 재부팅하여 앱에 새 패키지를 추가 할 수 있습니다. 컴파일 된 타이프 스크립트 파일은 건드리지 않으며 자신의 패키지에 개인 npm을 사용할 필요가 없습니다.