FreeReportv0.9.0English

백엔드 언어별 예제

Node.js, Java(Spring Boot), C#(ASP.NET Core), Python, PHP, Go에서 보고서 정의와 데이터를 JSON으로 내려 주고 출력 이력을 남기는 예제입니다. 어떤 백엔드 언어든 쓸 수 있습니다.

FreeReport는 화면 구성, 인쇄, 파일 저장을 브라우저에서 처리하므로 서버는 보고서 양식과 데이터를 JSON으로 돌려주기만 하면 됩니다. 어떤 언어·프레임워크든 쓸 수 있고 서버에 설치할 것이 없습니다. 아래 예제는 모두 같은 주소 네 개를 구현하므로, 백엔드를 무엇으로 고르든 브라우저 코드는 그대로입니다.

주소응답설명
GET /api/reports/{name}JSON디자이너에서 저장한 보고서 양식(정의).
PUT /api/reports/{name}204양식 저장(디자이너 onSave). 이름과 본문이 JSON인지 확인합니다.
GET /api/reports/sales/data?from=&to={ rows: [...] }조회 조건에 맞는 행(뷰어 fetchData). 키는 양식에서 쓰는 필드 이름입니다.
POST /api/report-logs204인쇄·저장 한 건(뷰어 onOutput): kind, report, pages, rows, params.

브라우저 (모든 백엔드 공통)

import { createViewer } from '@freereportjs/core';
import '@freereportjs/core/styles.css';

const json = (url: string, init?: RequestInit) =>
  fetch(url, init).then(r => { if (!r.ok) throw new Error(r.status + ' ' + url); return r.json(); });

// 1. the report form (made in the designer)  2. rows for the parameters  3. output log
const viewer = createViewer(document.getElementById('viewer')!, {
  definition: await json('/api/reports/sales'),
  params: { from: '2026-10-01', to: '2026-10-31' },
  fetchData: params => json('/api/reports/sales/data?' + new URLSearchParams(params as Record<string, string>)),
  onOutput: e => fetch('/api/report-logs', {
    method: 'POST', headers: { 'content-type': 'application/json' }, body: JSON.stringify(e),
  }).then(r => r.ok),                     // false: the server refused, nothing is printed or saved
  lang: 'ko',
});

// designer: createDesigner(el, { onSave: def => fetch('/api/reports/sales', { method: 'PUT', body: JSON.stringify(def), headers: { 'content-type': 'application/json' } }) })

서버 예제

// Node.js 20+ · npm i express@5 pg @freereportjs/core
import express from 'express';
import { readFile, writeFile } from 'node:fs/promises';
import pg from 'pg';
import { loadFonts, renderPdf } from '@freereportjs/core';

const app = express();
const db = new pg.Pool();                                  // PGHOST, PGUSER, … from the environment
app.use(express.json({ limit: '5mb' }));

const file = name => {
  if (!/^[\w-]+$/.test(name)) throw Object.assign(new Error('bad name'), { status: 400 });
  return 'reports/' + name + '.json';
};
const salesRows = async (from, to) => (await db.query(
  `SELECT to_char(sold_on, 'YYYY-MM-DD') AS date, region, product, qty, amount::float8 AS amount
     FROM sales WHERE sold_on BETWEEN $1 AND $2 ORDER BY region, sold_on`, [from, to])).rows;

// report form: the viewer loads it, the designer saves it
app.get('/api/reports/:name', async (req, res) => { res.type('json').send(await readFile(file(req.params.name), 'utf8')); });
app.put('/api/reports/:name', async (req, res) => {
  await writeFile(file(req.params.name), JSON.stringify(req.body, null, 2));
  res.sendStatus(204);
});

// data for the viewer's parameters
app.get('/api/reports/sales/data', async (req, res) => {
  res.json({ rows: await salesRows(String(req.query.from), String(req.query.to)) });
});

// output log (viewer onOutput)
app.post('/api/report-logs', async (req, res) => {
  const { kind, report, pages, rows, params } = req.body;
  await db.query('INSERT INTO report_log (user_id, kind, report, pages, row_count, params, ip) VALUES ($1, $2, $3, $4, $5, $6, $7)',
    [req.user?.id ?? null /* from your auth middleware */, kind, report, pages, rows, JSON.stringify(params), req.ip]);
  res.sendStatus(204);
});

// only JavaScript runtimes can also make the PDF on the server (batch jobs, e-mail attachments)
const fonts = await loadFonts(['Nanum Gothic']);
app.get('/api/reports/sales/pdf', async (req, res) => {
  const definition = JSON.parse(await readFile(file('sales'), 'utf8'));
  const rows = await salesRows(String(req.query.from), String(req.query.to));
  res.type('pdf').send(Buffer.from(await renderPdf(definition, { rows }, { fonts, params: req.query })));
});

app.listen(3000);

확인할 점

  • 날짜는 "yyyy-MM-dd" 문자열로, 금액은 숫자로 돌려주세요. 그래야 서식과 합계가 맞습니다. 행의 키는 양식에서 쓰는 필드 이름입니다.
  • 보고서 이름은 파일 경로에 쓰기 전에 검사하고, 저장하는 양식이 JSON인지 확인하세요. 저장과 이력 주소는 로그인한 사용자만 쓰게 하세요.
  • 서버가 여러 대라면 양식을 파일 대신 DB 테이블에 두세요. 정의는 JSON 텍스트 컬럼 하나입니다.
  • 서버에서 PDF·엑셀 파일을 만들려면 자바스크립트 런타임(Node.js, Deno, Bun의 renderPdf, renderXlsx)이 필요합니다. Java, C#, Python, PHP, Go에서는 작은 Node 서비스를 호출하거나 브라우저에서 파일을 만들게 하세요. 서버에서 생성
  • Spring + JSP(전자정부 표준프레임워크)는 내려받을 수 있는 예제 프로젝트를 보세요. 프레임워크와 전자정부