Azure Functions Node.js 개발자 가이드
이 가이드는 JavaScript 또는 TypeScript를 사용하여 Azure Functions를 개발하는 방법을 소개합니다. 이 문서에서는 Azure Functions 개발자 가이드를 이미 읽었다고 가정합니다.
Important
이 문서의 콘텐츠는 이 페이지 상단의 선택기에서 선택한 Node.js 프로그래밍 모델에 따라 변경됩니다. 선택한 버전은 앱에서 사용 중인 @azure/functions
npm 패키지의 버전과 일치해야 합니다. package.json
에 나열된 해당 패키지가 없는 경우 기본값은 v3입니다. 마이그레이션 가이드에서 v3과 v4의 차이점에 대해 자세히 알아봅니다.
Node.js 개발자는 다음 문서 중 하나에 관심이 있을 수도 있습니다.
시작하기 | 개념 | 학습 도우미 |
---|---|---|
고려 사항
- Node.js 프로그래밍 모델을 Azure Functions 런타임과 혼동하면 안 됩니다.
- 프로그래밍 모델: 코드를 작성하는 방법을 정의하고 JavaScript 및 TypeScript에만 적용됩니다.
- 런타임: Azure Functions의 기본 동작을 정의하고 모든 언어에서 공유됩니다.
- 프로그래밍 모델 버전은
@azure/functions
npm 패키지 버전과 엄격하게 연결되어 있습니다. 런타임과 독립적으로 버전이 지정됩니다. 런타임과 프로그래밍 모델 모두 최신 주 버전으로 숫자 4를 사용하지만 이는 우연의 일치입니다. - 동일한 함수 앱에서 v3 및 v4 프로그래밍 모델을 혼합할 수 없습니다. 앱에 하나의 v4 함수를 등록하는 즉시 function.json 파일에 등록된 모든 v3 함수는 무시됩니다.
지원되는 버전
다음 표에는 지원되는 Azure Functions 런타임 및 Node.js 버전과 함께 Node.js 프로그래밍 모델의 각 버전이 나와 있습니다.
프로그래밍 모델 버전 | 지원 수준 | Functions 런타임 버전 | Node.js 버전 | 설명 |
---|---|---|---|---|
4.x | GA | 4.25+ | 20.x, 18.x | 유연한 파일 구조와 트리거 및 바인딩에 대한 코드 중심 방식을 지원합니다. |
3.x | GA | 4.x | 20.x, 18.x, 16.x, 14.x | "function.json" 파일에 선언된 트리거 및 바인딩이 포함된 특정 파일 구조가 필요합니다. |
2.x | 해당 없음 | 3.x | 14.x, 12.x, 10.x | 2022년 12월 13일에 지원이 종료되었습니다. 자세한 내용은 함수 버전을 참조하세요. |
1.x | 해당 없음 | 2.x | 10.x, 8.x | 2022년 12월 13일에 지원이 종료되었습니다. 자세한 내용은 함수 버전을 참조하세요. |
폴더 구조
JavaScript 프로젝트에 필요한 폴더 구조는 다음 예제와 같습니다.
<project_root>/
| - .vscode/
| - node_modules/
| - myFirstFunction/
| | - index.js
| | - function.json
| - mySecondFunction/
| | - index.js
| | - function.json
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
기본 프로젝트 폴더(<project_root>)에는 다음 파일이 포함될 수 있습니다.
- .vscode/:(선택 사항) 저장된 Visual Studio Code 구성을 포함합니다. 자세한 내용은 Visual Studio Code 설정을 참조하세요.
- myFirstFunction/function.json: 함수의 트리거, 입력 및 출력에 대한 구성을 포함합니다. 디렉터리 이름에 따라 함수 이름이 결정됩니다.
- myFirstFunction/index.js: 함수 코드를 저장합니다. 이 기본 파일 경로를 변경하려면 scriptFile 사용을 참조하세요.
- .funcignore: (선택 사항) Azure에 게시하면 안 되는 파일을 선언합니다. 일반적으로 이 파일에는 편집기 설정을 무시하는 .vscode/, 테스트 사례를 무시하는 test/ 및 로컬 앱 설정을 게시하지 않도록 하는 local.settings.json이 포함되어 있습니다.
- host.json: 함수 앱 인스턴스의 모든 함수에 영향을 미치는 구성 옵션이 포함되어 있습니다. 이 파일은 Azure에 게시됩니다. 로컬로 실행할 경우 일부 옵션이 지원되지 않습니다. 자세한 내용은 host.json을 참조하세요.
- local.settings.json: 로컬에서 실행될 때 앱 설정과 연결 문자열을 저장하는 데 사용됩니다. 이 파일은 Azure에 게시되지 않습니다. 자세한 내용은 local.settings.file을 참조하세요.
- package.json: 패키지 종속성 목록, 기본 진입점 및 스크립트와 같은 구성 옵션을 포함합니다.
JavaScript 프로젝트에 권장되는 폴더 구조는 다음 예와 같습니다.
<project_root>/
| - .vscode/
| - node_modules/
| - src/
| | - functions/
| | | - myFirstFunction.js
| | | - mySecondFunction.js
| - test/
| | - functions/
| | | - myFirstFunction.test.js
| | | - mySecondFunction.test.js
| - .funcignore
| - host.json
| - local.settings.json
| - package.json
기본 프로젝트 폴더(<project_root>)에는 다음 파일이 포함될 수 있습니다.
- .vscode/:(선택 사항) 저장된 Visual Studio Code 구성을 포함합니다. 자세한 내용은 Visual Studio Code 설정을 참조하세요.
- src/functions/: 모든 함수와 관련 트리거 및 바인딩의 기본 위치입니다.
- tests/: (선택 사항) 함수 앱의 테스트 사례를 포함합니다.
- .funcignore: (선택 사항) Azure에 게시하면 안 되는 파일을 선언합니다. 일반적으로 이 파일에는 편집기 설정을 무시하는 .vscode/, 테스트 사례를 무시하는 test/ 및 로컬 앱 설정을 게시하지 않도록 하는 local.settings.json이 포함되어 있습니다.
- host.json: 함수 앱 인스턴스의 모든 함수에 영향을 미치는 구성 옵션이 포함되어 있습니다. 이 파일은 Azure에 게시됩니다. 로컬로 실행할 경우 일부 옵션이 지원되지 않습니다. 자세한 내용은 host.json을 참조하세요.
- local.settings.json: 로컬에서 실행될 때 앱 설정과 연결 문자열을 저장하는 데 사용됩니다. 이 파일은 Azure에 게시되지 않습니다. 자세한 내용은 local.settings.file을 참조하세요.
- package.json: 패키지 종속성 목록, 기본 진입점 및 스크립트와 같은 구성 옵션을 포함합니다.
함수 등록
v3 모델은 두 파일의 존재에 따라 함수를 등록합니다. 먼저 앱의 루트에서 한 수준 아래 폴더에 있는 function.json
파일이 필요합니다. 둘째, 함수를 내보내는 JavaScript 파일이 필요합니다. 기본적으로 모델은 function.json
와 동일한 폴더에 있는 index.js
파일을 찾습니다. TypeScript를 사용하는 경우 function.json
의 scriptFile
속성을 사용하여 컴파일된 JavaScript 파일을 가리켜야 합니다. 함수의 파일 위치 또는 내보내기 이름을 사용자 지정하려면 함수의 진입점 구성을 참조하세요.
내보내는 함수는 항상 v3 모델에서 async function
로 선언되어야 합니다. 동기 함수를 내보낼 수 있지만 context.done()
를 호출하여 함수가 완료되었다는 신호를 보내야 합니다. 이는 사용되지 않으며 권장되지 않습니다.
함수는 첫 번째 인수로 호출 context
를 전달하고 나머지 인수로 입력을 전달합니다.
다음 예는 트리거되었음을 로그하고 Hello, world!
로 응답하는 간단한 함수입니다.
{
"bindings": [
{
"type": "httpTrigger",
"direction": "in",
"name": "req",
"authLevel": "anonymous",
"methods": [
"get",
"post"
]
},
{
"type": "http",
"direction": "out",
"name": "res"
}
]
}
module.exports = async function (context, request) {
context.log('Http function was triggered.');
context.res = { body: 'Hello, world!' };
};
프로그래밍 모델은 package.json
의 main
필드를 기반으로 함수를 로드합니다. GLOB 패턴을 사용하여 main
필드를 단일 파일 또는 여러 파일로 설정할 수 있습니다. 다음 표에서는 main
필드의 예제 값을 보여 줍니다.
예제 | 설명 |
---|---|
src/index.js |
단일 루트 파일에서 함수를 등록합니다. |
src/functions/*.js |
자체 파일에서 각 함수를 등록합니다. |
src/{index.js,functions/*.js} |
자체 파일에서 각 함수를 등록하지만 일반 앱 수준 코드에 대한 루트 파일이 있는 조합입니다. |
함수를 등록하려면 @azure/functions
npm 모듈에서 app
개체를 가져와서 트리거 형식에 특정한 메서드를 호출해야 합니다. 함수를 등록할 때 첫 번째 인수는 함수 이름입니다. 두 번째 인수는 트리거, 처리기 및 기타 모든 입력 또는 출력에 대한 구성을 지정하는 options
개체입니다. 트리거 구성이 필요하지 않은 일부 경우 options
개체 대신 처리기를 두 번째 인수로 직접 전달할 수 있습니다.
해당 파일이 package.json
파일의 main
필드를 기반으로(직접 또는 간접적으로) 로드되는 한 프로젝트의 모든 파일에서 함수를 등록할 수 있습니다. 실행이 시작된 후에는 함수를 등록할 수 없으므로 함수를 전역 범위에 등록해야 합니다.
다음 예는 트리거되었음을 로그하고 Hello, world!
로 응답하는 간단한 함수입니다.
const { app } = require('@azure/functions');
app.http('helloWorld1', {
methods: ['POST', 'GET'],
handler: async (request, context) => {
context.log('Http function was triggered.');
return { body: 'Hello, world!' };
}
});
입력 및 출력
함수에는 트리거라는 기본 입력이 정확히 하나 있어야 합니다. 보조 입력 및/또는 출력을 가질 수도 있습니다. 입력 및 출력은 function.json
파일에서 구성되며 바인딩이라고도 합니다.
입력
입력은 direction
이 in
로 설정된 바인딩입니다. 트리거와 보조 입력 간의 주요 차이점은 트리거의 type
이 Trigger
로 끝나는 것입니다(예: blobTrigger
형식과 blob
형식 비교). 대부분의 함수는 트리거만 사용하며 많은 보조 입력 형식이 지원되지 않습니다.
입력은 다음과 같은 여러 가지 방법으로 액세스할 수 있습니다.
[권장] 함수에 전달된 인수:
function.json
에 정의된 것과 동일한 순서로 인수를 사용합니다.function.json
에 정의된name
속성은 조직을 위해 권장되지만 인수의 이름과 일치할 필요는 없습니다.module.exports = async function (context, myTrigger, myInput, myOtherInput) { ... };
context.bindings
의 속성:function.json
에 정의된name
속성과 일치하는 키를 사용합니다.module.exports = async function (context) { context.log("This is myTrigger: " + context.bindings.myTrigger); context.log("This is myInput: " + context.bindings.myInput); context.log("This is myOtherInput: " + context.bindings.myOtherInput); };
출력
출력은 direction
이 out
로 설정된 바인딩이며 다음과 같은 여러 가지 방법으로 설정할 수 있습니다.
[단일 출력에 권장] 값을 직접 반환: 비동기 함수를 사용하는 경우 값을 직접 반환할 수 있습니다. 다음 예제와 같이 출력 바인딩의
name
속성을$return
에서function.json
으로 변경해야 합니다.{ "name": "$return", "type": "http", "direction": "out" }
module.exports = async function (context, request) { return { body: "Hello, world!" }; }
[여러 출력에 권장] 모든 출력을 포함하는 개체 반환: 비동기 함수를 사용하는 경우
function.json
의 각 바인딩 이름과 일치하는 속성이 있는 개체를 반환할 수 있습니다. 다음 예제에서는 "httpResponse" 및 "queueOutput"이라는 출력 바인딩을 사용합니다.{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; return { httpResponse: { body: message }, queueOutput: message }; };
context.bindings
에서 값 설정: 비동기 함수를 사용하지 않거나 이전 옵션을 사용하지 않으려는 경우 키가 바인딩 이름과 일치하는context.bindings
에서 직접 값을 설정할 수 있습니다. 다음 예제에서는 "httpResponse" 및 "queueOutput"이라는 출력 바인딩을 사용합니다.{ "name": "httpResponse", "type": "http", "direction": "out" }, { "name": "queueOutput", "type": "queue", "direction": "out", "queueName": "helloworldqueue", "connection": "storage_APPSETTING" }
module.exports = async function (context, request) { let message = 'Hello, world!'; context.bindings.httpResponse = { body: message }; context.bindings.queueOutput = message; };
바인딩 데이터 형식
입력 바인딩에서 dataType
속성을 사용하여 입력 유형을 변경할 수 있지만 몇 가지 제한 사항이 있습니다.
- Node.js에서는
string
및binary
만 지원됩니다(stream
은 지원되지 않음). - HTTP 입력의 경우
dataType
속성은 무시됩니다. 대신request
개체의 속성을 사용하여 원하는 형식으로 본문을 가져옵니다. 자세한 내용은 HTTP 요청을 참조하세요.
스토리지 큐 트리거의 다음 예제에서 myQueueItem
의 기본 형식은 string
이지만 dataType
을 binary
로 설정하면 형식이 Node.js Buffer
로 변경됩니다.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"queueName": "helloworldqueue",
"connection": "storage_APPSETTING",
"dataType": "binary"
}
const { Buffer } = require('node:buffer');
module.exports = async function (context, myQueueItem) {
if (typeof myQueueItem === 'string') {
context.log('myQueueItem is a string');
} else if (Buffer.isBuffer(myQueueItem)) {
context.log('myQueueItem is a buffer');
}
};
함수에는 트리거라는 기본 입력이 정확히 하나 있어야 합니다. 또한 보조 입력, 반환 출력이라고 하는 기본 출력 및/또는 보조 출력이 있을 수 있습니다. 입출력은 Node.js 프로그래밍 모델의 컨텍스트 외부에서 바인딩이라고도 합니다. 모델 v4 이전에는 이러한 바인딩이 function.json
파일에 구성되었습니다.
트리거 입력
트리거는 유일한 필수 입력 또는 출력입니다. 대부분의 트리거 형식의 경우 트리거 형식 다음에 이름이 지정된 app
개체의 메서드를 사용하여 함수를 등록합니다. options
인수에서 직접 트리거에 특정한 구성을 지정할 수 있습니다. 예를 들어, HTTP 트리거를 사용하면 경로를 지정할 수 있습니다. 실행 중에 이 트리거에 해당하는 값이 처리기의 첫 번째 인수로 전달됩니다.
const { app } = require('@azure/functions');
app.http('helloWorld1', {
route: 'hello/world',
handler: async (request, context) => {
...
}
});
반환 출력
반환 출력은 선택 사항이며 경우에 따라 기본적으로 구성됩니다. 예를 들어, app.http
에 등록된 HTTP 트리거는 HTTP 응답 출력을 자동으로 반환하도록 구성됩니다. 대부분의 출력 형식의 경우 @azure/functions
모듈에서 내보낸 output
개체의 도움으로 options
인수에 반환 구성을 지정합니다. 실행하는 동안 처리기에서 반환하여 이 출력을 설정합니다.
다음 예제에서는 타이머 트리거 및 스토리지 큐 출력을 사용합니다.
const { app, output } = require('@azure/functions');
app.timer('timerTrigger1', {
schedule: '0 */5 * * * *',
return: output.storageQueue({
connection: 'storage_APPSETTING',
...
}),
handler: (myTimer, context) => {
return { hello: 'world' }
}
});
추가 입력 및 출력
트리거 및 반환 외에도 함수를 등록할 때 options
인수에 추가 입력 또는 출력을 지정할 수 있습니다. @azure/functions
모듈에서 내보낸 input
및 output
개체는 구문을 구성하는 데 도움이 되는 형식별 메서드를 제공합니다. 실행 중에 context.extraInputs.get
또는 context.extraOutputs.set
를 사용하여 값을 가져오거나 설정하고 원래 구성 개체를 첫 번째 인수로 전달합니다.
다음 예는 추가 스토리지 Blob 출력에 복사되는 추가 스토리지 Blob 입력이 있는 스토리지 큐에 의해 트리거되는 함수입니다. 큐 메시지는 파일 이름이어야 하며 바인딩 식을 사용하여 복사할 Blob 이름으로 {queueTrigger}
를 대체합니다.
const { app, input, output } = require('@azure/functions');
const blobInput = input.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}',
});
const blobOutput = output.storageBlob({
connection: 'storage_APPSETTING',
path: 'helloworld/{queueTrigger}-copy',
});
app.storageQueue('copyBlob1', {
queueName: 'copyblobqueue',
connection: 'storage_APPSETTING',
extraInputs: [blobInput],
extraOutputs: [blobOutput],
handler: (queueItem, context) => {
const blobInputValue = context.extraInputs.get(blobInput);
context.extraOutputs.set(blobOutput, blobInputValue);
}
});
제네릭 입력 및 출력
@azure/functions
모듈에서 내보낸 app
, trigger
, input
및 output
개체는 대부분의 형식에 대해 형식별 메서드를 제공합니다. 지원되지 않는 모든 형식의 경우 구성을 수동으로 지정할 수 있도록 generic
메서드가 제공됩니다. 형식별 메서드에서 제공하는 기본 설정을 변경하려는 경우에도 generic
메서드를 사용할 수 있습니다.
다음 예는 형식별 메서드 대신 제네릭 메서드를 사용하는 간단한 HTTP 트리거 함수입니다.
const { app, output, trigger } = require('@azure/functions');
app.generic('helloWorld1', {
trigger: trigger.generic({
type: 'httpTrigger',
methods: ['GET', 'POST']
}),
return: output.generic({
type: 'http'
}),
handler: async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
return { body: `Hello, world!` };
}
});
호출 컨텍스트
함수의 각 호출은 입력을 읽고, 출력을 설정하고, 로그에 쓰고, 다양한 메타데이터를 읽는 데 사용되는 호출 context
개체를 전달합니다. v3 모델에서 컨텍스트 개체는 항상 처리기에 전달되는 첫 번째 인수입니다.
context
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
invocationId |
현재 함수 호출의 ID입니다. |
executionContext |
실행 컨텍스트를 참조하세요. |
bindings |
바인딩을 참조하세요. |
bindingData |
값 자체를 포함하지 않고 이 호출에 대한 트리거 입력에 대한 메타데이터입니다. 예를 들어 이벤트 허브 트리거에는 enqueuedTimeUtc 속성이 있습니다. |
traceContext |
분산 추적에 대한 컨텍스트입니다. 자세한 내용은 Trace Context 를 참조하세요. |
bindingDefinitions |
function.json 에 정의된 입력 및 출력의 구성입니다. |
req |
HTTP 요청을 참조하세요. |
res |
HTTP 응답을 참조하세요. |
context.executionContext
context.executionContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
invocationId |
현재 함수 호출의 ID입니다. |
functionName |
호출되는 함수의 이름입니다. function.json 파일이 포함된 폴더의 이름에 따라 함수 이름이 결정됩니다. |
functionDirectory |
function.json 파일이 포함된 폴더입니다. |
retryContext |
다시 시도 컨텍스트를 참조하세요. |
context.executionContext.retryContext
context.executionContext.retryContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
retryCount |
현재 재시도 시도를 나타내는 숫자입니다. |
maxRetryCount |
실행이 다시 시도되는 최대 횟수입니다. -1 값은 무기한으로 다시 시도하는 것을 의미합니다. |
exception |
다시 시도를 발생시킨 예외입니다. |
context.bindings
context.bindings
개체는 입력을 읽거나 출력을 설정하는 데 사용됩니다. 다음 예제는 context.bindings
를 사용하여 스토리지 Blob 입력을 스토리지 Blob 출력으로 복사하는 스토리지 큐 트리거입니다. 큐 메시지의 콘텐츠는 {queueTrigger}
바인딩 식을 사용하여 복사할 파일 이름으로 을 대체합니다.
{
"name": "myQueueItem",
"type": "queueTrigger",
"direction": "in",
"connection": "storage_APPSETTING",
"queueName": "helloworldqueue"
},
{
"name": "myInput",
"type": "blob",
"direction": "in",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}"
},
{
"name": "myOutput",
"type": "blob",
"direction": "out",
"connection": "storage_APPSETTING",
"path": "helloworld/{queueTrigger}-copy"
}
module.exports = async function (context, myQueueItem) {
const blobValue = context.bindings.myInput;
context.bindings.myOutput = blobValue;
};
context.done
context.done
메서드는 더 이상 사용되지 않습니다. 비동기 함수가 지원되기 전에 context.done()
을 호출하여 함수가 완료되었음을 알립니다.
module.exports = function (context, request) {
context.log("this pattern is now deprecated");
context.done();
};
이제 context.done()
에 대한 호출을 제거하고 함수를 비동기로 표시하여 프라미스를 반환하는 것이 좋습니다(await
를 수행하지 않는 경우라도). 함수가 완료되는 즉시(즉, 반환된 프라미스가 확인됨) v3 모델은 함수가 완료된 것을 알 수 있습니다.
module.exports = async function (context, request) {
context.log("you don't need context.done or an awaited call")
};
함수의 각 호출에는 로깅에 사용되는 호출 및 메서드에 대한 정보가 포함된 호출 context
개체가 전달됩니다. v4 모델에서 context
개체는 일반적으로 처리기에 전달되는 두 번째 인수입니다.
InvocationContext
클래스에는 다음 속성이 있습니다.
속성 | 설명 |
---|---|
invocationId |
현재 함수 호출의 ID입니다. |
functionName |
함수의 이름. |
extraInputs |
추가 입력 값을 가져오는 데 사용됩니다. 자세한 내용은 추가 입력 및 출력을 참조하세요. |
extraOutputs |
추가 출력 값을 설정할 때 사용합니다. 자세한 내용은 추가 입력 및 출력을 참조하세요. |
retryContext |
다시 시도 컨텍스트를 참조하세요. |
traceContext |
분산 추적에 대한 컨텍스트입니다. 자세한 내용은 Trace Context 를 참조하세요. |
triggerMetadata |
값 자체를 포함하지 않고 이 호출에 대한 트리거 입력에 대한 메타데이터입니다. 예를 들어 이벤트 허브 트리거에는 enqueuedTimeUtc 속성이 있습니다. |
options |
유효성을 검사하고 기본값을 명시적으로 지정한 후 함수를 등록할 때 사용되는 옵션입니다. |
다시 시도 컨텍스트
retryContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
retryCount |
현재 재시도 시도를 나타내는 숫자입니다. |
maxRetryCount |
실행이 다시 시도되는 최대 횟수입니다. -1 값은 무기한으로 다시 시도하는 것을 의미합니다. |
exception |
다시 시도를 발생시킨 예외입니다. |
자세한 내용은 retry-policies
를 참조하세요.
로깅
Azure Functions에서 context.log()
를 사용하여 로그를 작성하는 것이 좋습니다. Azure Functions는 Azure Application Insights와 통합되어 함수 앱 로그를 더 잘 캡처합니다. Azure Monitor의 일부인 Application Insights는 애플리케이션 로그와 추적 출력을 모두 수집하고, 시각적으로 렌더링하고, 분석하는 기능을 제공합니다. 자세한 내용은 Azure Functions 모니터링을 참조하세요.
참고 항목
대체 Node.js console.log
메서드를 사용하는 경우 해당 로그는 앱 수준에서 추적되며 특정 함수와 연결되지 않습니다. 모든 로그가 특정 함수와 연결되도록 console
대신 로깅에 context
를 사용하는 것이 적극 권장됩니다.
다음 예에서는 호출 ID를 포함하여 기존 "정보 수준"에서 로그를 작성합니다.
context.log(`Something has happened. Invocation ID: "${context.invocationId}"`);
로그 수준
기본 context.log
메서드 외에도 특정 수준에서 로그를 작성할 수 있는 다음 메서드를 사용할 수 있습니다.
메서드 | 설명 |
---|---|
context.log.error() |
로그에 오류 수준 이벤트를 씁니다. |
context.log.warn() |
로그에 경고 수준 이벤트를 씁니다. |
context.log.info() |
정보 수준 이벤트를 로그에 로그합니다. |
context.log.verbose() |
추적 수준 이벤트를 로그에 로그합니다. |
메서드 | 설명 |
---|---|
context.trace() |
추적 수준 이벤트를 로그에 로그합니다. |
context.debug() |
로그에 디버그 수준 이벤트를 씁니다. |
context.info() |
정보 수준 이벤트를 로그에 로그합니다. |
context.warn() |
로그에 경고 수준 이벤트를 씁니다. |
context.error() |
로그에 오류 수준 이벤트를 씁니다. |
로그 수준 구성
Azure Functions를 사용하면 로그를 추적하고 볼 때 사용할 임계값 수준을 정의할 수 있습니다. 임계값을 설정하려면 host.json
파일의 logging.logLevel
속성을 사용합니다. 이 속성을 사용하면 모든 함수에 적용되는 기본 수준 또는 각 개별 함수에 대한 임계값을 정의할 수 있습니다. 자세한 내용은 Azure Functions에 대한 모니터링을 구성하는 방법을 참조하세요.
사용자 지정 데이터 추적
기본적으로 Azure Functions는 Application Insights에 대한 추적으로 출력을 씁니다. 더 많은 제어를 위해 대신 Application Insights Node.js SDK를 사용하여 Application Insights 인스턴스에 사용자 지정 데이터를 보낼 수 있습니다.
const appInsights = require("applicationinsights");
appInsights.setup();
const client = appInsights.defaultClient;
module.exports = async function (context, request) {
// Use this with 'tagOverrides' to correlate custom logs to the parent function invocation.
var operationIdOverride = {"ai.operation.id":context.traceContext.traceparent};
client.trackEvent({name: "my custom event", tagOverrides:operationIdOverride, properties: {customProperty2: "custom property value"}});
client.trackException({exception: new Error("handled exceptions can be logged with this method"), tagOverrides:operationIdOverride});
client.trackMetric({name: "custom metric", value: 3, tagOverrides:operationIdOverride});
client.trackTrace({message: "trace message", tagOverrides:operationIdOverride});
client.trackDependency({target:"http://dbname", name:"select customers proc", data:"SELECT * FROM Customers", duration:231, resultCode:0, success: true, dependencyTypeName: "ZSQL", tagOverrides:operationIdOverride});
client.trackRequest({name:"GET /customers", url:"http://myserver/customers", duration:309, resultCode:200, success:true, tagOverrides:operationIdOverride});
};
tagOverrides
매개 변수는 operation_Id
를 함수의 호출 ID로 설정합니다. 이 설정을 사용하면 지정된 함수 호출에 대해 자동으로 생성된 모든 로그와 사용자 지정 로그를 연관시킬 수 있습니다.
HTTP 트리거
HTTP 및 웹후크 트리거는 요청 및 응답 개체를 사용하여 HTTP 메시지를 나타냅니다.
HTTP 및 웹후크 트리거는 HttpRequest
및 HttpResponse
개체를 사용하여 HTTP 메시지를 나타냅니다. 클래스는 Node.js의 undici
패키지를 사용하여 페치 표준의 하위 집합을 나타냅니다.
HTTP 요청
요청은 다음과 같은 여러 가지 방법으로 액세스할 수 있습니다.
함수의 두 번째 인수로:
module.exports = async function (context, request) { context.log(`Http function processed request for url "${request.url}"`);
context.req
속성에서:module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.req.url}"`);
명명된 입력 바인딩에서: 이 옵션은 HTTP가 아닌 바인딩과 동일하게 작동합니다.
function.json
의 바인딩 이름은context.bindings
의 키 또는 다음 예제의 "request1"과 일치해야 합니다.{ "name": "request1", "type": "httpTrigger", "direction": "in", "authLevel": "anonymous", "methods": [ "get", "post" ] }
module.exports = async function (context, request) { context.log(`Http function processed request for url "${context.bindings.request1.url}"`);
HttpRequest
개체의 속성은 다음과 같습니다.
속성 | Type | 설명 |
---|---|---|
method |
string |
이 함수를 호출하는 데 사용되는 HTTP 요청 메서드입니다. |
url |
string |
요청 URL. |
headers |
Record<string, string> |
HTTP 요청 헤더. 이 개체는 대/소문자를 구분합니다. 대신 대/소문자를 구분하지 않는 request.getHeader('header-name') 을 사용하는 것이 좋습니다. |
query |
Record<string, string> |
URL에서 문자열 매개 변수 키 및 값을 쿼리합니다. |
params |
Record<string, string> |
매개 변수 키 및 값을 라우팅합니다. |
user |
HttpRequestUser | null |
함수 인증, SWA 인증 또는 로그인한 사용자가 없는 경우 null을 통해 로그인한 사용자를 나타내는 개체입니다. |
body |
Buffer | string | any |
미디어 형식이 "application/octet-stream" 또는 "multipart/*"인 경우 body 는 Buffer입니다. 값이 JSON 구문 분석 가능 문자열인 경우 body 는 구문 분석된 개체입니다. 그렇지 않으면 body 가 문자열입니다. |
rawBody |
string |
문자열 본문입니다. 이름과 달리, 이 속성은 버퍼를 반환하지 않습니다. |
bufferBody |
Buffer |
버퍼로서의 본문입니다. |
요청은 HTTP 트리거 함수에 대한 처리기의 첫 번째 인수로 액세스할 수 있습니다.
async (request, context) => {
context.log(`Http function processed request for url "${request.url}"`);
HttpRequest
개체의 속성은 다음과 같습니다.
속성 | Type | 설명 |
---|---|---|
method |
string |
이 함수를 호출하는 데 사용되는 HTTP 요청 메서드입니다. |
url |
string |
요청 URL. |
headers |
Headers |
HTTP 요청 헤더. |
query |
URLSearchParams |
URL에서 문자열 매개 변수 키 및 값을 쿼리합니다. |
params |
Record<string, string> |
매개 변수 키 및 값을 라우팅합니다. |
user |
HttpRequestUser | null |
함수 인증, SWA 인증 또는 로그인한 사용자가 없는 경우 null을 통해 로그인한 사용자를 나타내는 개체입니다. |
body |
ReadableStream | null |
읽기 가능한 스트림으로서의 본문입니다. |
bodyUsed |
boolean |
본문을 이미 읽었는지 여부를 나타내는 부울입니다. |
요청 또는 응답의 본문에 액세스하려면 다음 방법을 사용할 수 있습니다.
메서드 | 반환 형식 |
---|---|
arrayBuffer() |
Promise<ArrayBuffer> |
blob() |
Promise<Blob> |
formData() |
Promise<FormData> |
json() |
Promise<unknown> |
text() |
Promise<string> |
참고 항목
본문 함수는 한 번만 실행할 수 있습니다. 후속 호출은 빈 문자열/ArrayBuffers로 해결됩니다.
HTTP 응답
응답은 다음과 같은 여러 가지 방법으로 설정할 수 있습니다.
context.res
속성을 설정합니다.module.exports = async function (context, request) { context.res = { body: `Hello, world!` };
응답 반환: 함수가 비동기이고 바인딩 이름을
$return
에서function.json
으로 설정한 경우context
에서 설정하는 대신 응답을 직접 반환할 수 있습니다.{ "type": "http", "direction": "out", "name": "$return" }
module.exports = async function (context, request) { return { body: `Hello, world!` };
명명된 입력 바인딩 설정: 이 옵션은 HTTP가 아닌 바인딩과 동일하게 작동합니다.
function.json
의 바인딩 이름은context.bindings
의 키 또는 다음 예제의 "response1"과 일치해야 합니다.{ "type": "http", "direction": "out", "name": "response1" }
module.exports = async function (context, request) { context.bindings.response1 = { body: `Hello, world!` };
context.res.send()
호출: 이 옵션은 사용되지 않습니다. 암시적으로context.done()
을 호출하며 비동기 함수에서 사용할 수 없습니다.module.exports = function (context, request) { context.res.send(`Hello, world!`);
응답을 설정할 때 새 개체를 만드는 경우 해당 개체는 다음 속성이 있는 HttpResponseSimple
인터페이스와 일치해야 합니다.
속성 | Type | 설명 |
---|---|---|
headers |
Record<string, string> (선택 사항) |
HTTP 응답 헤더. |
cookies |
Cookie[] (선택 사항) |
HTTP 응답 쿠키. |
body |
any (선택 사항) |
HTTP 응답 본문. |
statusCode |
number (선택 사항) |
HTTP 응답 상태 코드입니다. 설정하지 않으면 기본값은 200 입니다. |
status |
number (선택 사항) |
statusCode 와 동일합니다. statusCode 가 설정된 경우 이 속성은 무시됩니다. |
context.res
개체를 덮어쓰지 않고 수정할 수도 있습니다. 기본 context.res
개체는 HttpResponseSimple
속성 외에도 다음 메서드를 지원하는 HttpResponseFull
인터페이스를 사용합니다.
메서드 | 설명 |
---|---|
status() |
상태를 설정합니다. |
setHeader() |
헤더 필드를 설정합니다. 참고: res.set() 및 res.header() 도 지원되며 동일한 작업을 수행합니다. |
getHeader() |
헤더 필드를 가져옵니다. 참고: res.get() 도 지원되며 동일한 작업을 수행합니다. |
removeHeader() |
헤더를 제거합니다. |
type() |
"content-type" 헤더를 설정합니다. |
send() |
이 메서드는 더 이상 사용되지 않습니다. 본문을 설정하고 context.done() 을 호출하여 동기화 함수가 완료되었음을 나타냅니다. 참고: res.end() 도 지원되며 동일한 작업을 수행합니다. |
sendStatus() |
이 메서드는 더 이상 사용되지 않습니다. 상태 코드를 설정하고 context.done() 을 호출하여 동기화 함수가 완료되었음을 나타냅니다. |
json() |
이 메서드는 더 이상 사용되지 않습니다. "content-type"을 "application/json"으로 설정하고, 본문을 설정하고, context.done() 을 호출하여 동기화 함수가 완료되었음을 나타냅니다. |
응답은 다음과 같은 여러 가지 방법으로 설정할 수 있습니다.
HttpResponseInit
형식의 간단한 인터페이스: 이 옵션은 응답을 반환하는 가장 간결한 방법입니다.return { body: `Hello, world!` };
HttpResponseInit
인터페이스에는 다음과 같은 속성이 있습니다.속성 Type 설명 body
BodyInit
(선택 사항)ArrayBuffer
,AsyncIterable<Uint8Array>
,Blob
,FormData
,Iterable<Uint8Array>
,NodeJS.ArrayBufferView
,URLSearchParams
,null
또는string
중 하나인 HTTP 응답 본문.jsonBody
any
(선택 사항)JSON 직렬화 가능한 HTTP 응답 본문. 설정한 경우 이 속성을 위해 HttpResponseInit.body
속성이 무시됩니다.status
number
(선택 사항)HTTP 응답 상태 코드입니다. 설정하지 않으면 기본값은 200
입니다.headers
HeadersInit
(선택 사항)HTTP 응답 헤더. cookies
Cookie[]
(선택 사항)HTTP 응답 쿠키. HttpResponse
형식의 클래스로: 이 옵션은 헤더와 같은 응답의 다양한 부분을 읽고 수정하기 위한 도우미 메서드를 제공합니다.const response = new HttpResponse({ body: `Hello, world!` }); response.headers.set('content-type', 'application/json'); return response;
HttpResponse
클래스는 선택적HttpResponseInit
를 생성자에 대한 인수로 허용하며 다음과 같은 속성을 가집니다.속성 Type 설명 status
number
HTTP 응답 상태 코드입니다. headers
Headers
HTTP 응답 헤더. cookies
Cookie[]
HTTP 응답 쿠키. body
ReadableStream | null
읽기 가능한 스트림으로서의 본문입니다. bodyUsed
boolean
본문을 이미 읽었는지 여부를 나타내는 부울입니다.
HTTP 스트림
HTTP 스트림은 대용량 데이터 처리, OpenAI 응답 스트리밍, 동적 콘텐츠 제공 및 기타 핵심 HTTP 시나리오 지원을 더 쉽도록 하는 기능입니다. Node.js 함수 앱의 HTTP 엔드포인트에 대한 요청과 응답을 스트리밍할 수 있습니다. 앱에 HTTP를 통한 클라이언트와 서버 간의 실시간 교환 및 상호 작용이 필요한 시나리오에서 HTTP 스트림을 사용합니다. HTTP 스트림을 사용하면 HTTP를 사용할 때 앱에 대한 최고의 성능과 안정성을 가져올 수도 있습니다.
Important
v3 모델에서는 HTTP 스트림이 지원되지 않습니다. HTTP 스트리밍 기능을 사용하려면 v4 모델로 업그레이드합니다.
프로그래밍 모델 v4의 기존 HttpRequest
및 HttpResponse
형식은 스트림을 포함하여 메시지 본문을 처리하는 다양한 방법을 이미 지원합니다.
필수 조건
@azure/functions
npm 패키지 버전 4.3.0 이상.- Azure Functions 런타임 버전 4.28 이상.
- 올바른 런타임 버전이 포함된 Azure Functions Core Tools 버전 4.0.5530 이상 버전.
스트림 사용
Azure의 함수 앱과 로컬 프로젝트에서 HTTP 스트림을 사용하도록 설정하려면 다음 단계를 사용합니다.
대량의 데이터를 스트리밍하려는 경우 Azure에서
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
설정을 수정합니다. 허용되는 기본 최대 본문 크기는104857600
이며, 이는 요청 크기를 ~100MB로 제한합니다.로컬 개발의 경우 local.settings.json 파일에
FUNCTIONS_REQUEST_BODY_SIZE_LIMIT
도 추가합니다.기본 필드에 포함된 파일의 앱에 다음 코드를 추가합니다.
const { app } = require('@azure/functions'); app.setup({ enableHttpStream: true });
스트림 예제
이 예에서는 HTTP POST 요청을 통해 데이터를 수신하는 HTTP 트리거 함수와 함수가 이 데이터를 지정된 출력 파일로 스트리밍하는 것을 보여 줍니다.
const { app } = require('@azure/functions');
const { createWriteStream } = require('fs');
const { Writable } = require('stream');
app.http('httpTriggerStreamRequest', {
methods: ['POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
const writeStream = createWriteStream('<output file path>');
await request.body.pipeTo(Writable.toWeb(writeStream));
return { body: 'Done!' };
},
});
이 예에서는 수신되는 HTTP GET 요청에 대한 응답으로 파일 콘텐츠를 스트리밍하는 HTTP 트리거 함수를 보여 줍니다.
const { app } = require('@azure/functions');
const { createReadStream } = require('fs');
app.http('httpTriggerStreamResponse', {
methods: ['GET'],
authLevel: 'anonymous',
handler: async (request, context) => {
const body = createReadStream('<input file path>');
return { body };
},
});
스트림을 사용하여 즉시 실행 가능한 샘플 앱을 보려면 GitHub에서 이 예를 확인합니다.
스트림 고려 사항
- 스트림 사용으로 최대의 이점을 가져오려면
request.body
를 사용합니다. 본문을 항상 문자열로 반환하는request.text()
와 같은 메서드를 계속 사용할 수 있습니다.
후크
후크는 v3 모델에서 지원되지 않습니다. 후크를 사용하도록 v4 모델로 업그레이드합니다.
후크를 사용하여 Azure Functions 수명 주기의 여러 지점에서 코드를 실행합니다. 후크는 등록된 순서대로 실행되며 앱의 모든 파일에서 등록할 수 있습니다. 현재 후크의 범위는 "앱" 수준과 "호출" 수준의 두 가지입니다.
할당 후크
호출 후크는 함수 호출에 따라 preInvocation
후크 이전에 또는 postInvocation
후크 이후에 한 번 실행됩니다. 기본적으로 후크는 모든 트리거 형식에 대해 실행되지만 형식별로 필터링할 수도 있습니다. 다음 예제에서는 호출 후크를 등록하고 트리거 유형별로 필터링하는 방법을 보여 줍니다.
const { app } = require('@azure/functions');
app.hook.preInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`preInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
app.hook.postInvocation((context) => {
if (context.invocationContext.options.trigger.type === 'httpTrigger') {
context.invocationContext.log(
`postInvocation hook executed for http function ${context.invocationContext.functionName}`
);
}
});
후크 처리기에 대한 첫 번째 인수는 해당 후크 형식과 관련된 컨텍스트 개체입니다.
PreInvocationContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
inputs |
호출에 전달된 인수입니다. |
functionHandler |
호출에 대한 함수 처리기입니다. 이 값을 변경하면 함수 자체에 영향을 미칩니다. |
invocationContext |
함수에 전달된 호출 컨텍스트 개체입니다. |
hookData |
동일한 범위의 후크 간에 데이터를 저장하고 공유하는 데 권장되는 위치입니다. 다른 후크의 데이터와 충돌하지 않도록 고유한 속성 이름을 사용해야 합니다. |
PostInvocationContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
inputs |
호출에 전달된 인수입니다. |
result |
함수의 결과입니다. 이 값을 변경하면 함수의 전체 결과에 영향을 미칩니다. |
error |
함수에서 throw된 오류이거나, 오류가 없으면 null/undefined입니다. 이 값을 변경하면 함수의 전체 결과에 영향을 미칩니다. |
invocationContext |
함수에 전달된 호출 컨텍스트 개체입니다. |
hookData |
동일한 범위의 후크 간에 데이터를 저장하고 공유하는 데 권장되는 위치입니다. 다른 후크의 데이터와 충돌하지 않도록 고유한 속성 이름을 사용해야 합니다. |
앱 후크
앱 후크는 appStart
후크에서 시작하는 동안 또는 appTerminate
후크에서 종료하는 동안 앱 인스턴스당 한 번씩 실행됩니다. 앱 종료 후크는 실행 시간이 제한되어 있으며 모든 시나리오에서 실행되지는 않습니다.
Azure Functions 런타임은 현재 호출 외부의 컨텍스트 로깅을 지원하지 않습니다. Application Insights npm 패키지를 사용하여 앱 수준 후크 중에 데이터를 기록합니다.
다음 예에서는 앱 후크를 등록합니다.
const { app } = require('@azure/functions');
app.hook.appStart((context) => {
// add your logic here
});
app.hook.appTerminate((context) => {
// add your logic here
});
후크 처리기에 대한 첫 번째 인수는 해당 후크 형식과 관련된 컨텍스트 개체입니다.
AppStartContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
hookData |
동일한 범위의 후크 간에 데이터를 저장하고 공유하는 데 권장되는 위치입니다. 다른 후크의 데이터와 충돌하지 않도록 고유한 속성 이름을 사용해야 합니다. |
AppTerminateContext
개체의 속성은 다음과 같습니다.
속성 | 설명 |
---|---|
hookData |
동일한 범위의 후크 간에 데이터를 저장하고 공유하는 데 권장되는 위치입니다. 다른 후크의 데이터와 충돌하지 않도록 고유한 속성 이름을 사용해야 합니다. |
스케일링 및 동시성
기본적으로 Azure Functions는 애플리케이션의 부하를 자동으로 모니터링하면서 필요에 따라 Node.js에 사용할 추가 호스트 인스턴스를 만듭니다. Azure Functions는 QueueTrigger에 대한 메시지 보존 기간, 큐 크기 등의 기본 제공(사용자 구성 불가능) 임계값을 여러 트리거 유형에 사용하여 인스턴스를 추가할 시기를 결정합니다. 자세한 내용은 사용 계획 및 프리미엄 계획의 작동 방식을 참조하세요.
해당 스케일링 동작은 여러 Node.js 애플리케이션을 지원하기에 충분합니다. CPU에 바인딩된 애플리케이션의 경우 여러 언어 작업자 프로세스를 사용하여 성능을 향상시킬 수 있습니다. FUNCTIONS_WORKER_PROCESS_COUNT 애플리케이션 설정을 사용하여 호스트당 작업자 프로세스 수를 기본값 1에서 최대 10개까지 늘릴 수 있습니다. 그러면 Azure Functions는 이러한 작업자 사이에 동시 함수 호출을 균등하게 분산하려고 시도합니다. 이 동작은 CPU를 많이 사용하는 함수가 다른 함수의 실행을 차단할 가능성을 줄입니다. 이 설정은 수요를 충족하기 위해 애플리케이션의 크기를 조정할 때 Azure Functions가 만드는 각 호스트에 적용됩니다.
Warning
FUNCTIONS_WORKER_PROCESS_COUNT
설정을 사용할 때는 주의해야 합니다. 동일한 인스턴스에서 실행되는 여러 프로세스는 예측할 수 없는 동작을 유발하고 함수 로드 시간을 증가시킬 수 있습니다. 이 설정을 사용하는 경우 패키지 파일에서 실행하여 이러한 단점을 상쇄하는 것이 좋습니다.
노드 버전
함수에서 process.version
을 로깅하여 해당 런타임이 사용하는 현재 버전을 볼 수 있습니다. 각 프로그래밍 모델에서 지원하는 Node.js 버전 목록은 supported versions
를 참조하세요.
노드 버전 설정
Node.js 버전을 업그레이드하는 방법은 함수 앱이 실행되는 OS에 따라 달라집니다.
Windows에서 실행하는 경우 Node.js 버전은 WEBSITE_NODE_DEFAULT_VERSION
애플리케이션 설정에 따라 설정됩니다. 이 설정은 Azure CLI를 사용하거나 Azure Portal에서 업데이트할 수 있습니다.
Node.js 버전에 대한 자세한 내용은 지원되는 버전을 참조하세요.
Node.js 버전을 업그레이드하기 전에 함수 앱이 최신 버전의 Azure Functions 런타임에서 실행되고 있는지 확인합니다. 런타임 버전을 업그레이드해야 하는 경우 Azure Functions 버전 3.x에서 버전 4.x로 앱 마이그레이션을 참조하세요.
Azure CLI az functionapp config appsettings set
명령을 실행하여 Windows에서 실행되는 함수 앱의 Node.js 버전을 업데이트합니다.
az functionapp config appsettings set --settings WEBSITE_NODE_DEFAULT_VERSION=~20 \
--name <FUNCTION_APP_NAME> --resource-group <RESOURCE_GROUP_NAME>
그러면 지원되는 ~20
의 LTS 버전이 WEBSITE_NODE_DEFAULT_VERSION
애플리케이션 설정으로 설정됩니다.
변경한 후 함수 앱이 다시 시작됩니다. Node.js에 대한 Functions 지원에 대해 자세히 알아보려면 언어 런타임 지원 정책을 참조하세요.
환경 변수
환경 변수는 운영 비밀(연결 문자열, 키, 엔드포인트 등) 또는 프로파일링 변수와 같은 환경 설정에 유용할 수 있습니다. 로컬 및 클라우드 환경 모두에 환경 변수를 추가하고 함수 코드에서 process.env
를 통해 액세스할 수 있습니다.
다음 예제에서는 WEBSITE_SITE_NAME
환경 변수를 기록합니다.
module.exports = async function (context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
}
async function timerTrigger1(myTimer, context) {
context.log(`WEBSITE_SITE_NAME: ${process.env["WEBSITE_SITE_NAME"]}`);
}
로컬 개발 환경
로컬에서 실행할 때 함수 프로젝트에는 환경 변수를 Values
개체에 저장하는 local.settings.json
파일이 포함됩니다.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "",
"FUNCTIONS_WORKER_RUNTIME": "node",
"CUSTOM_ENV_VAR_1": "hello",
"CUSTOM_ENV_VAR_2": "world"
}
}
Azure 클라우드 환경
Azure에서 실행하는 경우 함수 앱을 통해 서비스 연결 문자열과 같은 애플리케이션 설정을 사용 및 설정할 수 있고, 실행 중에 해당 설정을 환경 변수로 노출할 수 있습니다.
함수 앱 설정을 추가, 업데이트 및 삭제할 수 있는 여러 가지 방법이 있습니다.
함수 앱 설정을 변경하려면 함수 앱을 다시 시작해야 합니다.
작업자 환경 변수
Node.js와 관련된 몇 가지 Functions 환경 변수가 있습니다.
languageWorkers__node__arguments
이 설정을 사용하면 Node.js 프로세스를 시작할 때 사용자 지정 인수를 지정할 수 있습니다. 디버그 모드로 작업자를 시작하는 데 로컬로 가장 자주 사용되지만 사용자 지정 인수가 필요한 경우 Azure에서도 사용할 수 있습니다.
Warning
가능하면 콜드 시작 시간에 부정적인 영향을 미칠 수 있으므로 Azure에서 languageWorkers__node__arguments
를 사용하지 마세요. 미리 준비된 작업자를 사용하는 대신 런타임은 사용자 지정 인수를 사용하여 새 작업자를 처음부터 시작해야 합니다.
logging__logLevel__Worker
이 설정은 Node.js 관련 작업자 로그의 기본 로그 수준을 조정합니다. 기본적으로 경고 또는 오류 로그만 표시되지만 information
또는 debug
로 설정하여 Node.js 작업자 문제를 진단할 수 있습니다. 자세한 내용은 로그 수준 구성을 참조하세요.
ECMAScript 모듈(미리 보기)
참고 항목
ECMAScript 모듈은 현재 Azure Functions의 Node.js 14 이상에서 미리 보기 기능입니다.
ECMAScript 모듈(ES 모듈)은 Node.js에 대한 새로운 공식 표준 모듈 시스템입니다. 지금까지 이 문서의 코드 샘플에서는 CommonJS 구문을 사용합니다. Node.js 14 이상에서 Azure Functions를 실행하는 경우 ES 모듈 구문을 사용하여 함수를 작성하도록 선택할 수 있습니다.
함수에서 ES 모듈을 사용하려면 .mjs
확장을 사용하도록 파일 이름을 변경합니다. 다음 index.mjs 파일 예제는 ES 모듈 구문을 사용하여 uuid
라이브러리를 가져오고 값을 반환하는 HTTP 트리거 함수입니다.
import { v4 as uuidv4 } from 'uuid';
async function httpTrigger1(context, request) {
context.res.body = uuidv4();
};
export default httpTrigger;
import { v4 as uuidv4 } from 'uuid';
async function httpTrigger1(request, context) {
return { body: uuidv4() };
};
app.http('httpTrigger1', {
methods: ['GET', 'POST'],
handler: httpTrigger1
});
함수 진입점 구성
function.json
속성과 scriptFile
및 entryPoint
는 내보낸 함수의 위치와 이름을 구성하는 데 사용할 수 있습니다. scriptFile
속성은 TypeScript를 사용할 때 필요하며 컴파일된 JavaScript를 가리켜야 합니다.
scriptFile
사용
기본적으로 JavaScript 함수는 해당하는 function.json
과 동일한 부모 디렉터리를 공유하는 index.js
파일에서 실행됩니다.
scriptFile
은 다음 예제와 같은 폴더 구조를 가져오는 데 사용할 수 있습니다.
<project_root>/
| - node_modules/
| - myFirstFunction/
| | - function.json
| - lib/
| | - sayHello.js
| - host.json
| - package.json
myFirstFunction
의 function.json
에는 실행할 내보낸 함수가 있는 파일을 가리키는 scriptFile
속성이 포함되어야 합니다.
{
"scriptFile": "../lib/sayHello.js",
"bindings": [
...
]
}
entryPoint
사용
v3 모델에서 함수를 찾아서 실행하려면 module.exports
를 사용하여 함수를 내보내야 합니다. 기본적으로 트리거되면 실행되는 함수는 해당 파일의 내보내기, run
이라는 이름의 내보내기 또는 index
라고 명명된 내보내기입니다. 다음 예제에서는 function.json
의 entryPoint
를 사용자 지정 값인 "logHello"로 설정합니다.
{
"entryPoint": "logHello",
"bindings": [
...
]
}
async function logHello(context) {
context.log('Hello, world!');
}
module.exports = { logHello };
로컬 디버깅
디버그 모드에서 Node.js 프로세스를 자동으로 시작하고 프로세스에 연결하는 로컬 디버깅에는 VS Code를 사용하는 것이 좋습니다. 자세한 내용은 함수를 로컬로 실행을 참조하세요.
디버깅을 위해 다른 도구를 사용하거나 디버그 모드에서 Node.js 프로세스를 수동으로 시작하려는 경우 local.settings.json의 Values
아래에 "languageWorkers__node__arguments": "--inspect"
를 추가합니다. --inspect
인수는 기본적으로 포트 9229에서 디버그 클라이언트를 수신 대기하도록 Node.js에게 지시합니다. 자세한 내용은 Node.js 디버깅 가이드를 참조하세요.
권장 사항
이 섹션에서는 따라야 하는 Node.js 앱에 대한 몇 가지 영향력 있는 패턴에 대해 설명합니다.
단일 vCPU App Service 계획 선택
App Service 계획을 사용하는 함수 앱을 만들 때 여러 vCPU가 있는 계획보다는 단일 vCPU 계획을 선택하는 것이 좋습니다. 현재 Functions는 단일 vCPU VM에서 Node.js 함수를 더 효율적으로 실행하며, 더 큰 VM을 사용해도 예상되는 성능 향상을 얻지 못합니다. 필요한 경우 더 많은 단일 vCPU VM 인스턴스를 추가하여 수동으로 스케일 아웃하거나 자동 스케일링을 사용하도록 설정할 수 있습니다. 자세한 내용은 수동 또는 자동으로 인스턴스 개수 조정을 참조하세요.
패키지 파일에서 실행
서버리스 호스팅 모델에서 Azure Functions를 개발하는 경우 사실상 콜드 부팅됩니다. 콜드 부팅은 함수 앱이 일정 시간 동안 작업하지 않은 후 처음으로 함수 앱을 시작하면 시작하는 데 더 오래 걸린다는 사실을 의미합니다. 특히 종속성 트리가 큰 Node.js 앱의 경우 콜드 스타트가 중요할 수 있습니다. 콜드 부팅 프로세스의 속도를 높이려면 가능한 경우 함수를 패키지 파일로 실행합니다. 많은 배포 방법이 기본적으로 이 모델을 사용하지만 대규모 콜드 부팅이 발생하는 경우 이 방식으로 실행되고 있는지 확인해야 합니다.
단일 정적 클라이언트 사용
Azure Functions 애플리케이션에서 서비스별 클라이언트를 사용하는 경우 연결 제한에 도달할 수 있으므로 모든 함수 호출에 새 클라이언트를 만들어서는 안 됩니다. 대신 전체 범위에서 단일 정적 클라이언트를 만듭니다. 자세한 내용은 Azure Functions에서 연결 관리를 참조하세요.
async
및 await
사용
Node.js로 Azure Functions를 작성하는 경우 async
및 await
키워드를 사용하여 코드를 작성해야 합니다. 콜백 대신 async
와 await
를 사용하거나 프라미스와 함께 .then
및 .catch
를 사용하여 코드를 작성하면 다음 두 가지 일반적인 문제를 방지할 수 있습니다.
- 잠재적으로 다른 함수 실행에 영향을 줄 수 있는 Node.js 프로세스 크래시를 유발하는 포착되지 않은 예외 발생
- 올바르게 대기하지 않는 비동기 호출로 인해
context.log
의 로그 누락과 같은 예기치 않은 동작이 발생합니다.
다음 예에서 비동기 메서드 fs.readFile
은 오류 우선 콜백 함수를 두 번째 매개 변수로 사용하여 호출됩니다. 이 코드는 앞에서 언급한 두 가지 문제를 모두 일으킵니다. 올바른 범위에서 명시적으로 포착되지 않은 예외는 전체 프로세스를 중단시킬 수 있습니다.(문제 #1). 콜백이 완료되었는지 확인하지 않고 반환한다는 것은 http 응답에 빈 본문(문제 #2)이 있을 수 있다는 것입니다.
// DO NOT USE THIS CODE
const { app } = require('@azure/functions');
const fs = require('fs');
app.http('httpTriggerBadAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
let fileData;
fs.readFile('./helloWorld.txt', (err, data) => {
if (err) {
context.error(err);
// BUG #1: This will result in an uncaught exception that crashes the entire process
throw err;
}
fileData = data;
});
// BUG #2: fileData is not guaranteed to be set before the invocation ends
return { body: fileData };
},
});
다음 예에서 비동기 메서드 fs.readFile
은 오류 우선 콜백 함수를 두 번째 매개 변수로 사용하여 호출됩니다. 이 코드는 앞에서 언급한 두 가지 문제를 모두 일으킵니다. 올바른 범위에서 명시적으로 포착되지 않은 예외는 전체 프로세스를 중단시킬 수 있습니다.(문제 #1). 콜백 범위를 벗어나 사용되지 않는 context.done()
메서드를 호출하면 파일을 읽기 전에 함수가 완료되었음을 알릴 수 있습니다(문제 #2). 이 예에서는 context.done()
를 너무 일찍 호출하면 Data from file:
로 시작하는 로그 항목이 누락됩니다.
// NOT RECOMMENDED PATTERN
const fs = require('fs');
module.exports = function (context) {
fs.readFile('./hello.txt', (err, data) => {
if (err) {
context.log.error('ERROR', err);
// BUG #1: This will result in an uncaught exception that crashes the entire process
throw err;
}
context.log(`Data from file: ${data}`);
// context.done() should be called here
});
// BUG #2: Data is not guaranteed to be read before the Azure Function's invocation ends
context.done();
}
async
및 await
키워드를 사용하여 이러한 문제를 모두 방지할 수 있습니다. Node.js 에코시스템의 대부분의 API는 어떤 형태로든 프라미스를 지원하도록 변환되었습니다. 예를 들어 v14부터 Node.js는 fs
콜백 API를 대체하는 fs/promises
API를 제공합니다.
다음 예제에서 함수 실행 중에 발생한 처리되지 않은 예외는 예외를 발생시킨 개별 호출에서만 실패합니다. await
키워드는 readFile
이후의 단계가 완료된 후에만 실행된다는 것을 의미합니다.
// Recommended pattern
const { app } = require('@azure/functions');
const fs = require('fs/promises');
app.http('httpTriggerGoodAsync', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: async (request, context) => {
try {
const fileData = await fs.readFile('./helloWorld.txt');
return { body: fileData };
} catch (err) {
context.error(err);
// This rethrown exception will only fail the individual invocation, instead of crashing the whole process
throw err;
}
},
});
async
및 await
를 사용하는 경우 context.done()
콜백도 호출할 필요가 없습니다.
// Recommended pattern
const fs = require('fs/promises');
module.exports = async function (context) {
let data;
try {
data = await fs.readFile('./hello.txt');
} catch (err) {
context.log.error('ERROR', err);
// This rethrown exception will be handled by the Functions Runtime and will only fail the individual invocation
throw err;
}
context.log(`Data from file: ${data}`);
}
문제 해결
Node.js 문제 해결 가이드를 참조하세요.
다음 단계
자세한 내용은 다음 리소스를 참조하세요.