JasperReports 모듈형 라이브러리: 서브리포트와 데이터 관리 간소화
JasperReports에서 대규모 보고서 작업을 하다 보면 종종 단일 JRXML 파일이 거대해집니다. 디자인, 데이터 로직, 비즈니스 규칙이 뒤섞여 유지보수가 어려워지죠. 서브리포트는 모듈성을 해결하지만, 데이터를 전달하는 과정이 복잡해집니다.
일반적인 데이터 처리 방식:
- 단일 JSON: XML 내 경로와 함께 JsonDataSource 사용. 경로 오류는 컴파일 시점에 잡히지 않으며, REPORT_DATA_SOURCE가 암묵적으로 전달됩니다.
- 템플릿 내 SQL: 쿼리용 REPORT_CONNECTION 사용. 로직이 Java 외부에 존재하며 타입 검사가 없습니다.
- REPORT_DATA_SOURCE 전달: 소비 가능한 데이터 소스는 첫 번째 서브리포트 이후 소진됩니다.
- 수동 파라미터: 수십 개의 <subreportParameter>와 Java 내 params.put()이 필요하며 동기화가 요구됩니다.
jasper-modular 원리
이 라이브러리는 각 서브리포트에 두 가지 파라미터를 전달합니다:
<prefix>Report— 컴파일된 JasperReport.<prefix>MapParameter— 데이터를 포함하는 Map<String, Object>.
맵은 REPORT_PARAMETERS_MAP을 통해 해제됩니다: 키는 <subreportParameter> 없이 $P{key}가 됩니다. 어노테이션 프로세서가 컴파일 중에 파라미터와 JRXML을 생성합니다. 렌더러는 리플렉션을 사용해 서브리포트를 재귀적으로 채웁니다.
의존성 추가
JasperReports 7.x용:
<dependency>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-starter-jr7</artifactId>
<version>1.0.0</version>
</dependency>
6.x용:
<dependency>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-starter-jr6</artifactId>
<version>1.0.0</version>
</dependency>
maven-compiler-plugin 내 어노테이션 프로세서:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-processor-jr7</artifactId>
<version>1.0.0</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
보고서 클래스 구조
루트 보고서:
@Getter
@Setter
@JasperModularReport(templatePath = "/reports/company_report.jrxml")
public class CompanyReport extends ModularReport {
private TitleSubModule titleSubModule;
private FinancialSubModule financialSubModule;
}
서브리포트:
@Getter
@Setter
@JasperSubreport(templatePath = "/reports/sub_title_report.jrxml", prefix = "Title")
public class TitleSubModule extends SubreportModule {
private CompanyDetails companyDetails;
private String period;
private String currency;
@Override
public boolean isEmpty() {
return companyDetails == null;
}
}
중첩: FinancialSubModule은 RevenueSubModule, ExpenseSubModule, ProfitSubModule을 포함합니다. 각 모듈은 조건부 렌더링을 위해 isEmpty()를 확인합니다.
컬렉션:
@JasperCollection(columnWidth = 150)
private List<RevenueItem> items;
필드 제외:
@JasperIgnore
private transient String internalCache;
JRXML 생성 모드
어노테이션 프로세서는 target/generated-sources/ 내 템플릿을 업데이트합니다:
- CREATE: 파라미터, 데이터셋, 컬렉션 컴포넌트, 서브리포트 밴드를 포함한 완전한 JRXML을 생성합니다.
- INJECT (기본값): 기존 디자인을 보존하면서 누락된 요소를 추가합니다.
- NONE: 변경하지 않습니다.
생성 후, 템플릿은 Jaspersoft Studio에서 세부 조정할 수 있습니다.
샘플 프로젝트 트리:
- CompanyReport
- TitleSubModule (CompanyDetails, period, currency)
- FinancialSubModule
- RevenueSubModule (totalRevenue, growthPercent, List<RevenueItem>)
- ExpenseSubModule (totalExpenses, growthPercent, List<ExpenseItem>)
- ProfitSubModule (grossProfit, operatingProfit, netProfit, margin, List<ProfitBreakdown>)
핵심 요점
- Java 클래스를 통한 모듈성: 타입화된 데이터와 함께 필드로서의 서브리포트.
- 어노테이션 프로세서에 의한 자동 파라미터 및 JRXML 생성.
- 수동 데이터 전달 없이 재귀적 렌더링.
- @JasperCollection과 무제한 중첩 깊이를 지원하는 컬렉션 지원.
- JasperReports 6.x/7.x 및 Spring Boot 3.x/4.x와 호환성.
— Editorial Team
아직 댓글이 없습니다.