함수에서 웹훅 실행하기
외부 함수(External Functions)는 웹훅 호출 앞뒤에 코드 로직을 결합하여 외부 시스템과 상호작용하는 방식입니다. 입력을 외부 API 형식으로 바꾸고, 응답을 해석하여 온톨로지 편집에 사용하거나, 앞선 결과에 따라 여러 요청을 실행할 수 있습니다. 읽기 요청의 결과를 Workshop에 일시적으로 표시하는 용도로도 사용할 수 있습니다.
미리 정의한 요청을 재사용하려면 웹훅을 함수에서 호출합니다. 요청 구성을 함수 코드에서 직접 제어하려면 소스가 제공하는 HTTP 클라이언트를 사용하는 별도 API 호출 방식도 있습니다. TypeScript v1, TypeScript v2 및 Python 함수는 각 언어의 소스 인터페이스를 통해 직접 API를 호출할 수 있으며, 외부 연결에 필요한 소스 설정은 여전히 필요합니다.
함수 버전별 사용 방식
| 실행 방식 | 구성 |
|---|---|
| TypeScript v1 | 웹훅이 있는 소스를 저장소에 가져와 생성된 소스의 webhook 메서드를 호출합니다. 소스와 웹훅에 API 이름이 필요합니다. |
| TypeScript v2, Python | 웹훅을 온톨로지 함수로 게시한 뒤 해당 함수를 저장소에 가져오고 OSDK로 호출합니다. |
| 코드 없이 함수 재사용 | 웹훅 자체를 함수로 게시하여 Workshop, OSDK, 함수 기반 액션 등에서 호출합니다. |
소스는 네트워크 경로와 인증 정보를 보관하고, 웹훅은 실행할 구조화된 요청을 정의합니다. TypeScript v1에서 @Query()는 읽기 전용이며 외부 시스템을 바꾸면 안 됩니다. 쓰기나 온톨로지 편집에는 @OntologyEditFunction()을 사용합니다. Read API 웹훅은 두 함수 유형에서 사용할 수 있지만 Write API 웹훅은 @OntologyEditFunction()에서만 사용할 수 있습니다.
사전 정의된 사전 API 요청 만들기
다음은 공개 Free Dictionary API에서 영어 단어의 뜻을 조회하는 구성 예입니다. 이 서비스는 Palantir와 무관한 외부 서비스이며 동작이 바뀔 수 있습니다. 운영용 서비스로서의 보증이나 권장 사례로 해석하지 않습니다.
REST API 소스
- Data Connection의
New Source에서REST API를 선택합니다. - Foundry 워커를 선택합니다. 이 예제는 공개 인터넷의 API에 연결하므로 직접 연결 정책을 사용합니다.
- 소스 이름과 저장할 프로젝트를 지정합니다.
Domains에api.dictionaryapi.dev를 추가합니다. 이 조회 예제에는 별도 인증 정보를 넣지 않습니다.Network Connectivity에서 해당 호스트의 포트443을 허용하는 외부 통신 정책을 연결합니다.- 저장 후 소스 API 이름을
MyDictionarySource로 설정합니다.
입력과 요청
소스 Overview에서 Create webhook을 선택하고 이름, 설명과 API 이름을 정합니다. 예제 API 이름은 getDefinition입니다. 소스 API 이름은 해당 이름 공간에서 유일해야 하고, 웹훅 API 이름은 소스 안에서 유일해야 합니다.
문자열 입력 wordToDefine을 추가합니다. 요청은 다음과 같이 구성합니다.
| 항목 | 값 |
|---|---|
| 메서드 | GET |
| 도메인 | https://api.dictionaryapi.dev |
| 상대 경로 | /api/v2/entries/en/ 뒤에 입력 wordToDefine을 참조합니다. |
| 요청 분류 | Read API |
응답 자료형
Test Connection에서 조회할 단어를 입력하여 응답을 확인할 수 있습니다. 응답의 최상위 값은 단어 항목의 배열이고, 각 항목의 meanings에는 품사와 정의가 들어갑니다. 출력 매개변수 dictionary_definitions를 만들고 해당 Call의 Whole response를 선택합니다. 아래 중첩 자료형을 구성하면 함수가 품사별 정의를 직접 읽을 수 있습니다.
| 위치 | 기대 자료형과 필드 |
|---|---|
dictionary_definitions | List of Record |
각 단어 Record의 meanings | List of Record |
각 meaning Record의 partOfSpeech | String |
각 meaning Record의 definitions | List of Record |
각 definition Record의 definition | String |
이렇게 필요한 필드를 자료형으로 정의하면 입력과 출력의 코드 바인딩도 해당 구조를 반영합니다. 응답에 기대한 필드가 없으면 파싱 오류가 발생할 수 있으므로, 비어 있는 값으로 대체하여 성공 처리하지 않습니다.
TypeScript v1에서 호출
소스의 Code Repositories 가져오기를 허용하고 함수 저장소의 Resource imports > Add > Sources에서 소스를 가져옵니다. API 이름이 있는 소스만 선택할 수 있습니다. 이 TypeScript v1 웹훅 경로에서는 모든 함수 실행 환경에서 반출 가능한 보안 표지를 검증할 수 없으므로, 소스의 Enable exports에서 보안 표지 검증 없는 내보내기를 허용해야 합니다. 먼저 해당 반출 구성이 조직의 보안 정책에 맞는지 확인합니다.
다음 함수는 조회 요청을 실행하고 실제 응답의 품사별 정의를 문자열 목록으로 반환합니다. 예제에서 생성된 바인딩 이름은 MyDictionarySource.webhooks.GetDefinition입니다. 실제 저장소의 생성 식별자가 다르면 그 식별자를 사용합니다.
import { Query, isOk } from "@foundry/functions-api";
import { MyDictionarySource } from "@foundry/external-systems/sources";
export class DictionaryFunctions {
@Query()
public async defineWord(wordToDefine: string): Promise<string[]> {
const result = await MyDictionarySource.webhooks.GetDefinition.call({
wordToDefine,
});
if (!isOk(result)) {
throw new Error(`${result.error.name}: ${result.error.message}`);
}
const definitions: string[] = [];
for (const entry of result.value.output.dictionary_definitions) {
for (const meaning of entry.meanings) {
for (const definition of meaning.definitions) {
definitions.push(`${meaning.partOfSpeech}: ${definition.definition}`);
}
}
}
return definitions;
}
}
Cannot find module '@foundry/external-systems' or its corresponding type declarations. 오류가 발생하면 functions-typescript/functions.json의 enableExternalSystems가 true인지 확인하고 변경을 커밋합니다. 필요한 외부 시스템 패키지가 설치되어야 합니다.
코드를 게시하면 그 시점의 최신 웹훅 버전이 함수에 고정됩니다. 저장소의 자동 완성은 최신 웹훅 바인딩을 보여 주므로, 웹훅 수정 후 기존 게시 함수가 자동으로 새 버전을 사용한다고 가정하지 않습니다. 변경을 적용하려면 함수를 다시 게시하고 호출자가 사용할 함수 버전도 갱신합니다.
결과와 오류 처리
TypeScript v1의 webhook 메서드는 성공 또는 오류를 담은 Result를 반환합니다. isOk로 성공을 확인하면 result.value.output을 읽을 수 있고, 실패하면 result.error.name과 message를 확인합니다.
| 오류 이름 | 의미 |
|---|---|
WebhookExecutionFailedToStart | 실행을 시작하지 못했습니다. 외부 요청이 전송되지 않았다고 판단할 수 있습니다. |
WebhookExecutionTimedOut | 실행은 시작했지만 제한 시간 안에 외부 응답을 받지 못했습니다. |
RemoteRestApiReturnedError | REST API 소스의 외부 요청이 오류를 반환했습니다. 사전 API에서 단어를 찾지 못하는 경우도 여기에 해당할 수 있습니다. |
RemoteApiReturnedError | REST API가 아닌 소스의 외부 요청이 오류를 반환했습니다. |
ParsingResponseFailed | 외부 요청은 성공했지만 응답을 기대한 출력 구조로 해석하지 못했습니다. |
ServerError | 웹훅 서비스 또는 커넥터 내부 문제입니다. |
UnknownError | 특정 Foundry 서비스의 문제로 분류되지 않은 오류입니다. |
새 오류 이름이 추가될 수 있으므로 알려진 이름만 처리하고 나머지를 성공으로 넘기지 않습니다. 위 함수는 모든 실패 Result를 오류로 전달합니다.
Query 함수는 화면 로드 중 실행되거나 재시도될 수 있으므로 외부 변경을 수행하는 웹훅을 호출하지 않습니다. 외부 시스템 쓰기와 온톨로지 편집을 함께 수행하는 함수에서도 외부 쓰기가 성공한 뒤 온톨로지 편집이 실패할 수 있습니다. 두 시스템이 하나의 원자적 트랜잭션으로 묶인다고 가정해서는 안 됩니다.
웹훅 자체를 함수로 게시
TypeScript v2나 Python에서 사용할 때는 웹훅의 Function configuration을 활성화하고 온톨로지 및 함수 API 이름을 정합니다. 게시 후 함수 저장소에 해당 함수를 가져오고 OSDK가 제공하는 함수 호출 인터페이스로 wordToDefine을 전달합니다. 출력은 웹훅에 정의한 dictionary_definitions 구조입니다.
이 경로는 별도의 TypeScript v1 래퍼가 없어도 사용할 수 있습니다. 같은 게시 함수를 Workshop이나 함수 기반 액션에 연결할 수도 있습니다. 함수 게시의 비가역성과 실행 제한은 웹훅 설정 참조에 적용됩니다. 함수의 리소스 제한과 웹훅의 시간, 동시 실행 및 호출 횟수 제한도 함께 적용됩니다.