API 사용하기
API 사용하기
Pulsar 함수를 Java, Python, Go로 개발할 때 쓸 수 있는 API를 정리해 볼게요. 어떤 인터페이스를 고르느냐에 따라 필요한 라이브러리와 할 수 있는 일이 달라지니, 각각의 특징을 먼저 파악하는 게 중요해요.
크게 언어 네이티브 인터페이스, Pulsar 함수 SDK, 그리고 Java 전용 확장 SDK 세 가지로 나뉘어요. 함수가 컨텍스트(context)가 필요하냐, 외부 리소스를 초기화·해제해야 하냐에 따라 적절한 걸 선택하면 돼요.
출처: 문서
본문
아래 표는 Java, Python, Go에서 Pulsar 함수를 개발할 때 쓸 수 있는 API를 정리한 거예요.
| 인터페이스 | 설명 | 사용 사례 |
|---|---|---|
| Java/Python 언어 네이티브 인터페이스 | Pulsar 전용 라이브러리나 특별한 의존성이 필요 없어요 (핵심 라이브러리만). | 컨텍스트에 접근할 필요가 없는 함수 |
| Java/Python/Go Pulsar 함수 SDK | 상태 관리나 사용자 설정처럼 언어 네이티브 인터페이스에는 없는 다양한 기능을 제공하는 Pulsar 전용 라이브러리예요. | 컨텍스트에 접근해야 하는 함수 |
| Java 확장 Pulsar 함수 SDK | Pulsar 전용 라이브러리의 확장으로, Java에서 초기화(initialize)와 닫기(close) 인터페이스를 제공해요. | 외부 리소스의 초기화와 해제가 필요한 함수 |
Java/Python 언어 네이티브 인터페이스 사용하기 (Use language-native interface)
언어 네이티브 인터페이스는 Java/Python 함수를 작성하는 간단하고 깔끔한 방법이에요. 예를 들어 들어오는 모든 문자열에 느낌표를 붙이고 그 출력 문자열을 토픽에 게시하는 식이죠. 외부 의존성이 없어요.
아래 예시들은 언어 네이티브 함수예요.
Java:
Java 코드를 "언어 네이티브" 함수로 사용하려면 java.util.Function 인터페이스를 구현해야 해요. apply 메서드 안에 더 복잡한 처리 기능을 위한 어떤 로직이든 넣을 수 있어요.
import java.util.function.Function;
public class JavaNativeExclamationFunction implements Function<String, String> {
@Override
public String apply(String input) {
return String.format("%s!", input);
}
}
자세한 내용은 코드 예시를 참고해요.
Python:
Python 코드를 "언어 네이티브" 함수로 사용하려면 아래처럼 process라는 메서드가 있어야 해요. 이 메서드는 받은 문자열 값에 느낌표를 붙여요.
def process(input):
return "{}!".format(input)
자세한 내용은 코드 예시를 참고해요.
알아두기: Pulsar 함수를 Python 3로 작성해요. 함수가 실행되도록 하려면 함수 워커에 Python 3가 설치되어 있고 기본 인터프리터로 설정되어 있어야 해요.
Java/Python/Go SDK 사용하기 (Use SDK)
Pulsar 함수 SDK의 구현은 컨텍스트 객체를 매개변수로 포함하는 함수형 인터페이스를 지정해요.
아래 예시들은 다양한 언어의 Pulsar 함수 SDK를 사용한 모습이에요.
Java:
Java SDK로 함수를 개발할 때는 org.apache.pulsar.functions.api.Function 인터페이스를 구현해야 해요. 이 인터페이스는 구현해야 할 메서드가 process 하나뿐이에요.
import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.api.Function;
public class ExclamationFunction implements Function<String, String> {
@Override
public String process(String input, Context context) {
return String.format("%s!", input);
}
}
자세한 내용은 코드 예시를 참고해요.
함수의 반환 타입을 Record 제네릭으로 감쌀 수도 있는데, 이렇게 하면 토픽, 스키마, 프로퍼티 같은 출력 메시지를 더 세밀하게 제어할 수 있어요. Context::newOutputRecordBuilder 메서드를 사용해서 이 Record 출력을 만들면 돼요.
import java.util.HashMap;
import java.util.Map;
import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.api.Function;
import org.apache.pulsar.functions.api.Record;
public class RecordFunction implements Function<String, Record<String>> {
@Override
public Record<String> process(String input, Context context) throws Exception {
String output = String.format("%s!", input);
Map<String, String> properties = new HashMap<>(context.getCurrentRecord().getProperties());
context.getCurrentRecord().getTopicName().ifPresent(topic -> properties.put("input_topic", topic));
return context.newOutputRecordBuilder(Schema.STRING)
.value(output)
.properties(properties)
.build();
}
}
자세한 내용은 코드 예시를 참고해요.
Python:
Python SDK로 함수를 개발하려면 Python 설치에 pulsar 클라이언트 의존성을 추가해야 해요.
from pulsar import Function
class ExclamationFunction(Function):
def __init__(self):
pass
def process(self, input, context):
return input + '!'
자세한 내용은 코드 예시를 참고해요.
Go:
Go SDK로 함수를 개발하려면 Go 설치에 pulsar 클라이언트 의존성을 추가하고, main() 메서드 안에서 pf.Start() 메서드에 함수 이름을 제공해야 해요. 이렇게 하면 함수가 Pulsar 함수 프레임워크에 등록되어 새 메시지가 도착했을 때 지정한 함수가 호출될 수 있어요.
package main
import (
"context"
"fmt"
"github.com/apache/pulsar/pulsar-function-go/pf"
)
func HandleRequest(ctx context.Context, in []byte) error{
fmt.Println(string(in) + "!")
return nil
}
func main() {
pf.Start(HandleRequest)
}
자세한 내용은 코드 예시를 참고해요.
Java 확장 SDK 사용하기 (Use extended SDK for Java)
이 확장 Pulsar 함수 SDK는 외부 리소스를 초기화하고 해제하는 두 가지 추가 인터페이스를 제공해요.
initialize인터페이스 — 함수 인스턴스가 시작할 때 한 번만 초기화하면 되는 외부 리소스를 초기화할 수 있어요.close인터페이스 — 함수 인스턴스가 닫힐 때 참조하던 외부 리소스를 닫을 수 있어요.
알아두기: Java용 확장 Pulsar 함수 SDK는 Pulsar 2.10.0 이상 버전에서만 사용할 수 있어요. 사용하기 전에 Pulsar 2.10.0 이상 버전에서 함수 워커를 설정해야 해요.
아래 예시는 Java용 Pulsar 함수 SDK의 확장 인터페이스를 사용해서, 함수 인스턴스가 시작할 때 RedisClient를 초기화하고 함수 인스턴스가 닫힐 때 해제하는 모습을 보여줘요.
Java:
import org.apache.pulsar.functions.api.Context;
import org.apache.pulsar.functions.api.Function;
import io.lettuce.core.RedisClient;
public class InitializableFunction implements Function<String, String> {
private RedisClient redisClient;
private void initRedisClient(Map<String, Object> connectInfo) {
redisClient = RedisClient.create(connectInfo.get("redisURI"));
}
@Override
public void initialize(Context context) {
Map<String, Object> connectInfo = context.getUserConfigMap();
redisClient = initRedisClient(connectInfo);
}
@Override
public String process(String input, Context context) {
String value = client.get(key);
return String.format("%s-%s", input, value);
}
@Override
public void close() {
redisClient.close();
}
}
더 알아보기 (Learn more)
- 함수를 처음 개발한다면 함수 개발 튜토리얼부터 시작해 보세요.
- 컨텍스트 객체가 제공하는 기능이 궁금하다면 함수 개발 API의 관련 문서를 확인해요.
- 개발한 함수를 배포하는 방법은 함수 배포 문서를 참고해요.