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를 고려하세요.