가져오기
소개
개발할 때 우리는 여러 코드 파일을 서로 연결하여 사용해야 합니다. 그래야 기능을 정리하고 재사용하여 반복을 피할 수 있으며, 유용한 함수를 중앙화하여 유지보수를 쉽게 할 수 있습니다. 이는 전반적인 코드 줄 수를 줄이고 결과적으로 버그도 크게 줄여 줍니다.
그래서 유용한 코드를 다른 코드 파일에 중앙화하면, 다른 파일에서 이를 가져와 쉽게 재사용할 수 있습니다.
여기에서는 Netuno가 코드 재사용을 위해 제공하는 몇 가지 솔루션을 보여 줍니다.
폴리글랏 코어
Netuno가 지원하는 모든 프로그래밍 언어에서 애플리케이션의 server/core 폴더에 있는 모든 코드 파일을 가져올 수 있습니다.
Netuno가 제공하는 간단한 방식은 코드 가져오기를 위한 특수 주석 형식을 사용하는 것입니다. 주석 줄에 _core: 접두사를 붙이고, 이어서 애플리케이션의 server/core 폴더를 기준으로 한 코드 파일 경로를 작성합니다.
그래서 다음 코드 파일을 가져오려면:
server/core/예시/파일
파일 확장자는 사용하는 프로그래밍 언어에 맞아야 합니다.
서비스 등 모든 코드 파일의 시작 부분에서 다른 파일을 가져올 수 있습니다.
JavaScript, Groovy, Kotlin의 경우:
// _core: 예시/파일
...
Python과 Ruby의 경우:
# _core: 예시/파일
...
이 특수 가져오기 주석에는 파일 확장자를 넣을 필요가 없으며, Netuno가 자동으로 감지합니다.
가져온 파일에 선언된 변수, 상수, 함수, 클래스 등은 시작 부분에 이 유형의 주석으로 가져오기를 수행한 파일에서 사용할 수 있습니다.
여러 파일을 가져오려면 다른 파일의 경로로 가져오기 주석을 반복하면 됩니다.
JavaScript, Groovy, Kotlin에서 여러 파일을 가져오려면:
// _core: 예시/파일1
// _core: 예시/파일2
// _core: 예시/파일3
...
Python과 Ruby에서 여러 파일을 가져오려면:
# _core: 예시/파일1
# _core: 예시/파일2
# _core: 예시/파일3
...
Exec 리소스
_exec 리소스를 통해 실행 중 언제든지 코드를 가져올 수 있습니다.
가져온 코드 파일에 선언된 변수, 상수, 함수, 클래스 등을 사용할 수 있습니다.
core
프로그래밍 방식으로 코드 파일 가져오기를 실행합니다. 이 경우 📁 server/core 폴더 내부입니다:
_exec.core('경로/파일')
파일 확장자는 넣을 필요가 없으며 Netuno가 자동으로 감지합니다.
services
프로그래밍 방식으로 코드 파일 가져오기를 실행합니다. 이 경우 📁 server/services 폴더 내부입니다:
_exec.service('경로/파일')
파일 확장자는 넣을 필요가 없으며 Netuno가 자동으로 감지합니다.
JavaScript
Netuno는 JavaScript 개발을 위한 기반을 제공합니다. JavaScript는 가장 많이 사용되는 언어이며, 특히 JavaScript로 프런트엔드와 백엔드를 모두 프로그래밍할 수 있어 동일한 프로그래밍 언어로 풀스택 개발을 수행할 수 있습니다.
Netuno는 코드를 분석하여 import(ECMAScript Modules) 또는 require(CommonJS)가 사용되는지 자동으로 감지합니다.
import방식과require방식을 혼용해서는 안 되며, 둘 중 하나를 사용해야 합니다.
따라서 항상 코드 파일에 .js 확장자를 사용할 수 있으며, import 문을 사용하면 Netuno가 ECMAScript Modules로 처리하므로 export default를 사용할 수 있습니다.
가능하면 현대적인 표준인
import사용을 권장합니다.
코드 가져오기
네이티브 가져오기를 사용하면 앞선 예시와 달리 CommonJS(require) 또는 ECMAScript Modules(import) 표준에 따라 명시적으로 내보낸 것만 가져옵니다.
📁 server 폴더에는 package.json 파일이 있으며, 여기에 다음 지시문이 있어야 합니다:
...
"imports": {
"#actions/*": {
"default": "./actions/*"
},
"#components/*": {
"default": "./components/*"
},
"#core/*": {
"default": "./core/*"
},
"#reports/*": {
"default": "./reports/*"
},
"#services/*": {
"default": "./services/*"
},
"#setup/*": {
"default": "./setup/*"
},
"#templates/*": {
"default": "./templates/*"
}
},
...
이를 통해 모든 코드 파일에서 다른 파일을 가져올 수 있습니다. 예:
import 프로필 from "#core/lib/프로필.js";
const db프로필 = 프로필.로그인된프로필();
가져온 파일에서 import를 사용했으므로 export default를 사용합니다:
import {_db, _user} from "@netuno/server-types";
export default {
로그인된프로필: () => {
return _db.form("프로필")
.where(_db.where("프로필_사용자_아이디").equal(_user.id))
.first();
}
};
같은 애플리케이션 또는 프로젝트에서 서로 다른 파일이나 상황이더라도
import(ECMAScript Modules)와require(CommonJS) 사용을 혼용하는 것은 권장되지 않습니다. 항상 일관된 표준을 채택하는 것이 좋습니다. 현대적인 방식인import사용을 권장합니다.
대안으로 import(ECMAScript Modules) 대신 require(CommonJS)를 사용하는 경우:
const 프로필 = require("#core/lib/프로필.js");
const db프로필 = 프로필.로그인된프로필();
가져온 파일에서 require를 사용했으므로 module.exports를 사용합니다:
const {_db, _user} = require("@netuno/server-types");
module.exports = {
로그인된프로필: () => {
return _db.form("프로필")
.where(_db.where("프로필_사용자_아이디").equal(_user.id))
.first();
}
};
코드 자동 완성 및 유효성 검사
편집기에 통합된 코드 유효성 검사와 함께 코드 자동 완성 기능을 사용하려면, 애플리케이션의 📁 server 폴더에서 서버 타입을 설치해야 합니다.
서버 타입(
@netuno/server-types)은 TypeScript로 작성된 모든 폴리글랏 로우코드 프로그래밍 리소스 정의입니다. 이를 통해 편집기는 Netuno의 폴리글랏 로우코드 프레임워크가 제공하는 모든 것을 감지할 수 있습니다. 다만 TypeScript이므로 JavaScript 코드 작성을 돕는 용도로만 사용됩니다.
📁 server 폴더 안에서 서버 타입을 설치하세요:
bun add @netuno/server-types
이를 통해 일반 코드에서 Netuno 프레임워크에서 사용 가능한 폴리글랏 로우코드 리소스 중 하나를 가져올 수 있습니다. 예를 들어 다음 서비스 코드를 보세요:
import {_req, _db, _out, _val} from "@netuno/server-types";
const 이름 = _req.getString("이름");
_db.form("제품")
.set("이름", 이름)
.insert();
_out.json(
_val.map()
.set("이름", 이름)
.set("결과", true)
);
편집기가 코드를 유효성 검사하고 자동 완성하는 것을 확인할 수 있으며, 이는 매우 유용하고 개발 속도를 크게 높여 줍니다.
일부 편집기에서는
📁 server폴더를 코드 루트로 감지하기 위해 구성/활성화가 필요할 수 있습니다. 예를 들어 Visual Studio Code에서는 자동으로 감지하지만, WebStorm에서는server폴더를 마우스 오른쪽 버튼으로 클릭하고Mark Directory As > Resource Root를 클릭한 뒤 프로젝트를 다시 열어야 합니다.
JS & NPM - 외부 의존성
NPM 외부 의존성은 애플리케이션 내 package.json이 있는 📁 server 폴더에 설치할 수 있습니다.
하지만 앞서 권장한 것과 달리, 외부 라이브러리를 가져올 때는 require를 사용하며, 이 경우 프로젝트 내부 파일의 import와 혼용할 수 있습니다. 그다지 우아하진 않지만 가능합니다.
따라서 의존성을 추가하려면 bun add 명령으로 설치하면 됩니다.
예를 들어 momentjs를 설치할 수 있습니다:
bun add moment
의존성을 가져올 때는 require를 사용합니다. 예시는 다음과 같습니다:
import {_out} from "@netuno/server-types";
const moment = require('moment')
_out.json(moment().format())
dayjs를 사용한 또 다른 예시입니다. 먼저 설치하세요:
bun add dayjs
import {_out} from "@netuno/server-types";
const dayjs = require("dayjs");
_out.json(dayjs().format());
date-fns를 사용한 전체 예시입니다. 먼저 설치하세요:
bun add date-fns
import {_out} from "@netuno/server-types";
import 프로필 from "#core/lib/프로필.js";
const db프로필 = 프로필.로그인된프로필();
const { formatDistance, subDays } = require('date-fns');
_out.println(formatDistance(
subDays(new Date(), 3), new Date(), { addSuffix: true }
));
외부 라이브러리에 의존하는 것은 예외적인 상황이며, 일반적으로 필요한 모든 것은 Netuno의 폴리글랏 로우코드 프레임워크에서 찾을 수 있습니다.
NodeJS 네이티브 모듈
GraalVM은 NodeJS 네이티브 모듈과 완전히 호환되지 않으므로, 이를 우회하기 위해 이러한 모듈에 대한 대체 솔루션을 구현한 외부 의존성을 사용하면 더 높은 호환성을 얻을 수 있습니다.
네이티브 모듈인 것처럼 호환성을 제공하는 대체 외부 의존성을 설치할 수 있습니다.
다음은 NodeJS 네이티브 모듈을 대체하는 데 사용되는 모듈 목록과 각각의 설치 명령입니다:
- Buffer:
bun add buffer - Events:
bun add events - Util:
bun add util - Path:
bun add path-browserify - Stream:
bun add stream-browserify - HTTP:
bun add http-browserify - HTTPS:
bun add https-browserify
위 모듈은 애플리케이션 내 📁 server 폴더에 설치해야 합니다. NodeJS 네이티브 모듈에 대한 호환성이 제공되며, 이러한 대체 모듈이 사용됩니다.
결론
우리는 코드를 여러 방식으로 정리할 수 있지만, 코드를 재사용하고 반복을 피하는 것은 항상 매우 중요합니다.
코드 줄이 많을수록 버그가 발생할 가능성도 커집니다.
코드를 잘 정리하고 재사용을 중앙화하세요. 유지보수가 쉬워지고 버그를 피할 수 있으며 전반적인 생산성이 높아집니다.
외부 의존성 사용에 아직 몇 가지 제한이 있지만, 생태계를 개선하기 위해 작업하고 있습니다.
그동안 Netuno는 대부분의 요구 사항을 충족하는 다양한 로우코드 및 폴리글랏 리소스를 제공합니다.