신뢰성을 우선한 구조
장기간 운영을 전제로, 장애와 변경에
강한
단순한 계층 구조와
명확한 책임 분리를 지향합니다.
Client (Browser)
사용자 단말 · 웹 브라우저
Web / Application
TLS 적용 · 로직 처리
Storage / Database
콘텐츠 파일 · 메타데이터 보관
e-Book 서비스의 수명 전체를 바라보고, 신뢰성 · 보안성 · 유지보수성을 중심으로 설계한 리프아이티의 기술 기준을 소개합니다.
장기간 운영을 전제로, 장애와 변경에
강한
단순한 계층 구조와
명확한 책임 분리를 지향합니다.
국가 상위기관 및 고객사 보안
가이드라인을
기준으로, TLS와
접근 통제를 설계 단계부터 반영합니다.
외부 의존성을 최소화한 자체 코드와
일관된 규칙을 유지하여, 기능 개선을
안정적으로 이어갈 수 있습니다.
내부망, 온프레미스, 클라우드 등 다양한
인프라 환경에서 동일한 구조로
배포 · 운영할 수 있도록 설계합니다.
국가 상위 기관의 보안 권고를 참고하여
설정과 운영 기준을 수립하고 반영합니다.
HTTP 요청 처리, 세션 관리, 콘텐츠 URL 설계 등 사용자가
직접 마주하는 영역을 중심으로 기본적인 보안 구조를 설계합니다.
업무 목적에 따라 데이터베이스 스키마를 분리하고,
읽기 · 쓰기 권한을 기능 단위로 나누어 최소 권한 원칙을 적용합니다.
TLS 적용과 인증서 관리, 강한 암호화 스위트 우선 사용 등을 통해
네트워크 상에서 데이터를 안전하게 주고받을 수 있도록 준비합니다.
핵심 업무 흐름을 독립된 모듈로 분리하여 유지보수성을 높이고,
각 기능 단위의 테스트와 확장이 용이한 구조로 설계합니다.
개발 단계부터 잠재적인 보안 약점을 제거하는 행정안전부
시큐어 코딩 가이드를 준수하여, 해킹 및 외부 공격을 원천적으로 차단합니다.
관리자 활동과 주요 오류를 남길 수 있는 로그 구조를 마련해
이상 징후 분석과 사후 추적이 가능하도록 합니다.
세션 타임아웃 설정, 토큰 갱신 정책, 동시 접속 제어 등을 적용하여
사용자 인증 상태를 안전하게 유지합니다.
SSO(통합로그인), 그룹웨어, 검색엔진 등 기존 시스템과
유연하게 연동할 수 있도록 표준화된 API 및 인터페이스를 지원합니다.
국제 표준의 소프트웨어 품질 특성을 기준으로, 리프아이티 e-Book 솔루션의 기술 구조를 설명합니다.
e-Book 열람 환경에서 장애 없이 동작하도록 구성하고,
공공 · 교육 환경에서 검증된 설정을 기준으로 운영합니다.
코드와 폴더 구조를 명확히 분리하여, 신규 기능 추가와
마이너 업그레이드를 부담 없이 진행할 수 있습니다.
주요 브라우저와 기관별 PC 보안 설정,
다양한 OS 환경을 고려해 동작을 테스트합니다.
관리자 페이지 접근 제어, DB 권한 분리, TLS(SSL) 적용
등 국가 상위 기관의 보안 권고를 기준으로 설정합니다.
e-Book 뷰어 로딩, 썸네일 · 목차 메타 처리 등
실제 열람 속도를 기준으로 최적화합니다.
물리 · 클라우드 서버, ASP 환경 모두에서 서비스
중단 없이 안정적으로 열람할 수 있도록 구성합니다.
관리자 화면과 사용자 뷰어 모두 데스크톱, 태블릿,
모바일 환경에서 최적화된 레이아웃으로 표시됩니다.
네트워크 순간 단절 등 예상 가능한 오류 상황에서도
서비스가 중단되지 않도록 방어 로직을 구성합니다.
UI 흐름을 단순화하고, 제작자 권한 변경 등 운영자가
자주 사용하는 기능을 중심으로 구성합니다.
브라우저부터 스토리지 · 데이터베이스까지,
e-Book 서비스 운영에 필요한 핵심 계층 아키텍처입니다.
Client (Browser)
사용자 단말에서 동작하는
웹 브라우저 계층입니다.
Network / Security
방화벽, WAF, Reverse Proxy 등 기관 환경에 맞는 진입 보안 구간과 연계됩니다.
Web / Application
인증, 권한, 비즈니스 로직을 처리하는 핵심 웹 · 애플리케이션 서버 계층입니다.
Publishing Engine
e-Book 변환, 메타데이터 처리, 썸네일 생성 등 콘텐츠 제작 엔진이 위치합니다.
Storage
PDF, 이미지, 썸네일 등
e-Book 콘텐츠 파일을
저장하는 스토리지 계층입니다.
Database
메타데이터, 권한 정보, 로그를
InnoDB 기반 관계형
데이터베이스로 관리합니다.
기관 데이터센터 또는 내부망 서버에 설치하여,
내부 정책에 맞춘 네트워크 구성과 보안 정책을 유지한 채 운영합니다.
리프아이티 인프라에 동일한 아키텍처를 구축하여,
기관은 콘텐츠 제작과 운영에 집중하고 인프라 관리는 리프아이티가 담당합니다.
데이터 구조와 URL 체계를 유지하면서 기능 개선과
보안 패치를 단계적으로 반영할 수 있도록 설계되어 있습니다.
고객사 홈페이지 · 포털 시스템에서
e-Book 콘텐츠 목록을 직접 출력할 수 있도록,
선택적인 Open API를 제공합니다.
dePaper® Open API 개요
API는 서로 다른 시스템이 약속된 규칙으로 데이터를 주고받는 인터페이스입니다. 리프아이티는 공공 · 교육 환경의 보안 정책을 고려하여, 현장에서 자주 활용되는 기능을 중심으로 Open API 형태의 연동 방식을 제공합니다.
https://{YOUR_DOMAIN}/Web/Booklist?key={YOUR_KEY}&{PARAM} pagenumoutcntorderbyuseridtitle* 콘텐츠 목록 외 추가 API는 보안 정책과 시스템 구조에 따라 프로젝트별로 별도 협의 후 제공됩니다.
GET https://YOUR_DOMAIN/Web/Booklist?key=YOUR_KEY&userid=MAKER_ID // 1. API 기본 설정 -------------------------------------------------
const API_DOMAIN = 'YOUR_DOMAIN';
const API_KEY = 'YOUR_KEY';
const DEFAULT_PARAMS = {
pagenum: 5,
outcnt: 16,
orderby: 'reg_edit', // reg_edit / hit
};
// 2. 쿼리스트링 유틸리티 ------------------------------------------
function toQueryString(params) {
return Object.entries(params)
.map(([key, value]) =>
`${encodeURIComponent(key)}=${encodeURIComponent(value)}`
)
.join('&');
}
function buildBookListUrl(extraParams = {}) {
const query = toQueryString({
...DEFAULT_PARAMS,
...extraParams,
});
return `https://${API_DOMAIN}/Web/Booklist?key=${API_KEY}&${query}`;
}
// 3. XML 응답을 자바스크립트 객체로 변환 ----------------------------
function parseBooks(xmlDocument) {
const bookNodes = xmlDocument.querySelectorAll('book');
return Array.from(bookNodes).map((book) => {
const titleNode = book.querySelector('title');
const thumbNode = book.querySelector('thumb_path');
const rawTitle = titleNode ? titleNode.textContent : '';
const rawThumb = thumbNode ? thumbNode.textContent : '';
const code = book.getAttribute('code') || '';
const thumb =
rawThumb.trim().replace(/^\/\/, 'https://');
return {
code,
title: rawTitle.trim(),
thumb,
};
});
}
// 4. DOM 렌더링 (예시)
function renderBooks(books) {
const container =
document.getElementById('booklist');
if (!container) {
console.warn('[Booklist] 렌더링 대상 엘리먼트를 찾을 수 없습니다.');
console.table(books);
return;
}
container.innerHTML = '';
if (!books.length) {
container.textContent =
'조회된 e-Book 콘텐츠가 없습니다.';
return;
}
const list =
document.createElement('ul');
books.forEach((book) => {
const item =
document.createElement('li');
item.textContent =
`[${book.code}] ${book.title}`;
list.appendChild(item);
});
container.appendChild(list);
}
// 5. 실제 API 호출 함수 (async/await)
async function fetchBookList(extraParams = {}) {
const url = buildBookListUrl(extraParams);
try {
console.info('[Booklist] Request URL:', url);
const response =
await fetch(url);
if (!response.ok) {
throw new Error(
`HTTP ${response.status} ${response.statusText}`
);
}
const xmlText =
await response.text();
const xmlDoc =
new window.DOMParser()
.parseFromString(xmlText, 'text/xml');
const books = parseBooks(xmlDoc);
console.table(books);
renderBooks(books);
return books;
} catch (error) {
console.error('[Booklist] API Error:', error);
return [];
}
}
// 6. 페이지 로드 시 자동 실행 예시 -----------------------------------
document.addEventListener('DOMContentLoaded', () => {
fetchBookList({
pagenum: 1,
outcnt: 6,
});
});