Introduction
안녕하세요, Risk & Compliance Team에서 백엔드 개발자로 일하고 있는 Woony입니다. 저희 팀은 인도에서 운영 중인 저희 서비스 TrueBalance 및 TrueCredits의 위험 관리 및 규제 준수를 위한 시스템을 개발하고 유지보수하는 역할을 담당하고 있습니다.
금융 서비스, 특히 핀테크 분야에서 문서 처리와 전자 서명은 사업의 핵심 기능 중 하입니다. 밸런스히어로의 대출 관리 시스템은 인도에서 대출 계약서, 승인서 등 다양한 법적 문서를 PDF로 생성하고 전자 서명하는 기능을 제공하고 있습니다.
최근 저희는 사내 오픈소스 정책 검토 과정에서 PDF 처리 솔루션에 오픈소스 라이브러리를 도입하기로 결정했습니다. 비즈니스 확장에 따른 총소유비용(TCO) 최적화와 라이선스 유연성 확보가 주요 목적이었는데요.
이 블로그에서는 오픈소스 PDF 라이브러리인 OpenPDF 라이브러리 도입 과정에서 얻은 경험, 특히 전자 서명이라는 복잡한 기능의 구현 세부사항과 코드 리팩토링 작업에 대해 공유하고자 합니다. 핀테크 개발자 및 오픈소스에 관심 있는 분들께 실질적인 기술적 인사이트를 제공할 수 있기를 바랍니다.
⚠️ 고지사항
본 글은 특정 상황에서의 기술적 경험을 공유하는 것으로, 모든 환경에 적용 가능한 일반적인 권고사항이 아닙니다. 라이선스 정책과 규제 요건은 지역별, 시기별로 다를 수 있으며, 실제 도입 전에는 반드시 법무팀 및 컴플라이언스 전문가와 상의하시기 바랍니다.
프로젝트 배경: 오픈소스 PDF 라이브러리 도입
기존 시스템의 PDF 관련 기능
기존에 구현된 PDF 관련 핵심 기능들은 아래와 같습니다:
HTML → PDF 변환: 저희는 대출 계약서나 승인서 같은 동적 문서들을 HTML 템플릿으로 만들어두고, 이를 PDF로 변환하는 방식을 사용하고 있습니다. 이렇게 하면 문서 레이아웃을 유연하게 관리할 수 있습니다.
PDF 조작·병합: 여러 문서를 하나로 합치거나, 특정 페이지만 추출하거나, 페이지 순서를 바꾸는 등의 작업이 필요한 경우가 많습니다. 예를 들어 대출 계약서와 부속 서류들을 하나의 문서로 만들어야 할 때 이런 기능이 꼭 필요합니다.
PDF 전자 서명: 저희에게는 가장 중요한 기능 중 하나입니다. 금융 문서의 법적 효력을 보장하기 위해서는 디지털 서명이 반드시 필요하기 때문입니다. 이때, 서명의 시각적 표현뿐만 아니라 검증 기능까지 포함해야 합니다.
PDF 텍스트 추출: 서명을 어디에 배치할지 계산하거나, 문서 내용을 분석해서 색인화하는 용도로 사용하고 있습니다.
새로운 라이브러리로 전환하더라도 이 모든 기능들을 그대로 유지하는 것이 저희의 가장 큰 목표였습니다.
오픈소스 전환 배경
정기적인 기술 스택 검토 과정에서 몇 가지 고려사항들이 나왔는데요.
먼저 라이선스의 지속가능성 문제였습니다. 장기적으로 봤을 때 안정적이고 예측 가능한 라이선스 모델이 필요했어요.
두 번째는 비용 효율성이었습니다. 서비스가 확장되면서 문서 처리량이 늘어나고 있는데, 그에 따른 총소유비용을 최적화할 필요가 있었어요.
마지막으로는 규제 적합성 문제도 있었습니다. 인도에서 서비스하다 보니 현지 법규나 보안 요구사항들을 만족해야 하는데, 이런 부분에서 오픈소스가 더 유연할 수 있다고 판단했어요.
라이선스 분석 및 대안 검토
주요 오픈소스 PDF 라이브러리 라이선스 비교
PDF 처리를 위한 주요 오픈소스 라이브러리들의 라이선스 모델을 꼼꼼히 분석해봤습니다. 각각의 특징들을 표로 정리해보면 이렇습니다.
각 오픈소스 라이브러리 별 라이선스 모델 상세 분석
Apache 2.0은 가장 자유로운 라이선스 중 하나지만, 저희가 고려했던 Apache PDFBox는 기존 코드와의 호환성 면에서 아쉬운 부분이 있었습니다.
반면, OpenPDF의 LGPL/MPL 듀얼 라이선스는 상대적으로 유연합니다. LGPL(Lesser General Public License)의 핵심은 라이브러리를 단순히 사용하기만 할 때는 소스 공개 의무가 없다는 점인데요. 라이브러리 자체를 수정했을 때만 해당 수정사항을 공개하면 되거든요.
MPL(Mozilla Public License)은 파일 단위로 카피레프트가 적용되는 더욱 세밀한 구조예요. 다른 라이선스와의 호환성도 좋고, 상용 서비스에서 안전하게 활용할 수 있습니다.
라이선스 해석 주의사항: 위 내용은 일반적인 라이선스 특징을 설명한 것으로, 구체적인 법적 해석은 상황에 따라 달라질 수 있습니다. 실제 적용 전에는 반드시 법무팀과 상의하시기 바랍니다.
OpenPDF vs Apache PDFBox, 최종 선택의 근거
두 오픈소스 라이브러리를 직접 비교해본 결과를 정리해보면 이렇습니다.
결론적으로, OpenPDF로의 전환은 API 호환성 덕분에 가장 효율적인 마이그레이션 경로를 제공했습니다. 전환 비용과 리스크를 최소화하면서도 라이선스 유연성을 확보할 수 있는 선택이었습니다.
의사결정 프레임워크: 오픈소스 라이브러리 선택 기준
오픈소스 라이브러리를 선택할 때 저희가 적용한 평가 기준들을 소개해보겠습니다. 이런 프레임워크를 미리 정해두면 더 체계적이고 객관적인 판단을 할 수 있어요.
라이선스 적합성을 첫 번째 기준으로 잡았습니다. 저희 비즈니스 모델과 호환되는지, 장기적인 법적 리스크는 없는지, 소스코드 공개 의무의 범위는 어느 정도인지를 꼼꼼히 검토했어요.
기술적 호환성도 중요한 기준이었어요. 기존 코드베이스와 얼마나 잘 맞는지, 마이그레이션 작업량은 어느 정도 예상되는지, 성능이나 안정성 수준은 어떤지를 평가했습니다.
생태계의 건전성도 살펴봤어요. 커뮤니티가 얼마나 활발한지, 정기적인 업데이트가 이루어지는지, 이슈 대응 속도는 어떤지 등을 확인했어요. 오픈소스 프로젝트는 커뮤니티의 활동성이 정말 중요합니다.
마지막으로 규제 준수 측면도 고려했습니다. 저희가 서비스하는 지역의 법규 요구사항을 충족하는지, 보안 표준을 지원하는지, 필요할 때 감사 대응이 가능한지를 점검했습니다.
PDF 디지털 서명의 기술적 이해
저희가 사용하던 PDF 관련 핵심 기능 중, 가장 신경써야 했던 것은 바로 디지털 서명(Digital Signature) 기능이었습니다. OpenPDF에서는 디지털 서명에 대한 고수준의 메서드를 제공하지 않아 직접 저수준에서 구현해야 했기 때문입니다. 이 글을 읽을 독자들이 OpenPDF 도입을 고려할 수 있음을 감안해 디지털 서명에 대한 설명을 따로 할애하겠습니다.
디지털 서명을 이해하기 위해서는 몇 가지 암호화 기본 개념을 알아야 합니다. 이 섹션에서는 도입 과정에서 중요했던 핵심 개념들을 설명하겠습니다.
공개키 기반 구조(PKI) 상세 이해
디지털 서명의 핵심에는 공개키 기반 구조(PKI)가 있습니다. 이는 안전한 디지털 서명을 위한 필수적인 기술 체계입니다. PKI를 쉽게 이해하기 위해 실생활 비유로 설명해 보겠습니다.
PKI의 핵심 요소
1) 비대칭 암호화(개인키/공개키 쌍)
비대칭 암호화는 두 개의 수학적으로 연결된 키를 사용합니다:
개인키: 소유자만 가지고 있는 비밀 키로, 금고 열쇠나 집 열쇠와 유사합니다.
공개키: 누구나 접근할 수 있는 키로, 현관문에 달린 자물쇠라고 보면 됩니다. 누구나 볼 수 있지만, 개인키 없이는 열 수 없습니다.
암호화는 다른 사람이 내 공개키(자물쇠)로 현관문을 잠그는 행위이며, 이는 누구나 할 수 있습니다.
하지만 복호화(암호를 푸는 행위)는 오로지 개인키가 있어야만 할 수 있습니다.
이를 디지털 문서 서명에 적용하게 되면:
개인키는 여러분만 가진 특별한 도장이나 서명입니다.
공개키는 여러분의 서명이 진짜인지 확인할 수 있는 공개된(누구나 볼 수 있는) 서명 샘플입니다.
공개키로는 개인키로 서명한게 진짜인지 아닌지를 판별할 수는 있지만 서명 자체를 할 수는 없습니다.
2) 디지털 인증서(X.509)
디지털 인증서는 공개키가 특정 개인이나 조직에 속한다는 것을 증명하는 전자 문서입니다:
여권이나 주민등록증과 유사하게, 신원을 증명합니다.
인증서에는 소유자 정보, 공개키, 인증 기관의 서명 등이 포함됩니다.
인증서는 계층적 신뢰 구조를 갖습니다 (루트 CA → 중간 CA → 최종 사용자 인증서).
3) 인증 기관(CA, Certificate Authority)
인증 기관은 디지털 인증서를 발급하고 검증하는 신뢰할 수 있는 제3자입니다:
정부 발급 신분증의 발급 기관과 같은 역할을 합니다.
CA는 신원 확인 후 디지털 인증서를 발급하고 자신의 개인키로 서명합니다.
국내에서는 금융결제원, 한국정보인증 등이 공인된 CA로 활동합니다.
4) 해시 함수
해시 함수는 문서의 무결성을 확인하는 수학적 알고리즘입니다:
어떤 크기의 데이터든지 고정된 길이의 해시값으로 변환합니다.
원본 데이터가 1비트라도 변경되면 해시값이 완전히 달라집니다.
지문과 유사하게, 각 문서는 고유한 해시값을 가집니다.
SHA-256은 현재 표준으로 사용되는 강력한 해시 알고리즘입니다.
5) 디지털 서명 프로세스
디지털 서명 과정을 단계별로 설명하면:
해시 생성: 문서의 내용을 SHA-256과 같은 알고리즘으로 해싱합니다.
서명 생성: 해시값을 개인키로 암호화하여 디지털 서명을 생성합니다.
서명 첨부: 원본 문서와 서명을 PKCS#7/CMS 형식의 컨테이너에 함께 포함시킵니다.
검증 과정: 수신자는 서명자의 공개키로 서명을 복호화하고, 문서의 해시값과 비교하여 진위를 확인합니다.
6) PKCS#7/CMS 컨테이너
PKCS#7/CMS는 디지털 서명 데이터를 표준화된 형식으로 저장하는 컨테이너입니다. 이 컨테이너에는 아래와 같은 정보가 들어가게 되는데요:
서명된 해시값
서명 알고리즘 정보
인증서 체인
서명 시간 정보
기타 메타데이터
PDF에서는 이 PKCS#7 컨테이너가 /Contents 필드에 포함되어 서명의 핵심 구성 요소가 됩니다.
PKI가 제공하는 핵심 보안 요소
PKI 기반 디지털 서명은 다음과 같은 보안 요소를 제공합니다:
진위성(Authentication): 서명이 실제로 명시된 발신자에 의해 생성되었는지 확인합니다.
무결성(Integrity): 서명된 후 문서가 변경되지 않았음을 보장합니다.
부인 방지(Non-repudiation): 서명자가 나중에 서명 사실을 부인할 수 없도록 합니다.
시간 증명(Timestamping): 서명이 특정 시점에 존재했음을 증명합니다.
이러한 PKI의 원리와 요소들은 OpenPDF를 사용한 디지털 서명 구현의 기초가 됩니다. 특히 금융 문서와 같이 법적 효력이 중요한 문서에서는 이러한 보안 요소들이 필수적입니다.
PDF 서명의 구조적 이해
PDF 서명 프로세스는 다음과 같은 단계로 이루어집니다:
키스토어 준비: PKCS#12 형식의 키스토어에서 개인키와 인증서 체인을 로드합니다.
서명 필드 생성: PDF에 서명 필드를 추가하고, 서명 데이터를 위한 공간을 예약합니다.
문서 해싱: 예약된 공간을 제외한 문서 전체를 해싱합니다.
PKCS#7 생성: 해시값에 개인키로 서명하고, 서명 시간, 인증서 등의 정보를 포함하는 PKCS#7 구조를 생성합니다.
서명 데이터 삽입: 생성된 PKCS#7 데이터를 PDF의 예약된 공간에 삽입합니다.
이 과정은 문서의 '증분 업데이트(incremental update)'로 이루어지며, 원본 PDF는 그대로 유지한 채 서명 정보만 추가됩니다.
OpenPDF에서의 디지털 서명 구현
아래 코드는 학습용 예시입니다. 실제 운영 환경에서는 HSM(Hardware Security Module), 보안 키 관리 솔루션, 타임스탬프 서버 등의 추가 보안 조치가 필요합니다.
1. 키스토어와 인증서 설정
먼저, 서명에 사용할 개인 키와 인증서가 포함된 키스토어를 로드합니다:
public class DocumentSigner {
private static final String KEYSTORE_TYPE = "PKCS12";
public static SigningKey loadSigningKey(String keystorePath, String password, String alias) {
try (InputStream keyStream = loadKeystoreStream(keystorePath)) {
KeyStore keystore = KeyStore.getInstance(KEYSTORE_TYPE);
keystore.load(keyStream, password.toCharArray());
X509Certificate certificate = (X509Certificate) keystore.getCertificate(alias);
PrivateKey privateKey = (PrivateKey) keystore.getKey(alias, password.toCharArray());
Certificate[] certChain = keystore.getCertificateChain(alias);
return new SigningKey(privateKey, certificate, certChain);
} catch (Exception e) {
throw new SigningException("Failed to load signing key", e);
}
}
}
여기서 KEYSTORE_TYPE은 "PKCS12"로, 표준 키스토어 형식을 사용합니다. 인증서와 개인키는 보안을 위해 외부 파일에서 로드됩니다.
🔒 보안 팁: 운영 환경에서는 키스토어 경로와 패스워드를 환경변수나 보안 키 관리 솔루션에서 주입하고, HSM 기반 PKCS#11 인터페이스를 사용하는 것을 권장합니다.
2. 서명 프로세스 구현
OpenPDF에서 PDF 서명은 PdfStamper.createSignature를 통해 시작되며, 서명 영역과 모양을 정의하고 실제 서명 데이터를 계산하는 복잡한 프로세스입니다:
public SignedDocument signDocument(byte[] pdfData, DocumentType docType) {
PdfStamper stamper = null;
try {
PdfReader reader = new PdfReader(pdfData);
ByteArrayOutputStream signedPdf = new ByteArrayOutputStream();
// 서명을 위한 PDF 스탬퍼 생성
stamper = PdfStamper.createSignature(reader, signedPdf, '\0');
// 서명 외관 설정
PdfSignatureAppearance appearance = setupSignatureAppearance(stamper);
// 서명 위치 설정
setSignaturePosition(appearance, docType, reader.getNumberOfPages());
// 실제 서명 적용
byte[] signatureData = applyDigitalSignature(appearance);
return new SignedDocument(signedPdf.toByteArray(), signatureData);
} catch (Exception e) {
throw new SigningException("Document signing failed", e); } finally {
closeStamper(stamper);
}
}
여기서 중요한 점은:
PdfStamper.createSignature로 서명 프로세스를 초기화합니다.
setupSignatureAppearance, setSignaturePosition로 서명의 위치와 크기를 지정합니다.
appearance.setRender로 서명의 시각적 표현을 설정합니다.
applyDigitalSignature로 실제 암호화 서명을 적용합니다.
3. 서명 모양 및 메타데이터 설정
서명의 시각적 모양과 메타데이터를 설정하는 과정은 다음과 같습니다:
private PdfSignatureAppearance setupSignatureAppearance(PdfStamper stamper) {
PdfSignatureAppearance appearance = stamper.getSignatureAppearance();
// 서명 기본 정보 설정
appearance.setReason("Legal Document Signature");
appearance.setLocation("Digital Signature Service");
appearance.setSignDate(Calendar.getInstance());
// 인증서 설정
appearance.setCertificate(signingKey.getCertificate());
// 서명 외관
appearance.setRender(
PdfSignatureAppearance.SignatureRender.DESCRIPTION);
appearance.setAcro6Layers(true);
// 서명 텍스트 설정
String signerName = extractSignerName(signingKey.getCertificate());
String signatureText = String.format( "Digitally signed by: %s\nDate: %s\nReason: %s", signerName, formatSignatureDate(new Date()), "Legal Document Signature" );
appearance.setLayer2Text(signatureText);
return appearance;
}
여기서는:
서명자 정보, 서명 이유, 서명 위치, 서명 시간 등 메타데이터를 설정합니다.
appearance.setRender로 서명의 시각적 표현 방식을 지정합니다.
appearance.setLayer2Text로 서명 필드에 표시될 텍스트를 설정합니다.
4. 암호화 과정 상세 설명
OpenPDF에서 디지털 서명 시 암호화 과정은 여러 단계로 이루어집니다. 아래 코드는 이 과정의 핵심부입니다:
private static final int SIGNATURE_SIZE = 8192; // 8KB 서명 공간 예약
private byte[] applyDigitalSignature(PdfSignatureAppearance appearance) throws GeneralSecurityException, DocumentException, IOException {
// 서명 데이터를 위한 충분한 공간 예약
Map<PdfName, Integer> exclusionSizes = new HashMap<>();
exclusionSizes.put(PdfName.CONTENTS, SIGNATURE_SIZE * 2 + 2);
appearance.preClose(exclusionSizes);
// 문서 해시 계산 (서명 영역 제외)
byte[] documentHash = MessageDigest.getInstance("SHA-256") .digest(appearance.getRangeStream().readAllBytes());
// PKCS#7 컨테이너 생성
PdfPKCS7 pkcs7 = new PdfPKCS7( signingKey.getPrivateKey(), signingKey.getCertificateChain(), null, "SHA-256", null, false );
// 인증된 속성 생성 및 서명
byte[] authenticatedAttributes = pkcs7.getAuthenticatedAttributeBytes( documentHash, appearance.getSignDate(), null );
// RSA 서명 계산
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(signingKey.getPrivateKey());
signature.update(authenticatedAttributes);
byte[] signatureBytes = signature.sign();
// 서명 데이터 설정
pkcs7.setExternalDigest(signatureBytes, null, "RSA");
// 최종 PKCS#7 인코딩
return pkcs7.getEncodedPKCS7(documentHash, appearance.getSignDate(), null, null, null);
}
이 코드를 단계별로 자세히 설명하면:
1) 서명 공간 예약
서명 데이터를 저장할 공간을 미리 할당합니다. PDF는 서명 전에 서명 데이터의 크기를 알아야 하므로, 충분한 공간을 예약해야 합니다. 여기서는 약 8KB를 예약했습니다.
2) 문서 해싱
문서의 서명 대상 부분에 대한 SHA-256 해시를 계산합니다. 여기서 핵심은 appearance.getRangeStream()이 반환하는 스트림이 서명 공간을 제외한 문서의 모든 부분을 포함한다는 점입니다. 이 해시값이 문서 무결성을 보장합니다.
3) PKCS#7 컨테이너 생성
PdfPKCS7 객체는 디지털 서명, 인증서 체인, 시간 정보 등을 포함하는 PKCS#7 컨테이너를 생성합니다. 이 단계에서 개인키, 인증서 체인, 해시 알고리즘 등이 설정됩니다.
4) 인증된 속성(Authenticated Attributes) 처리
인증된 속성은 서명 과정에서 추가적으로 보호되는 메타데이터로, 해시값, 서명 시간, 서명 유형 등을 포함합니다. 이 속성들은 서명의 일부로 포함되어 보호됩니다.
5) RSA 서명 계산
SHA-256으로 해싱된 인증된 속성에 개인키로 RSA 서명을 계산합니다. 이것이 실제 '서명' 과정입니다.
6) PKCS#7 인코딩 및 삽입
최종적으로 해시값, 서명값, 인증서 체인 등을 포함한 PKCS#7 구조를 DER 형식으로 인코딩하고, 이를 PDF의 예약된 공간에 삽입합니다.
OpenPDF 도입 과정에서 주요 구현사항 및 기술적 도전
OpenPDF를 도입하는 과정에서 다음과 같은 주요 변경 및 개선이 이루어졌습니다:
1. 디지털 서명 관련 고수준 API의 부재로 인해 저수준 API로 직접 서명 프로세스 구현
OpenPDF에는 디지털 서명 기능과 관련해 고수준의 추상화된 API가 없습니다. 따라서 위에서 설명했던 ‘OpenPDF에서의 디지털 서명 구현’과 같이 저수준 API를 사용해 서명 프로세스를 직접 구현해야 했습니다.
2. 문서 병합 기능 구현
OpenPDF에서 문서를 병합할 때는 각 페이지를 개별적으로 가져와 추가해야 합니다.
// OpenPDF에서의 문서 병합
PdfReader reader = new PdfReader(pdf);
int numOfPages = reader.getNumberOfPages();
for (int i = 1; i <= numOfPages; i++) {
copy.addPage(copy.getImportedPage(reader, i));
}
이러한 기능은 페이지별 처리가 가능해져 특정 페이지만 선택적으로 병합하는 장점이 있습니다.
3. 디지털 서명 보안성 유지
OpenPDF 도입 과정에서 가장 중요한 점은 디지털 서명의 보안성과 법적 유효성을 유지하는 것이었습니다. 이를 충족시키기 위한 요구사항은 아래와 같았는데요. 오픈소스로 구현할 때도 동일하게 해당 사항을 적용시켰습니다.
SHA-256 해시 알고리즘 사용
RSA 2048비트 키 사용
PKCS#7 형식 준수
4. 코드 품질 개선
오픈소스 도입을 기회로 전반적인 코드 품질을 개선했습니다. 다른 개발자들이 해당 코드를 더 읽기 쉽게 고쳤다고 이해해주시면 되겠습니다:
매직 넘버 제거 및 상수화
예외 처리 개선 (적절한 로깅 추가)
불필요한 주석 제거
구조적 개선:
공통 클래스 추출
리팩토링을 통한 코드 가독성 및 유지보수성 향상
검증 및 테스트 전략
마지막으로, 상용 서비스에서 문제 없이 원활하게 동작하는 것을 보장하기 위한 검증 프로세스를 도입했습니다:
1. 문서 검증 및 호환성 테스트
기존 문서 및 신규 문서 간 비교 검증: PDF producer를 제외한 다른 모든 내용이 동일한지 확인
서명 유효성
서명 위치
메타데이터
2. 성능(P95) 모니터링
마이그레이션 전후의 성능 차이를 정량적으로 검증하기 위해 실제 운영 환경과 유사한 조건에서 24시간 동안 모니터링을 수행했습니다. 주요 지표는 문서 생성 실행 시간으로, P95 지표를 중점으로 확인했는데요. P95는 통계에서 95번째 백분위수를 의미합니다. 예컨대, P95가 10초 소요된다고 하면 전체 측정값 중 95% 는 10초 이내로 소요되고 상위 5%만이 10초 이상 소요된다고 할 수 있습니다.
현재 저희 서비스에서 생성되는 PDF의 양이 많지는 않았기 때문에(초당 수백건 내외) Gatling 등을 통한 부하 테스트를 따로 진행하지는 않았습니다.
모니터링 환경 및 방법
모니터링 대상: 대출 승인서, 지급 영수증, 채무 증명서 등 주요 문서 유형
모니터링 환경: stage0 (기존 솔루션) vs stage3 (오픈소스 라이브러리)
측정 기간: 24시간 연속 측정 (30분 단위 집계)
측정 지표: 문서 생성 실행 시간의 95백분위수(P95)
성능 모니터링 결과
문서 생성 실행 시간 (P95 기준):
- 기존 솔루션: 2.5초
- 신규 오픈소스 라이브러리: 2.0초
- 성능 차이: ±5% 이내
기존 솔루션과 도입한 라이브러리 간 P95 실행 시간에 의미 있는 차이가 없음을 확인했습니다. 이는 둘 사이에 문서 생성에 걸리는 시간에 유의미한 차이가 없다는 것을 확인했음을 뜻합니다.
±5% 범위의 변동은 일반적인 시스템 노이즈 수준으로 판단했습니다.
결론 및 교훈
OpenPDF 오픈소스 라이브러리 도입은 기술적 도전이었지만, 다음과 같은 긍정적인 결과를 가져왔습니다:
1. 라이선스 유연성 확보
LGPL/MPL 라이선스 하에서 비즈니스 확장에 따른 제약 없이 PDF 라이브러리를 활용할 수 있게 되었습니다.
2. 기술적 역량 강화
PDF 생성 및 디지털 서명의 저수준 구현에 대한 이해도가 크게 향상되었습니다. 특히 PKI, PKCS#7, 증분 업데이트 등의 개념에 대해 심층적으로 이해를 쌓을 수 있었습니다.
3. 코드 품질 향상
마이그레이션 과정에서 코드 리팩토링을 통해 유지보수성과 가독성이 개선되었습니다.
4. 기술 스택 결정 시 고려사항
오픈소스 라이브러리 선택 시 고려해야 할 요소들을 재확인했습니다:
라이선스 정책의 장기적 영향
API 호환성과 커뮤니티 지원
총소유비용(TCO)
이러한 경험 공유가 향후 유사한 마이그레이션 프로젝트나 기술 스택 결정 시 유용한 참고 자료가 되기를 바랍니다.
참고 자료
오픈소스 프로젝트
라이선스 가이드
PDF 및 전자 서명 표준
암호화 및 PKI
라이선스 및 상표 고지 (NOTICE)
본 글에서 사용된 코드 예시는 Apache License 2.0 하에 제공됩니다.
오픈소스 프로젝트 크레딧:
OpenPDF © LibrePDF Project (LGPL v3 / MPL 2.0)
본 글은 2025년 5월 26일 작성되었으며, 오픈소스 라이선스 및 규제 요건은 지속적으로 변경될 수 있습니다. 최신 정보는 각 프로젝트의 공식 문서를 참조해 주세요.
면책 고지 (Disclaimer)
이 글은 밸런스히어로 엔지니어링 팀의 기술적 경험을 공유하기 위한 것입니다. 특정 제품이나 서비스에 대한 공식적인 평가나 권고사항이 아니며, 법률·보안·라이선스에 관한 전문적 자문을 대체하지 않습니다. 최종 기술 결정 전에는 반드시 관련 전문가와 상의하시기 바랍니다.
이 블로그는 밸런스히어로 엔지니어링 팀의 기술적 경험을 공유하기 위해 작성되었습니다. 더 자세한 내용이나 질문이 있으시면 GitHub 또는 회사 기술 블로그 댓글을 통해 문의해 주세요.