StaxXmlWriter - 비동기 XML 스트림 라이터
StaxXmlWriter - 비동기 XML 스트림 라이터
섹션 제목: “StaxXmlWriter - 비동기 XML 스트림 라이터”StaxXmlWriter는 대용량 문서와 메모리 효율적인 처리를 위해 설계된 비동기, 스트림 기반 XML 라이터입니다. XML 데이터를 WritableStream에 직접 작성하여 스트리밍 응답과 실시간 XML 생성에 이상적입니다.
주요 기능
섹션 제목: “주요 기능”- 스트림 기반: 메모리 효율성을 위해 WritableStream에 직접 작성
- 비동기: 논블로킹 작업을 위해 모든 메서드가 promise 반환
- 대용량 문서 지원: 임의의 크기의 XML 문서 처리
- 메모리 효율적: 전체 XML을 메모리에 저장할 필요 없음
- 실시간 생성: 스트리밍 API와 라이브 데이터에 완벽
참고: 동기식, 메모리 내 XML 생성을 위해서는 XML을 문자열로 구성하는 StaxXmlWriterSync를 참조하세요.
🔧 빠른 시작
섹션 제목: “🔧 빠른 시작”import { Hono } from 'hono';import { stream } from 'hono/streaming';import { StaxXmlWriter } from 'stax-xml';
const app = new Hono();
app.get('/api/products', (c) => { // 샘플 제품 데이터 const products = [ { id: 'P001', name: 'Smartphone', price: 699.99, category: 'Electronics' }, { id: 'P002', name: 'Headphones', price: 199.99, category: 'Electronics' }, { id: 'P003', name: 'Coffee Maker', price: 149.99, category: 'Appliances' } ];
// 적절한 헤더 설정 c.header('Content-Type', 'application/xml; charset=utf-8'); c.header('Cache-Control', 'no-cache');
return stream(c, async (stream) => { const writer = new StaxXmlWriter(stream, { prettyPrint: true, indentString: ' ' });
try { // 스트림에 직접 XML 생성 - 모든 메서드에 await 필요 await writer.writeStartDocument('1.0', 'utf-8'); await writer.writeStartElement('products', { attributes: { count: products.length.toString(), generated: new Date().toISOString() } });
for (const product of products) { await writer.writeStartElement('product', { attributes: { id: product.id, category: product.category } });
await writer.writeStartElement('name'); await writer.writeCharacters(product.name); await writer.writeEndElement();
await writer.writeStartElement('price', { attributes: { currency: 'USD' } }); await writer.writeCharacters(product.price.toString()); await writer.writeEndElement();
await writer.writeEndElement(); // product }
await writer.writeEndElement(); // products await writer.writeEndDocument(); await writer.close(); // 중요: 스트림 닫기
} catch (error) { console.error('XML 생성 오류:', error); // 참고: 스트리밍 컨텍스트에서 오류 처리는 제한적입니다 } });});
export default app;네임스페이스와 사용자 정의 엔터티를 포함한 고급 기능
섹션 제목: “네임스페이스와 사용자 정의 엔터티를 포함한 고급 기능”import { Hono } from 'hono';import { stream } from 'hono/streaming';import { StaxXmlWriter } from 'stax-xml';
const app = new Hono();
app.get('/api/catalog', (c) => { const items = [ { id: '001', name: 'Premium Laptop', featured: true }, { id: '002', name: 'Wireless Mouse', featured: false } ];
c.header('Content-Type', 'application/xml; charset=utf-8');
return stream(c, async (stream) => { const writer = new StaxXmlWriter(stream, { prettyPrint: true, indentString: ' ', addEntities: [ { entity: 'company', value: 'Acme Corporation' }, { entity: 'copyright', value: '© 2024' } ], autoEncodeEntities: true });
try { // 네임스페이스와 사용자 정의 엔터티로 XML 작성 await writer.writeStartDocument('1.0', 'utf-8');
await writer.writeStartElement('catalog', { prefix: 'cat', uri: 'http://example.com/catalog', attributes: { version: '2.0' } }); await writer.writeNamespace('meta', 'http://example.com/metadata');
await writer.writeStartElement('header', { prefix: 'meta' }); await writer.writeStartElement('title'); await writer.writeCharacters('Product Catalog'); await writer.writeEndElement();
await writer.writeStartElement('company'); await writer.writeCharacters('&company;'); // 자동으로 인코딩됩니다 await writer.writeEndElement(); await writer.writeEndElement(); // header
await writer.writeStartElement('products'); for (const item of items) { await writer.writeStartElement('product', { attributes: { id: item.id, featured: item.featured.toString() } });
await writer.writeStartElement('name'); await writer.writeCharacters(item.name); await writer.writeEndElement();
// 자체 닫는 엘리먼트 await writer.writeStartElement('thumbnail', { attributes: { src: `${item.id}.jpg`, alt: 'Product Image' }, selfClosing: true });
await writer.writeStartElement('description'); await writer.writeCData('<p>This is <b>HTML</b> content in CDATA</p>'); await writer.writeEndElement();
await writer.writeEndElement(); // product } await writer.writeEndElement(); // products await writer.writeEndElement(); // catalog
await writer.writeEndDocument(); await writer.close();
} catch (error) { console.error('XML 생성 오류:', error); } });});
export default app;WriteElementOptions API
섹션 제목: “WriteElementOptions API”StaxXmlWriter는 엘리먼트 생성을 단순화하는 통합 API를 지원합니다:
// 속성이 있는 자체 닫는 엘리먼트await writer.writeStartElement('img', { attributes: { src: 'image.jpg', alt: 'Image' }, selfClosing: true // writeEndElement() 호출 불필요});
// 네임스페이스가 있는 엘리먼트await writer.writeStartElement('title', { prefix: 'html', uri: 'http://www.w3.org/1999/xhtml', attributes: { lang: 'ko' }});📚 API 참조
섹션 제목: “📚 API 참조”StaxXmlWriter (비동기식, 스트림 기반)
섹션 제목: “StaxXmlWriter (비동기식, 스트림 기반)”class StaxXmlWriter { // 생성자 - WritableStream에 직접 XML 스트리밍용 constructor(stream: WritableStream<Uint8Array>, options?: StaxXmlWriterOptions)
// 문서 레벨 메서드 writeStartDocument(version?: string, encoding?: string): Promise<this> writeEndDocument(): Promise<void>
// 엘리먼트 작성 메서드 writeStartElement(localName: string, options?: WriteElementOptions): Promise<this> writeEndElement(): Promise<this>
// 콘텐츠 작성 메서드 writeCharacters(text: string): Promise<this> writeCData(cdata: string): Promise<this> writeComment(comment: string): Promise<this>
// 스트림 관리 close(): Promise<void> // 기본 스트림 닫기 flush(): Promise<void> // 수동 플러시 getMetrics(): object // 성능 메트릭}
interface StaxXmlWriterOptions { encoding?: string; // 기본값: 'utf-8' prettyPrint?: boolean; // 기본값: false indentString?: string; // 기본값: ' ' addEntities?: { entity: string, value: string }[]; autoEncodeEntities?: boolean; // 기본값: true namespaces?: NamespaceDeclaration[]; bufferSize?: number; // 기본값: 16384 highWaterMark?: number; // 기본값: 65536 flushThreshold?: number; // 기본값: 0.8 enableAutoFlush?: boolean; // 기본값: true}인터페이스
섹션 제목: “인터페이스”interface WriteElementOptions { prefix?: string; uri?: string; attributes?: Record<string, string | AttributeInfo>; selfClosing?: boolean;}
interface AttributeInfo { value: string; localName: string; prefix?: string; uri?: string;}
interface NamespaceDeclaration { prefix?: string; uri: string;}🚀 StaxXmlWriter를 언제 사용해야 할까요?
섹션 제목: “🚀 StaxXmlWriter를 언제 사용해야 할까요?”StaxXmlWriter를 사용하는 경우:
- 대용량 XML 문서 구성 (> 100MB)
- 클라이언트에 실시간 XML 스트리밍
- 메모리 효율성이 중요한 경우
- 비동기/스트리밍 아키텍처 작업
- 메모리에 맞지 않는 데이터 처리
- 응답을 스트리밍해야 하는 API 구축
- 라이브 데이터 소스에서 실시간 XML 생성
소규모 문서나 동기식 작업의 경우 XML을 메모리에서 문자열로 구성하는 StaxXmlWriterSync를 고려하세요.