SDK는 어떻게 설치하나요?
패키지 관리자로 패키지를 설치하세요. Node 20.3 이상, Bun 또는 번들러가 필요합니다. TypeScript 타입이 포함되어 있어 @types/node는 필요 없습니다.
npm install @pdf123/sdkbun add @pdf123/sdk와 pnpm add @pdf123/sdk도 같은 방식으로 동작합니다.
PDF 두 개를 병합하려면?
클라이언트를 만들고, 파일 두 개에 merge 도구를 실행한 뒤 결과를 저장합니다. 옵션 없이 만들면 클라이언트는 공개 API에 익명으로 접속합니다.
import { Pdf123Client } from "@pdf123/sdk";
import { readFileInput, saveResult } from "@pdf123/sdk/node";
const client = new Pdf123Client();
const result = await client.run("merge", {
input: [await readFileInput("a.pdf"), await readFileInput("b.pdf")],
});
const path = await saveResult(result, { output: "merged.pdf" });
console.log(path);결과에는 바이트가 data에, 콘텐츠 타입이 contentType에, 서버가 정한 파일 이름이 filename에 들어 있습니다. 보고서를 반환하는 도구에서는 json도 쓸 수 있습니다. 같은 작업을 웹사이트에서는 PDF 병합으로 사용할 수 있습니다.
어떤 진입점을 가져와야 하나요?
| 진입점 | 필요한 것 | 제공하는 것 |
|---|---|---|
@pdf123/sdk | fetch만 | Pdf123Client, TOOLS, getTool, Pdf123Error, 카탈로그 헬퍼 |
@pdf123/sdk/node | Node 또는 Bun | readFileInput, fileSource, saveResult, checkOutput, clientFromEnv |
브라우저와 엣지 런타임에서는 루트 진입점에서 가져오고, 파일을 읽거나 쓰는 곳에만 node 진입점을 추가하세요.
클라이언트에는 어떤 메서드가 있나요?
| 메서드 | 기능 |
|---|---|
run(tool, { input, params }) | 도구 하나를 실행하고 결과로 완료됨 |
runBatch(tool, inputs, options) | 단일 파일 도구를 여러 입력에 실행하고, 입력마다 항목 하나씩으로 완료됨 |
pipeline(steps, input, options) | 여러 도구를 한 번의 요청으로 실행 |
call(target, files, fields) | 도구 ID, 작업 ID 또는 /api/... 경로에 원시 요청을 보냄 |
upload(file) | 청크 업로드 API로 파일 하나를 업로드하고 그 ID를 반환 |
카탈로그 헬퍼는 일반 함수입니다. TOOLS는 모든 도구를 나열하고, getTool(id)는 도구 하나의 필드, 기본값, 허용되는 파일 형식을 반환하며, toolGroup, toolSummary, matchesQuery, suggestTools는 도구 선택기를 만드는 데 도움이 됩니다. 명령줄에서도 pdfx list와 pdfx describe로 같은 카탈로그를 출력합니다.
도구에 옵션을 전달하려면?
params에는 도구별로 타입이 지정됩니다. 해당 도구의 필드만 받아들이고, 선택형 필드는 허용된 값만 받습니다. 숫자 필드는 최솟값과 최댓값, 파일은 허용되는 형식이 무엇이든 업로드하기 전에 검사됩니다. 서버가 필요로 하는 기본값은 채워집니다.
const marked = await client.run("watermark", {
input: await readFileInput("a.pdf"),
params: { watermarkText: "DRAFT", fontSize: 40, rotation: -45 },
});
await saveResult(marked, { output: "draft.pdf" });빈 문자열은 "설정하지 않음"을 뜻하며 기본값이 적용됩니다. 각 옵션의 역할은 워터마크 넣기를 참고하세요.
많은 파일은 어떻게 처리하나요?
runBatch는 압축, 회전, 보호처럼 단일 파일을 처리하는 도구를 같은 옵션으로 각 입력에 실행합니다. 기본적으로 두 파일씩 동시에 실행합니다. 파일 하나가 실패해도 나머지는 멈추지 않습니다.
import { fileSource, saveResult } from "@pdf123/sdk/node";
const controller = new AbortController();
const entries = await client.runBatch("compress", [fileSource("a.pdf"), fileSource("b.pdf")], {
concurrency: 2,
signal: controller.signal,
onResult: async (entry, index) => {
if (entry.ok) await saveResult(entry.result, { output: "compressed/" });
},
});
console.log(entries.map((entry) => entry.ok));fileSource(path)는 지연 소스로, 워커가 가져갈 때에야 읽힙니다. 따라서 큰 파일이 많아도 한꺼번에 메모리에 올라가지 않습니다.onResult는 각 결과가 완료되는 대로 전달받습니다. 저장은 여기에서 하세요. 100개 중 50번째 파일에서 취소해도 앞의 49개는 남습니다.retainData: false를 지정하면 반환되는 배열에 바이트가 보관되지 않습니다.- 모든 호출에서
timeoutMs와 취소용signal을 지정할 수 있습니다. idempotencyKey는 파일마다<key>:<index>가 됩니다.
필터 도구(ID가 filter-로 시작하는 도구)는 조건이 맞지 않을 때 예외를 던지지 않고 matched: false로 완료됩니다. 일괄 처리에서는 이런 파일도 ok로 집계됩니다.
한 번의 요청으로 여러 도구를 연결하려면?
pipeline은 단계 목록과 하나 이상의 입력을 보냅니다. 서버는 각 단계의 출력을 다음 단계로 넘깁니다.
const piped = await client.pipeline(
[{ tool: "merge" }, { tool: "watermark", params: { watermarkText: "DRAFT" } }, { tool: "compress" }],
[await readFileInput("a.pdf"), await readFileInput("b.pdf")],
);
await saveResult(piped, { output: "out.pdf" });파이프라인은 run과 같은 비밀번호 옵션을 받습니다.
암호화된 PDF는 어떻게 다루나요?
run에 password를 전달하면 암호화된 입력을 먼저 엽니다. 잠금 해제와 도구 실행은 한 번의 요청으로 처리됩니다. 병합처럼 여러 파일을 받는 도구에서는 입력마다 항목 하나씩을 가진 passwords를 전달하세요. 잠겨 있지 않은 파일에는 빈 문자열을 씁니다. 각 파일은 따로 잠금 해제됩니다.
await client.run("compress", { input: await readFileInput("locked.pdf"), password: "secret" });
await client.run("merge", {
input: [await readFileInput("locked.pdf"), await readFileInput("open.pdf")],
passwords: ["secret", ""],
});일괄 처리에서는 passwordFor(file, index)가 각 입력의 비밀번호를 반환합니다. 보호를 영구적으로 제거하려면 해제 도구를 사용하세요.
오류는 어떻게 처리하나요?
실패하면 Pdf123Error가 던져집니다. 이 오류에는 status(응답이 없었다면 undefined), code, password_required 같은 세부 원인을 나타내는 reason, 서버의 문제 세부 정보인 problem이 있으며, 이 세부 정보에는 힌트가 있을 때 hint가 포함됩니다. 검증 오류는 아무것도 업로드하기 전에 던져집니다.
import { Pdf123Error } from "@pdf123/sdk";
try {
await client.run("compress", { input: await readFileInput("locked.pdf") });
} catch (error) {
if (error instanceof Pdf123Error) {
console.error(error.status, error.code, error.reason, error.problem?.hint);
} else {
throw error;
}
}서버 코드는 오류 코드에 정리되어 있습니다. 클라이언트는 다음과 같은 자체 코드를 추가합니다.
| 코드 | 의미 |
|---|---|
network_error | 요청에 대한 응답이 없었음 |
timeout | 요청이 timeoutMs를 초과함 |
cancelled | signal이 호출을 중단함 |
input_unreadable | 로컬 경로를 읽을 수 없었음 |
output_unwritable | 지정한 경로에 결과를 저장할 수 없었음 |
output_mismatch | saveResult가 ZIP을 .pdf 이름으로 쓰는 것을 거부함 |
unsupported_file_type | 도구가 받지 않는 파일 형식임 |
unknown_tool | 도구 ID가 존재하지 않음. 메시지에 비슷한 ID가 제안됨 |
invalid_target | call이 .., . 또는 빈 세그먼트가 있는 /api/... 경로를 거부함 |
no_content | 도구가 반환할 내용이 없었음(HTTP 204) |
saveResult는 디렉터리 안의 기존 파일을 덮어쓰지 않습니다. 경로에 쓸 수 있는지 업로드 전에 알아보려면 먼저 checkOutput(output, { several })를 호출하세요.
어떤 TypeScript 및 모듈 설정에서 동작하나요?
타입은 moduleResolution 설정 nodenext, node16, bundler, 그리고 예전 방식인 node10에서 해석되며, @pdf123/sdk/node 하위 경로도 포함됩니다. 패키지는 ES 모듈이므로 import는 어디서나 동작합니다. CommonJS에서 require("@pdf123/sdk")는 Node 22.12 이상에서 동작하며 Node 20에서는 사용할 수 없습니다.
클라이언트는 어떻게 설정하나요?
| 옵션 | 환경 변수 | 기본값 |
|---|---|---|
baseUrl | PDFX_API_BASE | https://pdf123.xyz |
apiKey | PDFX_API_KEY | 없음(익명) |
timeoutMs | 없음 | 300000 |
new Pdf123Client()는 환경 변수를 전혀 읽지 않습니다. @pdf123/sdk/node의 clientFromEnv()는 두 환경 변수를 읽으며, 직접 전달한 옵션이 우선합니다. 키는 X-API-KEY 헤더로 전송됩니다. 자세한 내용은 인증을 참고하세요.
자체 서버를 사용하려면 baseUrl을 그 주소(예: http://localhost:8080)로 설정하세요. 셀프 호스트도 참고하세요.
SDK를 브라우저에서 쓸 수 있나요?
네. 루트 진입점 @pdf123/sdk는 fetch만 필요하고 Node 의존성이 없습니다. 파일 헬퍼는 node 진입점에 있으므로, FileInput 객체는 File 또는 Uint8Array로 직접 만드세요. 다른 사람이 읽을 수 있는 브라우저 코드에 API 키를 넣어 배포하지 마세요.
관련 페이지
- 개발자 개요: REST API와 인증
- pdfx 명령줄: 이 SDK를 기반으로 만들어졌습니다
- MCP 서버: AI 에이전트용
- Swagger UI와 OpenAPI 문서
- 도구 페이지: 병합, 분할, 압축, OCR, 보호
FAQ
SDK에 API 키가 필요한가요?
아니요. 옵션 없이 만든 클라이언트는 공개 API를 익명으로 호출합니다. X-API-KEY 헤더를 보내려면 apiKey를 전달하세요.
SDK에는 어떤 Node 버전이 필요한가요?
Node 20.3 이상 또는 Bun입니다. 루트 진입점은 fetch만 필요하므로 브라우저와 번들러에서도 실행됩니다.
SDK보다 새로운 도구는 어떻게 쓰나요?
client.call을 사용하세요. 도구 ID, general/merge-pdfs 같은 작업 ID 또는 /api/... 경로와 함께 파일과 필드를 받습니다. 로컬에서는 검증도 기본값 채우기도 하지 않습니다.
업로드할 수 있는 파일 크기는 얼마인가요?
총 95 MB를 넘는 입력은 자동으로 청크 업로드 API를 거칩니다. 직접 요청 본문 하나는 100 MiB로 제한됩니다.
표가 없는 PDF에서 호출이 예외를 던진 이유는 무엇인가요?
pdf-to-csv, pdf-to-xlsx 같은 도구는 PDF에서 표를 찾지 못하면 내용 없이 응답합니다. SDK는 빈 파일을 반환하는 대신 코드 no_content인 Pdf123Error를 던집니다. 빈 결과가 허용되는 경우에는 이 코드를 확인하세요.