# FreeReport — full reference for AI assistants FreeReport is a web reporting tool with a browser designer, viewer, exact printing, Korean PDF, Excel and HWPX export. No install. Free for personal use. ## Key facts - Product: FreeReport, a web reporting tool. Latest version v0.8.0 (2026-10-15). - Maker: (주)세컨드코리아 (2nd Korea Co., Ltd.), Paju, Korea; also makes the FreeGrid data grid (https://freegrid.app). help@2nd-korea.com - npm: @freereportjs/core, @freereportjs/react, @freereportjs/vue, @freereportjs/svelte, @freereportjs/angular. CDN: https://freereport.app/cdn/latest/freereport.min.js - Price: personal use free. Company KRW 500,000 per domain per year, or KRW 900,000 per domain perpetual (one year of updates). With the Windows print program KRW 1,000,000/year or 1,800,000 perpetual. VAT separate. Unlimited developers, users and outputs. - Platforms: current browsers on any OS; Node.js, Deno, Bun for server rendering; React, Vue 3, Svelte 5, Angular; eGovFrame 4.3 sample; optional signed Windows 10/11 print agent for silent printing. - Exports: print, PDF (embedded Korean font subset, AES-256 password and permissions), Excel as printed or as data, CSV, HWPX (KS X 6101). - Not yet: GS certification, SA security confirmation, e-Form data entry, DOCX/PPTX export, automatic conversion of forms from other tools. ## API quick reference - createViewer(el, { definition, data, params, lang, zoom, licenseKey, onOutput, pdfSecurity }) → Viewer (destroy(), report) - createReport(definition, data) → Report: ready(), layout(), print(), toPdf(), toXlsx("form" | "data"), toCsv(), toHwpx(), download(kind, name?) - createDesigner(el, { definition, data, lang, onChange, onSave }) → Designer: setDefinition(), setData() - renderPdf / renderXlsx(definition, data, { fonts }) in Node.js, Deno or Bun; loadFonts, registerFont(family, { normal, bold }) for TTF fonts - setLicenseKey(key) once, or licenseKey per viewer/report - agent.detect(), agent.pair(), agent.printers(), agent.print(pdfBlob, { printer, copies }) for the optional Windows print agent Rules: positions and sizes are millimetres inside the band; font sizes are points; expressions are strings; text templates use {expr} or {expr:format}. Do not invent options that are not listed here. ## Quick start ```js import { createViewer } from '@freereportjs/core'; import '@freereportjs/core/styles.css'; const definition = await fetch('/reports/sales.json').then(r => r.json()); const viewer = createViewer(document.getElementById('viewer'), { definition, data: { rows }, // detail rows; other keys are usable in expressions lang: 'ko', }); //
``` ## Report definition - `name` (string): Report name; used for file names and the output event. - `page` (PageSetup): Paper size, orientation and margins. - `font` ({ family, size, color }): Default font of the report (default Nanum Gothic 9pt). - `styles` (Record): Named styles; elements refer to them with styleName. - `params` (Record): Report parameters shown in the viewer's parameter panel. - `dataSource` (string): Which array in the data holds the detail rows (default "rows"). - `sort` (string[]): Sort detail rows, e.g. ["region", "-amount"] ("-" = descending). - `filter` (Expr): Keep only rows where the expression is truthy. - `bands` (object): title, pageHeader, columnHeader, groups, detail, summary, pageFooter, noData. - `pageHeaderSkipFirst` (boolean): Do not print the page header on the first page. - `fillEmptyRows` (boolean): Fill the rest of each page with blank detail rows (form tables). - `watermark` (string | Watermark | Watermark[]): Text or image marks behind (or over) the content. - `emboss` (Emboss | Emboss[]): Raised seals, logos or text pressed into the paper. ```json { "name": "거래처별 매출", "page": { "size": "A4", "orientation": "portrait", "margins": 15 }, "font": { "family": "Nanum Gothic", "size": 9 }, "sort": ["customer", "date"], "bands": { "title": { "height": 14, "elements": [ { "type": "text", "x": 0, "y": 0, "w": 180, "h": 10, "text": "거래처별 매출", "style": { "fontSize": 16, "bold": true } } ] }, "columnHeader": { "height": 7, "elements": [ { "type": "text", "x": 0, "y": 0, "w": 30, "h": 7, "text": "일자", "style": { "bold": true, "border": true } }, { "type": "text", "x": 30, "y": 0, "w": 110, "h": 7, "text": "거래처", "style": { "bold": true, "border": true } }, { "type": "text", "x": 140, "y": 0, "w": 40, "h": 7, "text": "금액", "style": { "bold": true, "border": true } } ] }, "detail": { "height": 6, "elements": [ { "type": "field", "x": 0, "y": 0, "w": 30, "h": 6, "expr": "date", "format": "yyyy-MM-dd", "style": { "border": true } }, { "type": "field", "x": 30, "y": 0, "w": 110, "h": 6, "expr": "customer", "suppressRepeated": true, "style": { "border": true } }, { "type": "field", "x": 140, "y": 0, "w": 40, "h": 6, "expr": "amount", "format": "#,##0", "style": { "border": true, "align": "right" } } ] }, "summary": { "height": 8, "elements": [ { "type": "text", "x": 0, "y": 1, "w": 180, "h": 7, "text": "합계 {sum(amount):#,##0}원 ({koreanAmount(sum(amount))})", "style": { "align": "right", "bold": true } } ] }, "pageFooter": { "height": 8, "elements": [ { "type": "text", "x": 0, "y": 2, "w": 180, "h": 5, "text": "{page} / {pages}", "style": { "align": "center" } } ] } } } ``` ## Page setup - `size` ('A3' | 'A4' | 'A5' | 'B4' | 'B5' | 'Letter' | 'Legal' | [w, h]): Paper name or [width, height] in mm. Default A4. - `orientation` ('portrait' | 'landscape'): Default portrait. - `margins` (number | [top, right, bottom, left]): Margins in mm. Default 15. ## Bands - `title` (Band): First page only, before everything else (title, letterhead, whole forms). - `pageHeader` (Band): Top of every page. - `columnHeader` (Band): Below the page header on every page with detail rows (table column titles). - `groups` (GroupDefinition[]): Group headers and footers, outermost first. - `detail` (Band): Once per detail row. - `summary` (Band): After the last row (grand totals, charts). - `pageFooter` (Band): Bottom of every page (page numbers, page subtotals). - `noData` (Band): Printed instead of the detail rows when there is no data. ### Band properties - `height` (number): Height in mm. - `elements` (ReportElement[]): Positioned elements; x, y, w, h in mm inside the band. - `canGrow` (boolean): Grow when text needs more room (default true for detail and group bands). - `visible` (Expr): Print the band only when the expression is truthy. - `pageBreakBefore / pageBreakAfter` (boolean): Start a new page before / after the band. - `background` (string): Band background color. - `altBackground` (string): Detail only: alternate row background (zebra). - `columns / columnGap` (number): Detail only: print rows side by side in columns (label sheets, cards); gap in mm. ## Groups - `by` (Expr): Expression that groups consecutive rows, e.g. "region". - `sort` ('asc' | 'desc'): Sort rows by the group expression first (otherwise rows keep their order). - `header / footer` (Band): Printed before / after each group; aggregates cover the group. - `newPage` (boolean): Each group starts on a new page. - `repeatHeader` (boolean): Repeat the group header on pages where the group continues. - `keepWithRows` (number): Keep the header with at least this many rows (default 1). - `resetPageNumber` (boolean): Restart page / pages for each group. ```json "groups": [{ "by": "region", "sort": "asc", "repeatHeader": true, "keepWithRows": 2, "header": { "height": 7, "elements": [ { "type": "text", "x": 0, "y": 0, "w": 180, "h": 7, "text": "■ {region} ({count()}건)", "style": { "bold": true } } ] }, "footer": { "height": 7, "elements": [ { "type": "text", "x": 0, "y": 0, "w": 140, "h": 7, "text": "{region} 소계", "style": { "align": "center" } }, { "type": "field", "x": 140, "y": 0, "w": 40, "h": 7, "expr": "sum(amount)", "format": "#,##0", "style": { "align": "right" } } ] } }], "pageFooter": { "height": 7, "elements": [ { "type": "text", "x": 0, "y": 1, "w": 180, "h": 6, "text": "이 페이지 소계 {sum(amount, 'page'):#,##0}원 · 누계 {sum(amount, 'report'):#,##0}원" } ] } ``` ## Elements (common properties) - `type` ('text' | 'field' | 'line' | 'rect' | 'image' | 'barcode' | 'chart' | 'table' | 'crosstab'): Element kind. - `x, y, w, h` (number): Position and size inside the band, in mm. - `id` (string): Optional id (the designer sets one). - `style / styleName` (Style / string): Inline style, merged over the named style. - `visible` (Expr): Draw only when truthy. - `canGrow` (boolean): Grow downwards when the text needs room (the band grows with it). - `stretch` (boolean): Follow the band height when it grows (default for elements touching the band bottom). - `name` (string): Column name in Excel "data" mode. ## Element types - `text` ({ text }): Static or templated text: "합계 {sum(amount):#,##0}원". {{ and }} are literal braces. - `field` ({ expr, format?, nullText?, suppressRepeated? }): One expression with an optional format; suppressRepeated hides values equal to the row above. - `line` ({ color?, width?, dash? }): From (x, y) to (x + w, y + h); a horizontal line has h = 0. Width in mm. - `rect` ({ fill?, color?, width?, radius? }): Rectangle; width 0 for no stroke. - `image` ({ src? | expr?, fit? }): URL or data: URL, or an expression from data. fit: contain | cover | fill. - `barcode` ({ expr, format?, showText?, ecc?, color? }): format: 'code128' | 'ean13' | 'qr' | 'datamatrix' | 'pdf417'. ecc: QR error correction L/M/Q/H. - `chart` ({ chartType, category, series, source?, title?, legend?, format?, showValues?, stacked? }): chartType: 'bar' | 'hbar' | 'line' | 'area' | 'pie' | 'doughnut'. - `table` ({ source, columns, rowHeight?, showHeader?, headerStyle?, footerLabel?, altBackground? }): A list inside a band (master–detail); columns: { header, expr, width?, format?, align?, sum? }. - `crosstab` ({ rowKey, columnKey, value, aggregate?, format?, totals?, corner?, source?, cellHeight?, rowHeaderWidth?, headerStyle? }): Rows × columns with an aggregated value per cell and totals. aggregate: sum | count | avg | min | max. ```json { "type": "chart", "x": 0, "y": 16, "w": 110, "h": 60, "chartType": "bar", "title": "지역별 매출", "source": "groupSum(rows, 'region', 'amount')", "category": "region", "series": [{ "expr": "amount", "label": "매출" }], "format": "#,##0" }, { "type": "table", "x": 0, "y": 20, "w": 180, "h": 20, "source": "items", "altBackground": "#fafbfd", "columns": [{ "header": "품목", "expr": "name" }, { "header": "수량", "expr": "qty", "width": 20, "align": "right" }, { "header": "금액", "expr": "qty * price", "width": 40, "format": "#,##0", "sum": true }] }, { "type": "crosstab", "x": 0, "y": 0, "w": 180, "h": 50, "rowKey": "region", "columnKey": "category", "value": "amount", "aggregate": "sum", "format": "#,##0", "corner": "지역 / 품목군" } ``` ```json "detail": { "height": 38, "columns": 3, "columnGap": 3, "elements": [ { "type": "field", "x": 2, "y": 2, "w": 36, "h": 6, "expr": "name", "style": { "bold": true } }, { "type": "barcode", "x": 40, "y": 2, "w": 18, "h": 18, "expr": "'https://example.com/a/' + assetNo", "format": "qr", "ecc": "M" }, { "type": "barcode", "x": 2, "y": 24, "w": 56, "h": 11, "expr": "assetNo", "format": "code128" } ] } ``` ## Styles - `fontFamily, fontSize` (string, number): Font family and size in points (default 9). - `bold, italic, underline, strike` (boolean): Font styles. - `color, background` (string): Text and background color. - `align, valign` ('left' | 'center' | 'right' | 'justify'; 'top' | 'middle' | 'bottom'): Horizontal and vertical alignment. - `padding` (number | [t, r, b, l]): Inner padding in mm (default 1 horizontally, 0.5 vertically). - `border` (true | "0.3 solid #333" | { top, right, bottom, left }): true = 0.2mm solid black; a CSS-like string; or per side. - `lineHeight` (number): Multiple of the font size (default 1.25). - `wrap` (boolean): Wrap long text (default true); false cuts at the box edge. - `shrinkToFit` (boolean): Shrink the font until one line fits. - `letterSpacing` (number): Letter spacing in mm (spaced titles like 견 적 서). ```json "styles": { "th": { "bold": true, "align": "center", "background": "#eef1f6", "border": "0.2 solid #8a94a6" }, "num": { "align": "right", "border": { "bottom": "0.15 solid #b9c1cd" } } }, "bands": { "detail": { "height": 6, "elements": [ { "type": "field", "x": 140, "y": 0, "w": 40, "h": 6, "expr": "amount", "format": "#,##0", "styleName": "num", "style": { "bold": true } } ] } } ``` ## Expressions ```text price * qty arithmetic amount >= params.minAmount comparison with a parameter customer.name ?? '(미지정)' member access and fallback qty > 10 ? '대량' : '일반' condition sum(amount) aggregate over the band's scope sum(amount, 'page') page subtotal sum(amount) / sum(amount, 'report') share of the grand total format(date, 'yyyy년 M월 d일 (ddd)') 2026년 10월 15일 (목) koreanAmount(1230000) 일금 일백이십삼만원정 bizNo('7928703276') 792-87-03276 {page} / {pages} page x / y in a text template ``` ### Variables - `page, pages` (number): Page number and page count (per group with resetPageNumber). - `rowNum` (number): Row number within the group (or report). - `rowIndex` (number): Row number within the report. - `groupKey, groupLevel` (unknown, number): Current group value and depth. - `now` (Date): Time the report was laid out. - `params` (object): Parameter values: params.from. - `row, rows, allRows, data` (object, array): Current row, rows in scope, all rows, the whole data object. ### Aggregates (scope: 'group' | 'page' | 'report'; default is the band's natural scope) - `sum(expr, scope?)` (number): Sum over the scope. - `avg / min / max(expr, scope?)` (number): Average, minimum, maximum. - `count(expr?, scope?)` (number): Rows (or non-empty values). - `distinct(expr, scope?)` (number): Number of different values. - `first / last(expr, scope?)` (unknown): Value of the first / last row. - `runningSum(expr, scope?)` (number): Sum up to and including the current row (default scope report). ### Functions - `format(v, f)` (string): Format a number or date: format(date, "yyyy-MM-dd"). - `koreanAmount(n) / korean(n)` (string): 1230000 → 일금 일백이십삼만원정. - `bizNo(v), phone(v)` (string): 1234567890 → 123-45-67890; 0212345678 → 02-1234-5678. - `round / floor / ceil(v, digits?)` (number): Rounding to digits after the point. - `abs, number, string` (—): Conversions. - `upper, lower, trim, len, left, right, substr, replace, concat, padStart, join` (string): Text functions. - `iif(c, a, b), coalesce(...), isEmpty(v)` (—): Conditions and fallbacks (?: and ?? work too). - `date, today, now, year, month, day, addDays, dateDiff, ymd` (—): Dates. - `groupSum(rows, key, value), groupCount(rows, key)` (array): Totals per key, handy as a chart source. - `min2(a, b), max2(a, b)` (number): Smaller / larger of two values. ## Formats - `#,##0 #,##0.00 0.0%` (number): Excel-style number patterns. - `₩#,##0 #,##0원 #,##0,"천"` (number): Prefixes, suffixes and thousands scaling. - `#,##0;(#,##0);-` (number): Sections: positive; negative; zero. - `yyyy-MM-dd HH:mm:ss` (date): Dates and times. - `yyyy년 M월 d일 (ddd)` (date): Korean dates with the weekday (월, 화…). - `a h:mm` (date): 오전/오후 (AM/PM). - `korean, koreanNumber` (number): 일금 ○○원정 / 십이만삼천. - `bizNo, upper, lower` (string): Business number and case. ## Watermarks - `text` (string): Template, e.g. "{params.user} · {format(now(), 'yyyy-MM-dd HH:mm')}". - `image, imageWidth` (string, number): Image mark instead of (or with) text; width in mm. - `repeat, gap` (boolean, number): Tile over the page (security pattern); distance in mm (default 45). - `opacity, angle, color, fontSize, bold` (—): Default opacity 0.12, angle -35°. - `pages` ('all' | 'first' | 'last' | 'odd' | 'even'): Which pages. - `layer` ('back' | 'front'): Behind the content (default) or over it. ### Emboss - `text, centerText` (string): Text around a round seal and in its centre (templates allowed). - `image` (string): A logo turned into a relief. - `x, y, w, h` (number): Position and size in mm (default a 32mm seal near the bottom right). - `shape` ('circle' | 'rect' | 'none'): Outline. - `depth, color, opacity, fontSize, pages` (—): Relief depth in mm (default 0.3), paper tone, opacity, pages. ```json "watermark": [ { "text": "{params.user} · {format(now(), 'yyyy-MM-dd HH:mm')} 출력", "repeat": true, "opacity": 0.07, "fontSize": 10, "gap": 40 }, { "text": "사 본", "fontSize": 110, "color": "#c8102e", "pages": "all" } ], "emboss": { "text": "(주)세컨드코리아 대표이사 직인 ·", "centerText": "인증", "x": 140, "y": 240, "w": 34 } ``` ## Parameters - `label` (string): Label in the parameter panel. - `type` ('string' | 'number' | 'date' | 'boolean' | 'select'): Input type. - `default` (unknown): Initial value. - `options` ({ value, label? }[]): Choices for select. - `required` (boolean): Must be filled before 조회 (Run). ```js // definition.params: { from: { label: '시작일', type: 'date', required: true }, // region: { label: '지역', type: 'select', options: [{ value: '' , label: '전체' }, { value: '서울' }] } } createViewer(el, { definition, paramsOpen: true, fetchData: params => fetch('/api/sales?' + new URLSearchParams(params)).then(r => r.json()), }); ``` ## Viewer options - `definition` (ReportDefinition): The report (JSON). - `data` (ReportData): { rows: [...] } plus any other values used by expressions. - `fetchData` ((params) => data | Promise): Load data for the parameters (on start and on 조회). - `params` (object): Initial parameter values (over the defaults). - `lang` ('ko' | 'en'): Toolbar language (default ko). - `toolbar` ({ pages, zoom, print, pdf, xlsx, xlsxData, csv, params }): Buttons to show (csv is off by default). - `zoom` (number | 'width' | 'page'): Initial zoom (default width). - `paramsOpen` (boolean): Open the parameter panel at start. - `fileName` (string): Base name of saved files. - `licenseKey` (string): License key (or setLicenseKey once). - `onOutput` ((e) => boolean | void | Promise): Before every print or export; return false to cancel. - `pdfSecurity` ({ userPassword?, ownerPassword?, permissions? }): PDF password and permissions (AES-256). - `author` (string): PDF metadata author. ### Viewer methods - `refresh()` (Promise): Run the report again. - `setData(data) / setParams(p) / setDefinition(def)` (Promise): Change data, parameters or the definition and re-run. - `goTo(page) / setZoom(z)` (void): Navigate and zoom. - `print()` (Promise): Print (false when onOutput cancelled). - `report` (Report): The report object below (toPdf, toXlsx…). - `destroy()` (void): Remove the viewer. ## Report API (print, PDF, Excel, CSV) - `createReport(def, data, options?)` (Report): Bind a definition to data without a viewer. - `ready()` (Promise): Wait for web fonts, then lay out. Call before the first output in browsers. - `layout()` (LayoutResult): Pages, row count and time (cached). - `print({ pages? })` (Promise): Print through the browser at the exact paper size. - `toPdf()` (Promise): PDF with embedded font subsets. - `toXlsx('form' | 'data')` (Promise): "form" keeps merged cells and borders; "data" writes one row per record. - `toHwpx()` (Promise): Hangul document (.hwpx, KS X 6101) laid out like the printed pages. - `toCsv()` (Promise): CSV (UTF-8 with BOM, so Excel shows Korean correctly). - `download('pdf' | 'xlsx' | 'xlsx-data' | 'csv' | 'hwpx', name?)` (Promise): Create and save the file. ```js import { createReport } from '@freereportjs/core'; const report = createReport(definition, { rows }); await report.ready(); // wait for web fonts, then lay out await report.print(); // browser print at the paper size const pdf = await report.toPdf(); // Blob, fonts embedded const form = await report.toXlsx('form'); // merged cells and borders, like the printout const data = await report.toXlsx('data'); // one row per record await report.download('pdf', '매출 보고서'); // or save directly ``` ## Designer ```js import { createDesigner } from '@freereportjs/core'; import '@freereportjs/core/styles.css'; const designer = createDesigner(document.getElementById('designer'), { definition, // leave out to start with a blank report data: { rows }, // sample data for the field list and the preview lang: 'ko', onChange: def => localStorage.setItem('draft', JSON.stringify(def)), onSave: def => fetch('/api/reports/sales', { method: 'PUT', body: JSON.stringify(def) }), }); designer.setMode('preview'); // 'design' | 'preview' | 'json' const json = designer.getDefinition(); ``` ## Server rendering ```js // Node 20+, Deno or Bun — no browser needed import { writeFile } from 'node:fs/promises'; import { loadFonts, renderPdf, renderXlsx } from '@freereportjs/core'; const fonts = await loadFonts(['Nanum Gothic']); // TTF bytes (or read your own files) const pdf = await renderPdf(definition, { rows }, { fonts, params: { user: 'batch' } }); await writeFile('sales.pdf', pdf); await writeFile('sales.xlsx', await renderXlsx(definition, { rows }, { fonts, mode: 'form' })); ``` ## React ```tsx // npm i @freereportjs/core @freereportjs/react import { useRef, useState } from 'react'; import { FreeReportDesigner, FreeReportViewer, type ReportDefinition } from '@freereportjs/react'; import '@freereportjs/core/styles.css'; export function SalesReport({ definition, rows }) { const ref = useRef(null); // { viewer, report } return ; } export function SalesDesigner({ initial, rows, save }) { const [def, setDef] = useState(initial); return ; } ``` ## Vue ```vue ``` ## Svelte ```svelte (def = d)} onSave={save} /> ``` ## Angular ```ts // npm i @freereportjs/core @freereportjs/angular // angular.json "styles": ["node_modules/@freereportjs/core/dist/styles.css"] import { Component } from '@angular/core'; import { FreeReportDesignerComponent, FreeReportViewerComponent } from '@freereportjs/angular'; @Component({ selector: 'app-sales-report', imports: [FreeReportViewerComponent, FreeReportDesignerComponent], template: ` `, }) export class SalesReportComponent { def = initialDefinition; data = { rows: [] }; save(def) { /* PUT the JSON to your server */ } } ``` ## eGovFrame (JSP) ```html <%-- reportView.jsp: the viewer in an eGovFrame (Spring + JSP) page --%>
``` ## Fonts ```js import { registerFont } from '@freereportjs/core'; registerFont('Malgun Gothic', { css: '/fonts/malgun.css', // @font-face rules for screen and print (optional) normal: '/fonts/malgun.ttf', // TrueType for the PDF (URL or Uint8Array) bold: '/fonts/malgunbd.ttf', }); // then: "font": { "family": "Malgun Gothic" } or "style": { "fontFamily": "Malgun Gothic" } ``` ## PDF security ```js createViewer(el, { definition, data, pdfSecurity: { userPassword: '1234', // asked when the PDF is opened (omit: opens freely) permissions: { print: true, copy: false, modify: false }, }, }); ``` ## Output log hook ```js createViewer(el, { definition, data, params: { user: '홍길동' }, // e = { kind: 'print' | 'pdf' | 'xlsx' | 'xlsx-data' | 'csv', report, pages, rows, params, fileName } onOutput: async e => { const res = await fetch('/api/output-log', { method: 'POST', body: JSON.stringify(e) }); return res.ok; // false cancels the print or download }, }); ``` ## License key ```js import { setLicenseKey } from '@freereportjs/core'; setLicenseKey('FR1.eyJkb21haW5zIjpb...'); // once, before creating viewers // or: createViewer(el, { definition, data, licenseKey: 'FR1.eyJkb21haW5zIjpb...' }) ``` ## Frequently asked questions ### What is FreeReport? FreeReport is a web reporting tool: a report designer, a paged viewer, printing, PDF, Excel and CSV export in one JavaScript package. Reports are JSON definitions made of bands (title, page header, groups, detail, summary, page footer). It is made in Korea for Korean business documents and is an alternative to OZ Report, ClipReport, UbiReport and Crystal Reports. ### Does anything need to be installed? No. The designer, viewer, printing and exports run in the browser on web standards. There is no plugin, ActiveX or print module. An optional, signed Windows program prints silently to a chosen printer for counters and offices that need it. ### Is the Korean text in PDFs searchable? Yes. The PDF embeds a subset of the TrueType font (Nanum Gothic by default, or your own font), so Korean text can be searched and copied, and it looks the same on every computer. ### How much does it cost? Personal, educational, research and non-commercial use is free. Companies pay KRW 500,000 per domain per year, or KRW 900,000 per domain once (perpetual, with one year of updates). VAT separate. There is no limit on developers, users or outputs. ### Can it handle large reports? Yes. 100,000 rows are laid out into thousands of pages, and the viewer draws pages only when they scroll into view. See the 100,000 rows demo. ### Can I convert forms from another reporting tool? There is no automatic converter yet. Forms are rebuilt in the designer or written as JSON; most Korean forms (quotes, statements, certificates) take a few hours. ### Does it work with React, Vue and eGovFrame? Yes. The core package works in any framework (see the code below), and @freereportjs/react, /vue, /svelte and /angular provide FreeReportViewer and FreeReportDesigner components. An integration sample shows FreeReport in an eGovFrame (Spring + JSP) project. ### What counts as company use? Any use by or for a company, organization or public body: internal systems, products you sell, and sites you build for clients. A developer building a system for a client needs a license for that client domain. ### How is an intranet counted? An intranet installation site counts as one domain: the host name your users open (for example report.corp.local or an internal server name). Each separate site needs its own license. ### What happens after the annual term or the perpetual update period? Reports keep working either way; nothing on screen changes. After an annual term the library prints a notice in the developer console until the license is renewed. A perpetual key keeps working forever with the versions released within its update period; newer versions print a console notice until updates are renewed. ### What does the library send to freereport.app? On public domains, once a day: the domain, the page address without query string, the version and whether a key is set. Never report data or anything about your users. Local and private network addresses send nothing. ### How do I get the Windows program? Download the signed installer from this page (Windows 10/11, no administrator rights needed). The first time a site asks to print, the program asks you to allow that site. It works without a key for evaluation; company use needs a license that includes the Windows program. ### Reporting tool basics Q: What is a web reporting tool? A: A web reporting tool lets people view business documents such as quotations, certificates and sales reports in a web page, print them, and save them as PDF or Excel. The layout (report definition) and the data are kept apart, and an engine merges them into pages. FreeReport is a web reporting tool whose designer, viewer, printing and PDF, Excel and HWPX exports all run in the browser. Q: Is there a free reporting tool? A: FreeReport is free, with every feature, for personal, educational, research and non-commercial use. It is the same package companies use, not a limited edition, and it installs with npm i @freereportjs/core. Companies may evaluate it for 30 days and then pay KRW 500,000 per domain per year, or KRW 900,000 per domain once. Q: Who makes FreeReport and what is the latest version? A: FreeReport is made in Korea by 2nd Korea Co., Ltd. ((주)세컨드코리아), the maker of the FreeGrid data grid. The latest version is v0.8.0, published on npm as @freereportjs/core, with packages for React, Vue, Svelte and Angular. Q: Is there a reporting tool that needs no install? A: Yes. FreeReport runs on web standards with no plugin, ActiveX, print module or report server. The designer also runs in the browser, so form authors install nothing. It works in current Chrome, Edge, Firefox and Safari. Q: Can FreeReport replace OZ Report? A: For banded business forms such as quotations, statements, certificates and sales reports, yes. It has a web designer, Korean PDF, Excel as printed, HWPX, 2D barcodes, watermarks and embossing. It has no GS certification yet and no e-Form data entry, so if either is required, the incumbent product is the better fit. Q: Can it replace ClipReport or UbiReport? A: Yes, when the goal is web output without installs and a lower license cost. The server only returns data as JSON, and reports are JSON files that are easy to version. There is no automatic converter for existing forms yet, so forms are rebuilt in the designer. Q: Is it an alternative to Crystal Reports? A: Yes. It builds banded reports with groups, subtotals, page headers and footers and crosstabs like Crystal Reports, and the designer runs in the browser instead of on Windows. It cannot read .rpt files, so reports are rebuilt. Korean PDF and Korean formats are built in. ### Development and integration Q: How do I print reports in an eGovFrame project? A: The controller returns the report definition and the data as JSON, and the JSP page creates a FreeReport viewer. Printing, PDF and Excel are made in the browser, so no report server is needed. The eGovFrame 4.3 sample (Spring 5.3, MyBatis) includes the viewer, the designer and an output log. Q: How do I make a PDF from JSP or Spring? A: Spring returns the data as JSON and FreeReport in the browser calls report.toPdf(). The Korean font is embedded, so the server needs no fonts or PDF library. To create files on a server, call renderPdf from a Node.js job. Q: Can I build reports in React or Vue? A: Yes. @freereportjs/react, @freereportjs/vue, @freereportjs/svelte and @freereportjs/angular provide viewer and designer components. The core package @freereportjs/core has no dependencies and works in any framework with one createViewer call. Q: Can a server generate PDFs in bulk? A: Yes. renderPdf and renderXlsx create the same PDF and Excel files without a browser, in Node.js, Deno or Bun. Text is measured with the TrueType font, so line breaks match the screen. Use it for nightly batches of thousands of statements. Q: What format are report definitions? A: A report is a plain JSON file with the page setup, fonts, parameters, styles and bands of elements positioned in millimetres. You can keep it in Git, generate it in code and store it in a database. With no binary format, an AI assistant can write definitions too. Q: How is report data passed in? A: Data is a JSON object: the rows the detail band repeats plus any values for headers, such as the company name or period. Existing systems only need to return JSON from a REST API or JSP, without changing the database. Q: Does it work on an intranet or air-gapped network? A: Yes. Host the package on your own server; private addresses and intranet hosts send nothing to freereport.app. On a network without internet access, host the PDF fonts (TTF) too and register them with registerFont. One intranet installation site counts as one domain for licensing. ### Output and formats Q: Why does Korean text break in PDFs, and how do I fix it? A: Korean text breaks or shows boxes when the PDF does not contain a Korean font. FreeReport embeds a subset of the TrueType font with only the characters used, so the text looks the same everywhere and can be searched and copied. The default font is Nanum Gothic; your own TTF fonts can be registered. Q: Can I export to Excel exactly as printed? A: Yes. toXlsx('form') keeps the printed layout with merged cells and borders, and toXlsx('data') writes one row per record. Use the form for submissions and the data mode for further analysis. CSV is supported too. Q: Can I export to Hangul (HWP) files? A: Yes. toHwpx() creates an HWPX document (KS X 6101) that opens in Hangul, laid out like the printed pages. It is HWPX, not the older binary .hwp format. Q: Can it print barcodes and QR codes? A: Yes: Code128, EAN-13, QR, DataMatrix and PDF417. Barcodes are drawn as vectors, not images, so they scan sharp at any zoom, in print and in PDF. QR error correction (L/M/Q/H) is selectable. Q: Can it print barcode label sheets? A: Yes. A multi-column detail band (columns: 3, for example) turns each data row into one label. Label size and gaps are set in millimetres. See the barcode label demo for a 3-across sheet. Q: Can it print silently, without the print dialog? A: Browsers cannot skip the print dialog, so FreeReport offers an optional Windows print program. The signed program prints to a chosen printer without a dialog, sets copies, duplex and tray, keeps a print log and updates itself. It runs on Windows 10/11 and installs without administrator rights. Q: Does the printout match the screen? A: Yes. The viewer, printing, PDF and Excel all draw the same pages from the layout engine, so line and page breaks match. Printing uses the exact paper size; a three-page report on screen is three pages in the PDF. Q: Does it support charts and crosstabs? A: Yes. Bar, horizontal bar, line, area, pie and doughnut charts bind to the report data. Crosstabs aggregate rows by columns, such as region × product or region × month, with totals. Groups, subtotals, page subtotals and running totals are supported. ### Security, anti-forgery and privacy Q: Can seals and watermarks prevent forgery? A: Yes. Add a security watermark that repeats the user and print time over the page, a raised web emboss seal, a seal image and a QR code for checking the original. Watermarks appear on screen, in print and in PDF, so photos and copies keep them. The verification page itself is built by each system. Q: Can I password-protect PDFs or block copying? A: Yes. Set an open password and print, copy and modify permissions with AES-256, per report or per user. See the output control demo. Q: Can I keep an output log for documents with personal data? A: Yes. The onOutput event fires before every print or export, so you can record who printed which document, when and in which format. Returning false cancels the output. This supports output records required by Korean personal information protection rules. Q: Is report data sent to an outside server? A: No. Report data and generated files stay in the browser. On public domains the library sends, once a day, only the domain, the page address without query string, the version and whether a key is set; intranet addresses send nothing. Q: Does FreeReport have GS or security certification? A: Not yet. FreeReport was released in 2026 and has no GS certification or security function confirmation (SA). If a public project requires a certified product, consider a certified incumbent. ### Performance Q: Is it fast with large reports? A: Yes. A list of 100,000 rows is laid out into thousands of pages, and the viewer draws only the pages in view, so you can page through at once. Try the 100,000 rows demo. Large PDFs can also be made on a server with renderPdf. ### Pricing and license Q: How much does FreeReport cost? A: Free for personal use. Companies pay KRW 500,000 per domain per year, or KRW 900,000 per domain once (perpetual). With the Windows print program the price doubles: KRW 1,000,000 per year or 1,800,000 perpetual. VAT separate; every plan has every feature. Q: Is there a perpetual license? A: Yes. KRW 900,000 per domain, paid once, never expires and includes one year of updates. After that, reports keep working; renew updates to use newer versions. Q: Are developers, users or outputs limited? A: No. Licenses are per domain (or intranet installation site) and do not count developers, users, servers or outputs. The www address counts as the same domain. Q: Can a company try it before buying? A: Yes. Companies may evaluate every feature for 30 days with no sign-up or key. When you go live, apply for a company license on the pricing page; the domain key is issued once the payment arrives. Q: Can I convert forms from another reporting tool? A: Not automatically yet. Rebuild the form in the designer with the old one beside it, or write the JSON. Common forms such as quotations, statements and certificates take a few hours each. ## 자주 묻는 질문 (Korean) ### FreeReport는 무엇인가요? FreeReport는 웹 리포팅 툴입니다. 보고서 디자이너, 페이지 뷰어, 인쇄, PDF·엑셀·CSV 저장이 자바스크립트 패키지 하나에 들어 있습니다. 보고서는 제목, 페이지 머리글, 그룹, 상세, 요약, 페이지 바닥글 같은 밴드로 이루어진 JSON 정의입니다. 국내 업무 문서를 기준으로 만들었으며 OZ Report, ClipReport, UbiReport, Crystal Reports를 대신해 쓸 수 있습니다. ### 따로 설치해야 하는 것이 있나요? 없습니다. 디자이너, 뷰어, 인쇄, 저장이 모두 웹 표준으로 브라우저에서 동작하며 플러그인, ActiveX, 인쇄 모듈이 필요 없습니다. 창구나 사무실처럼 지정한 프린터로 바로 인쇄해야 하는 곳을 위해 서명된 Windows 프로그램을 선택 사항으로 제공합니다. ### PDF에서 한글을 검색할 수 있나요? 네. 트루타입 글꼴(기본은 나눔고딕, 원하는 글꼴도 가능)을 부분 내장하므로 한글을 검색하고 복사할 수 있고, 어느 PC에서 열어도 똑같이 보입니다. ### 가격은 얼마인가요? 개인, 교육, 연구, 비상업적 용도는 무료입니다. 회사는 도메인당 연 500,000원, 또는 도메인당 900,000원에 영구 라이선스(1년 업데이트 포함)를 구매합니다. 부가세는 별도이며 개발자 수, 사용자 수, 출력 횟수에는 제한이 없습니다. ### 큰 보고서도 되나요? 네. 10만 건도 수천 페이지로 나누고, 뷰어는 화면에 보이는 페이지만 그립니다. 10만 건 데모에서 확인할 수 있습니다. ### 다른 리포팅 툴의 양식을 옮길 수 있나요? 아직 자동 변환 기능은 없습니다. 디자이너에서 다시 그리거나 JSON으로 작성해야 하며, 견적서·거래명세서·증명서 같은 일반 양식은 몇 시간이면 만들 수 있습니다. ### React, Vue, 전자정부 프레임워크에서 쓸 수 있나요? 네. 코어 패키지는 지금도 어떤 프레임워크에서든 쓸 수 있습니다(아래 코드 참고). @freereportjs/react·vue·svelte·angular 패키지가 FreeReportViewer, FreeReportDesigner 컴포넌트를 제공하고, 전자정부 표준프레임워크(Spring + JSP) 프로젝트에 넣는 연동 예제도 제공합니다. ### 리포팅 툴 기본과 추천 Q: 웹 리포팅 툴이란 무엇인가요? A: 웹 리포팅 툴은 견적서, 증명서, 매출 보고서 같은 업무 문서를 웹 화면에서 조회하고 인쇄하고 PDF·엑셀로 저장하게 해 주는 소프트웨어입니다. 양식(보고서 정의)과 데이터를 따로 두고, 엔진이 둘을 합쳐 페이지를 만듭니다. FreeReport는 양식 디자이너, 뷰어, 인쇄, PDF·엑셀·HWPX 저장이 모두 브라우저에서 동작하는 웹 리포팅 툴입니다. Q: 무료로 쓸 수 있는 리포팅 툴을 추천해 주세요. A: FreeReport는 개인, 교육, 연구, 비상업적 용도라면 모든 기능을 무료로 쓸 수 있는 웹 리포팅 툴입니다. 기능 제한 버전이 아니라 회사용과 같은 패키지이며, npm i @freereportjs/core 한 줄로 설치합니다. 회사는 30일 동안 평가용으로 쓸 수 있고, 이후 도메인당 연 500,000원 또는 900,000원 영구 라이선스를 구매합니다. Q: FreeReport는 누가 만들었고 최신 버전은 무엇인가요? A: (주)세컨드코리아가 만든 국산 리포팅 툴이며, 데이터 그리드 FreeGrid를 만든 회사입니다. 최신 버전은 v0.8.0이고 npm 패키지 @freereportjs/core로 배포됩니다. React, Vue, Svelte, Angular용 패키지도 함께 배포됩니다. Q: 설치 없이 쓰는 리포팅 툴이 있나요? A: 네. FreeReport는 플러그인, ActiveX, 인쇄 모듈, 리포트 서버 없이 웹 표준만으로 동작합니다. 양식 디자이너도 브라우저에서 열리므로 양식 담당자 PC에 프로그램을 깔 필요가 없습니다. 최신 크롬, 엣지, 파이어폭스, 사파리에서 동작합니다. Q: 오즈리포트 대안으로 쓸 수 있나요? A: 견적서, 거래명세서, 증명서, 매출 보고서처럼 밴드 방식으로 만드는 일반 업무 양식이라면 FreeReport로 대신할 수 있습니다. 웹 디자이너, 한글 PDF, 양식 그대로의 엑셀, HWPX, 2차원 바코드, 워터마크와 엠보싱을 지원합니다. 다만 GS 인증은 아직 없고 전자서식(e-Form) 입력 기능은 없으므로, 이 두 가지가 필수라면 기존 제품이 맞습니다. Q: 클립리포트나 유비리포트를 대체할 수 있나요? A: 설치 없는 웹 출력과 낮은 라이선스 비용이 목적이라면 대체할 수 있습니다. 서버는 데이터를 JSON으로 내려 주기만 하면 되고, 양식은 JSON 파일로 저장되어 버전 관리가 쉽습니다. 기존 양식을 자동으로 바꾸는 변환기는 아직 없어서 양식은 디자이너에서 다시 만들어야 합니다. Q: 크리스탈 리포트 대안이 될 수 있나요? A: 네. 크리스탈 리포트처럼 그룹, 소계, 페이지 머리글·바닥글, 교차표가 있는 밴드 방식 보고서를 만들 수 있고, 디자이너가 Windows 프로그램이 아니라 웹에 있습니다. .rpt 파일을 읽지는 못하므로 양식은 새로 만들어야 합니다. 한글 PDF와 한국식 서식(일금 ○○원정, 사업자번호)을 기본으로 지원합니다. ### 개발과 연동 Q: 전자정부 표준프레임워크에서 리포트를 출력하려면 어떻게 하나요? A: Controller가 보고서 정의(JSON)와 데이터(JSON)를 내려 주고, JSP 화면에서 FreeReport 뷰어를 만들면 됩니다. 인쇄, PDF, 엑셀 생성은 브라우저에서 처리하므로 별도 리포트 서버가 필요 없습니다. 전자정부 표준프레임워크 4.3(Spring 5.3, MyBatis) 연동 예제에 조회, 디자이너, 출력 이력 저장까지 들어 있습니다. Q: JSP나 Spring에서 PDF를 출력하려면 어떻게 하나요? A: Spring은 데이터를 JSON으로 돌려주고, 브라우저의 FreeReport가 report.toPdf()로 PDF를 만듭니다. 한글 글꼴이 내장되므로 서버에 글꼴을 설치하거나 PDF 라이브러리를 붙일 필요가 없습니다. 서버에서 파일을 만들어야 한다면 Node.js 작업에서 renderPdf를 호출하면 됩니다. Q: React나 Vue에서 보고서를 만들 수 있나요? A: 네. @freereportjs/react, @freereportjs/vue, @freereportjs/svelte, @freereportjs/angular 패키지가 뷰어와 디자이너 컴포넌트를 제공합니다. 코어 패키지 @freereportjs/core는 외부 라이브러리가 없어 어떤 프레임워크에서도 createViewer 한 번으로 쓸 수 있습니다. Q: 서버에서 PDF를 일괄 생성할 수 있나요? A: 네. renderPdf와 renderXlsx가 브라우저 없이 Node.js, Deno, Bun에서 같은 PDF·엑셀 파일을 만듭니다. 트루타입 글꼴로 글자 폭을 재므로 화면과 줄바꿈이 같습니다. 야간 배치로 명세서 수천 건을 만드는 작업에 쓸 수 있습니다. Q: 보고서 양식은 어떤 형식으로 저장되나요? A: 보고서 양식은 평범한 JSON 파일입니다. 용지, 글꼴, 파라미터, 스타일, 밴드와 요소의 위치(mm)가 들어 있어 Git으로 버전 관리하고, 코드로 생성하고, DB에 저장할 수 있습니다. 전용 바이너리 형식이 없으므로 AI 도우미에게 양식 작성을 맡기기도 쉽습니다. Q: 보고서 데이터는 어떻게 넘기나요? A: 데이터는 JSON 객체로 넘깁니다. 상세 밴드가 반복할 행 배열(rows)과 머리글에 쓸 값(회사명, 기간 등)을 함께 담으면 됩니다. 기존 시스템은 REST API나 JSP에서 JSON만 내려 주면 되므로 DB 구조를 바꿀 필요가 없습니다. Q: 사내망(인트라넷)이나 폐쇄망에서도 쓸 수 있나요? A: 네. 패키지 파일을 사내 서버에 두고 쓰면 되고, 사설 IP와 사내 호스트에서는 freereport.app으로 아무것도 보내지 않습니다. 인터넷이 아예 막힌 폐쇄망이라면 PDF용 글꼴(TTF)도 사내 서버에 두고 registerFont로 등록합니다. 라이선스는 사내망 설치 사이트 1곳을 도메인 1개로 계산합니다. ### 출력과 서식 Q: PDF에서 한글이 깨질 때 어떻게 해결하나요? A: PDF에 한글 글꼴이 들어 있지 않으면 한글이 깨지거나 네모로 보입니다. FreeReport는 문서에 쓰인 글자만 골라 트루타입 글꼴을 부분 내장하므로 어느 PC에서 열어도 한글이 똑같이 보이고, 검색과 복사도 됩니다. 기본 글꼴은 나눔고딕이며 회사 글꼴(TTF)도 등록해 쓸 수 있습니다. Q: 엑셀로 양식 그대로 내보낼 수 있나요? A: 네. toXlsx('form')은 셀 병합과 테두리를 살려 인쇄한 모양 그대로 엑셀을 만들고, toXlsx('data')는 한 행에 한 건씩 데이터만 씁니다. 양식 그대로는 결재·제출용으로, 데이터 모드는 다시 가공할 때 씁니다. CSV 저장도 지원합니다. Q: 한글(HWP) 파일로 내보낼 수 있나요? A: 네. toHwpx()가 한/글에서 열리는 HWPX 문서(KS X 6101)를 인쇄한 페이지와 같은 배치로 만듭니다. 구형 바이너리 HWP(.hwp)가 아니라 HWPX 형식입니다. 공공기관 제출 문서처럼 한/글 파일이 필요한 경우에 씁니다. Q: 바코드와 QR 코드를 출력할 수 있나요? A: 네. Code128, EAN-13, QR, DataMatrix, PDF417 다섯 가지를 지원합니다. 바코드를 이미지가 아닌 벡터로 그리기 때문에 어떤 배율에서도, 인쇄와 PDF에서도 선명하게 읽힙니다. QR 오류 정정 수준(L/M/Q/H)도 고를 수 있습니다. Q: 라벨 용지에 바코드 라벨을 찍을 수 있나요? A: 네. 상세 밴드를 여러 열(columns: 3 등)로 찍으면 데이터 한 행이 라벨 한 칸이 됩니다. 라벨 크기와 간격은 mm 단위로 지정합니다. 바코드 라벨 데모에서 3열 라벨 용지를 확인할 수 있습니다. Q: 미리보기 없이 바로 인쇄(무팝업 인쇄)할 수 있나요? A: 브라우저만으로는 인쇄 대화상자를 건너뛸 수 없어서, 선택 사항인 Windows 인쇄 프로그램을 제공합니다. 서명된 프로그램이 지정한 프린터로 대화상자 없이 인쇄하고, 매수·양면·용지함을 지정하고, 인쇄 이력을 남기며, 자동으로 업데이트됩니다. Windows 10/11용이고 관리자 권한 없이 설치됩니다. Q: 화면과 인쇄 결과가 같나요? A: 네. 뷰어, 인쇄, PDF, 엑셀이 모두 레이아웃 엔진이 만든 같은 페이지를 그리므로 줄바꿈과 페이지 나눔이 같습니다. 인쇄는 정확한 용지 크기로 나갑니다. 화면에서 3페이지였던 문서는 PDF에서도 3페이지입니다. Q: 차트와 교차표도 만들 수 있나요? A: 네. 막대, 가로 막대, 꺾은선, 영역, 원형, 도넛 차트를 보고서 데이터에 연결할 수 있습니다. 교차표(crosstab)는 지역 × 품목, 지역 × 월처럼 행과 열을 집계하고 합계를 붙입니다. 그룹, 소계, 페이지 소계, 누계도 지원합니다. ### 보안, 위변조 방지, 개인정보 Q: 직인과 워터마크로 위변조를 막을 수 있나요? A: 네. 출력자와 출력 일시를 페이지 전체에 반복하는 보안 워터마크, 종이에 눌러 찍은 듯한 웹 엠보싱(돋움 직인), 직인 이미지, 원본 확인용 QR 코드를 넣을 수 있습니다. 워터마크는 화면, 인쇄, PDF에 모두 나오므로 사진이나 복사본에도 남습니다. 원본 확인 페이지는 각 시스템에서 구현합니다. Q: PDF에 암호를 걸거나 복사를 막을 수 있나요? A: 네. PDF 열기 암호와 인쇄·복사·수정 권한을 AES-256으로 설정할 수 있습니다. 보고서마다, 또는 사용자마다 다른 암호를 줄 수 있습니다. 출력 보안과 이력 데모에서 확인할 수 있습니다. Q: 개인정보가 담긴 문서의 출력 이력을 남길 수 있나요? A: 네. 인쇄나 저장 직전에 onOutput 이벤트가 오므로, 누가 언제 어떤 문서를 어떤 형식으로 출력했는지 서버에 기록할 수 있습니다. 이벤트에서 false를 돌려주면 출력을 막습니다. 개인정보의 안전성 확보조치 기준에 따른 출력 기록 관리에 쓸 수 있습니다. Q: 보고서 데이터가 외부 서버로 전송되나요? A: 아니요. 보고서 데이터와 만든 파일은 브라우저 안에서만 처리됩니다. 공개 도메인에서 하루 한 번 도메인, 페이지 주소(쿼리 문자열 제외), 버전, 라이선스 키 설정 여부만 보내며, 사내망 주소에서는 아무것도 보내지 않습니다. Q: GS 인증이나 보안 인증을 받았나요? A: 아직 없습니다. FreeReport는 2026년에 공개된 제품으로 GS 인증과 보안기능 확인서(SA)를 받지 않았습니다. 공공 사업에서 인증 제품이 필수 조건이라면 인증을 받은 기존 제품을 검토하세요. ### 성능 Q: 대용량 보고서도 빠르게 출력되나요? A: 네. 10만 건 목록을 수천 페이지로 나누고, 뷰어는 화면에 보이는 페이지만 그려서 바로 넘겨 볼 수 있습니다. 10만 건 데모에서 직접 확인할 수 있습니다. 대량 PDF는 서버에서 renderPdf로 만드는 방법도 있습니다. ### 가격과 라이선스 Q: FreeReport 가격은 얼마인가요? A: 개인은 무료이고, 회사는 도메인당 연 500,000원 또는 도메인당 900,000원(영구)입니다. Windows 인쇄 프로그램을 포함하면 두 배인 연 1,000,000원 또는 1,800,000원(영구)입니다. 부가세 별도이며 모든 기능이 똑같이 들어 있습니다. Q: 영구 라이선스가 있나요? A: 네. 도메인당 900,000원을 한 번 내면 기간 제한 없이 쓰고, 1년 동안의 업데이트가 포함됩니다. 업데이트 기간이 끝나도 보고서는 그대로 동작하며, 그 뒤에 나온 버전을 쓰려면 업데이트를 갱신합니다. Q: 개발자 수나 사용자 수, 출력 횟수 제한이 있나요? A: 없습니다. 라이선스는 도메인(또는 사내망 설치 사이트) 단위이며 개발자 수, 사용자 수, 서버 대수, 출력 횟수를 세지 않습니다. www가 붙은 주소는 같은 도메인으로 봅니다. Q: 회사에서 구매 전에 써 봐도 되나요? A: 네. 회사도 30일 동안 모든 기능을 평가용으로 쓸 수 있고, 신청이나 키가 필요 없습니다. 운영에 쓰기 시작하면 가격 페이지에서 회사 라이선스를 신청하고, 입금이 확인되면 도메인 키를 발급합니다. Q: 다른 리포팅 툴의 양식을 옮길 수 있나요? A: 아직 자동 변환 기능은 없습니다. 기존 서식을 화면에 띄워 놓고 디자이너에서 다시 그리거나 JSON으로 작성합니다. 견적서, 거래명세서, 증명서 같은 일반 양식은 한 장에 몇 시간이면 옮길 수 있습니다. ## Reporting tools compared (public information; ask each vendor for details) - Report designer: FreeReport — Web browser; OZ Report — Desktop program; ClipReport — Desktop program; UbiReport — Desktop program; Crystal Reports — Desktop program (Windows); ActiveReportsJS — Desktop + web designer - Install on user PCs: FreeReport — None (optional agent for silent printing); OZ Report — Depends on setup; ClipReport — Depends on setup; UbiReport — Depends on setup; Crystal Reports — Depends on runtime and server; ActiveReportsJS — None - Report file: FreeReport — JSON; OZ Report — Proprietary; ClipReport — Proprietary; UbiReport — Proprietary; Crystal Reports — .rpt; ActiveReportsJS — JSON-based (.rdlx-json) - Main exports: FreeReport — PDF, Excel (form/data), CSV, HWPX; OZ Report — PDF, Excel and more; ClipReport — PDF, Excel, HWP and more; UbiReport — PDF, XLSX, DOCX, PPTX, HWP and more; Crystal Reports — PDF, Excel, Word, CSV and more; ActiveReportsJS — PDF, XLSX, HTML, CSV - Hangul (HWP/HWPX): FreeReport — HWPX; OZ Report — Ask the vendor; ClipReport — Yes; UbiReport — Yes; Crystal Reports — No; ActiveReportsJS — No - 2D barcodes: FreeReport — QR, DataMatrix, PDF417; OZ Report — QR, DataMatrix, PDF417; ClipReport — Ask the vendor; UbiReport — Ask the vendor; Crystal Reports — Ask the vendor; ActiveReportsJS — Yes - Korean certifications: FreeReport — None (no GS or SA yet); OZ Report — See vendor; ClipReport — GS grade 1, SA; UbiReport — See vendor; Crystal Reports — Not applicable; ActiveReportsJS — Not applicable - Price: FreeReport — Free personal · company KRW 500,000/domain/yr or 900,000 perpetual; OZ Report — Not published (quoted per project); ClipReport — Not published (quoted per project); UbiReport — Not published (quoted per project); Crystal Reports — Published price list; ActiveReportsJS — Published price list Details: https://freereport.app/compare/ · https://freereport.app/ko/compare/ ## Pricing - Personal: Free. Personal, educational, research and non-commercial use; Every feature, no limits; Companies may evaluate it for 30 days. - Company · annual: ₩500,000 per domain, per year. One domain (www included), or one intranet installation site; All updates during the term; Unlimited developers, users and outputs; Tax invoice issued, renewable each year. - Company · perpetual: ₩900,000 per domain, one-time. One payment, the key never expires; One year of updates included (the key carries the update date); One domain (www included), or one intranet installation site; Unlimited developers, users and outputs. - With the Windows program: ₩1,000,000 per domain, per year, or ₩1,800,000 per domain, one-time. A signed local print agent for Windows: silent printing to a chosen printer, copies, duplex and tray, and print logs. The price is double the company license. - All prices exclude VAT. Apply: https://freereport.app/pricing/ (email help@2nd-korea.com) ## Demos - Sales report: Parameters, region groups with subtotals, page subtotals, charts and a watermark with the user and print time. (https://freereport.app/demos/sales/) - Quotation: A Korean form: amount in words, seal image, embossing, Code128 and QR, a table filled with blank rows. (https://freereport.app/demos/quote/) - Certificate: An official certificate with a security pattern, a raised seal and a QR code to check the original. (https://freereport.app/demos/certificate/) - Barcode labels: A 3-across label sheet (detail columns) with Code128 and QR, DataMatrix or PDF417 per label, drawn as vectors. (https://freereport.app/demos/labels/) - Charts: Bar, horizontal bar, line, area, pie and doughnut charts inside a report. (https://freereport.app/demos/charts/) - Crosstab: Region × product group and region × month tables with row and column totals, from the same rows. (https://freereport.app/demos/crosstab/) - 100,000 rows: A list of 100,000 rows laid out into thousands of pages; pages are drawn as they scroll into view. (https://freereport.app/demos/big-data/) - Output control: PDF password and permissions, an output log written before every print or export, and cancelling outputs. (https://freereport.app/demos/output/) ## Releases ### 0.8.0 (2026-10-15) — Feature-complete preview: frameworks, HWPX, direct printing, fingerprints - Version numbering moved to 0.8 to reflect the feature set; the API is stable ahead of 1.0 - Framework components for React, Vue, Svelte and Angular (FreeReportViewer, FreeReportDesigner) and an eGovFrame (전자정부 표준프레임워크) sample - HWPX (Hangul) export laid out like the printed pages; Excel 'as printed' fits each report page on one printed page - Direct printing through the signed Windows print agent (directPrint option) with fallback to the browser dialog - Document fingerprint (SHA-256 of the printed text) with docHash/docHashShort for originality QR codes - Viewer: find text (Ctrl+F) with highlights; Save menu with Excel, Hangul and CSV - Server rendering without a browser: renderPdf, renderXlsx, ttfMeasurer - Fixes: designer escaping of definition values, listener cleanup on destroy, page subtotals with live page rows, CSV negative numbers, decimal rounding, safe table/crosstab expressions, faster layout (100,000 rows in about 2 seconds) ### 0.1.0 (2026-10-15) — First release - Banded report engine: title, page header, column header, groups with headers and footers, detail, summary, page footer and no-data bands - Web report designer in the browser: toolbox, data fields, bands, property panel, preview and JSON views, undo and redo - JSON report definitions with a safe expression language: aggregates over group, page or report scope, running sums, Korean formats (일금 ○○원정, business numbers, phone numbers, dates) - Paged SVG viewer with a parameter panel, zoom, page navigation and keyboard shortcuts - Printing that matches the screen, PDF with an embedded Korean font subset (searchable and copyable text), PDF password and permissions (AES-256) - Excel export as printed (merged cells and borders) or as data, and CSV - Barcodes as vectors: Code128, EAN-13, QR, DataMatrix and PDF417; bar, line, area, pie and doughnut charts - Table and crosstab elements, multi-column detail bands for label sheets - Server rendering without a browser: renderPdf and renderXlsx with TrueType text measurement - Watermarks including a repeated security pattern with the user and print time, and web embossing (raised seals) - Page subtotals, page x / y, blank rows to fill form tables, repeated-value suppression, output event hook for print logs - License keys per domain (annual or perpetual)