Technology

리프아이티의 철학으로
만든 기술, dePaper®

  • 외부 서비스와 라이브러리 의존도를 줄이고 완전한 자체 플랫폼에서 기동되는 기술로,
  • 필요한 구성요소를 직접 관리 가능한 구조로 설계하여 장기적인 안정성을 확보하며,
  • 국가 상위 기관의 보안 권고사항을 성실히 반영한 고차원 e-Book 기술입니다.
  • 신뢰성 · 보안성 · 유지보수성을 중심으로 설계한 리프아이티의 철학이 담긴 dePaper를 소개합니다.
  • dePaper® 상표 제 40-1709310호

Client (Browser)

사용자 단말 · 웹 브라우저

Web / Application

TLS 적용 · 로직 처리

Storage / Database

콘텐츠 파일 · 메타데이터 보관

원칙을 세우고 지켜서
설계한 dePaper®

e-Book 서비스의 수명 전체를 바라보고, 신뢰성 · 보안성 · 유지보수성을 중심으로 설계한 리프아이티의 기술 기준을 소개합니다.

신뢰성을 우선한 구조

장기간 운영을 전제로, 장애와 변경에
강한
단순한 계층 구조와
명확한 책임 분리를 지향합니다.

보안 권고사항의 상시 반영

국가 상위기관 및 고객사 보안
가이드라인을
기준으로, TLS와
접근 통제를 설계 단계부터 반영합니다.

유지보수 가능한 코드베이스

외부 의존성을 최소화한 자체 코드와
일관된 규칙을 유지하여, 기능 개선을
안정적으로 이어갈 수 있습니다.

환경에 맞춘 유연한 배포

내부망, 온프레미스, 클라우드 등 다양한
인프라 환경에서 동일한 구조로
배포 · 운영할 수 있도록 설계합니다.

dePaper® 보안 · 규정 준수 기준

국가 상위 기관의 보안 권고를 참고하여
설정과 운영 기준을 수립하고 반영합니다.

웹 애플리케이션 계층의 보호

HTTP 요청 처리, 세션 관리, 콘텐츠 URL 설계 등 사용자가
직접 마주하는 영역을 중심으로 기본적인 보안 구조를 설계합니다.

데이터 계층 분리와 접근 관리

업무 목적에 따라 데이터베이스 스키마를 분리하고,
읽기 · 쓰기 권한을 기능 단위로 나누어 최소 권한 원칙을 적용합니다.

통신 구간 암호화와 TLS 설정

TLS 적용과 인증서 관리, 강한 암호화 스위트 우선 사용 등을 통해
네트워크 상에서 데이터를 안전하게 주고받을 수 있도록 준비합니다.

웹 비즈니스 로직 모듈화

핵심 업무 흐름을 독립된 모듈로 분리하여 유지보수성을 높이고,
각 기능 단위의 테스트와 확장이 용이한 구조로 설계합니다.

시큐어 코딩 적용

개발 단계부터 잠재적인 보안 약점을 제거하는 행정안전부
시큐어 코딩 가이드를 준수하여, 해킹 및 외부 공격을 원천적으로 차단합니다.

로그 · 감사 이력 관리

관리자 활동과 주요 오류를 남길 수 있는 로그 구조를 마련해
이상 징후 분석과 사후 추적이 가능하도록 합니다.

세션 및 인증 토큰 관리

세션 타임아웃 설정, 토큰 갱신 정책, 동시 접속 제어 등을 적용하여
사용자 인증 상태를 안전하게 유지합니다.

표준 연계 인터페이스

SSO(통합로그인), 그룹웨어, 검색엔진 등 기존 시스템과
유연하게 연동할 수 있도록 표준화된 API 및 인터페이스를 지원합니다.

dePaper®, 소프트웨어
품질 특성으로 보는 구조

국제 표준의 소프트웨어 품질 특성을 기준으로, 리프아이티 e-Book 솔루션의 기술 구조를 설명합니다.

Reliability · 신뢰성

e-Book 열람 환경에서 장애 없이 동작하도록 구성하고,
공공 · 교육 환경에서 검증된 설정을 기준으로 운영합니다.

Maintainability · 유지보수성

코드와 폴더 구조를 명확히 분리하여, 신규 기능 추가와
마이너 업그레이드를 부담 없이 진행할 수 있습니다.

Compatibility · 호환성

주요 브라우저와 기관별 PC 보안 설정,
다양한 OS 환경을 고려해 동작을 테스트합니다.

Security · 보안성

관리자 페이지 접근 제어, DB 권한 분리, TLS(SSL) 적용
등 국가 상위 기관의 보안 권고를 기준으로 설정합니다.

Performance · 성능

e-Book 뷰어 로딩, 썸네일 · 목차 메타 처리 등
실제 열람 속도를 기준으로 최적화합니다.

Availability · 가용성

물리 · 클라우드 서버, ASP 환경 모두에서 서비스
중단 없이 안정적으로 열람할 수 있도록 구성합니다.

Usability · 사용성

관리자 화면과 사용자 뷰어 모두 데스크톱, 태블릿,
모바일 환경에서 최적화된 레이아웃으로 표시됩니다.

Fault Tolerance · 내결함성

네트워크 순간 단절 등 예상 가능한 오류 상황에서도
서비스가 중단되지 않도록 방어 로직을 구성합니다.

Operation Convenience · 운영 편의성

UI 흐름을 단순화하고, 제작자 권한 변경 등 운영자가
자주 사용하는 기능을 중심으로 구성합니다.

dePaper® 아키텍처

브라우저부터 스토리지 · 데이터베이스까지,
e-Book 서비스 운영에 필요한 핵심 계층 아키텍처입니다.

Client (Browser)

사용자 단말에서 동작하는
웹 브라우저 계층입니다.

Network / Security

방화벽, WAF, Reverse Proxy 등 기관 환경에 맞는 진입 보안 구간과 연계됩니다.

Web / Application

인증, 권한, 비즈니스 로직을 처리하는 핵심 웹 · 애플리케이션 서버 계층입니다.

Publishing Engine

e-Book 변환, 메타데이터 처리, 썸네일 생성 등 콘텐츠 제작 엔진이 위치합니다.

Storage

PDF, 이미지, 썸네일 등

e-Book 콘텐츠 파일을
저장하는 스토리지 계층입니다.

Database

메타데이터, 권한 정보, 로그를
InnoDB 기반 관계형
데이터베이스로 관리합니다.

온프레미스 · 내부망 설치

기관 데이터센터 또는 내부망 서버에 설치하여,
내부 정책에 맞춘 네트워크 구성과 보안 정책을 유지한 채 운영합니다.

ASP 운영

리프아이티 인프라에 동일한 아키텍처를 구축하여,
기관은 콘텐츠 제작과 운영에 집중하고 인프라 관리는 리프아이티가 담당합니다.

버전 업그레이드 · 유지보수

데이터 구조와 URL 체계를 유지하면서 기능 개선과
보안 패치를 단계적으로 반영할 수 있도록 설계되어 있습니다.

Open API를 통한 콘텐츠 목록 연동

고객사 홈페이지 · 포털 시스템에서
e-Book 콘텐츠 목록을 직접 출력할 수 있도록,
선택적인 Open API를 제공합니다.

</>

dePaper® Open API 개요

API는 서로 다른 시스템이 약속된 규칙으로 데이터를 주고받는 인터페이스입니다. 리프아이티는 공공 · 교육 환경의 보안 정책을 고려하여, 현장에서 자주 활용되는 기능을 중심으로 Open API 형태의 연동 방식을 제공합니다.

요청 주소

GET https://{YOUR_DOMAIN}/Web/Booklist?key={YOUR_KEY}&{PARAM}

주요 파라미터

  • pagenum

    페이지 번호

    기본값 1

  • outcnt

    출력될 콘텐츠 개수

    기본값 10

  • orderby

    정렬 기준

    reg_edit, hit

  • userid

    제작자 ID

    특정 ID 콘텐츠만 호출

  • title

    제목 검색

    Like 검색 지원

* 콘텐츠 목록 외 추가 API는 보안 정책과 시스템 구조에 따라 프로젝트별로 별도 협의 후 제공됩니다.

Request
GET https://YOUR_DOMAIN/Web/Booklist?key=YOUR_KEY&userid=MAKER_ID
JavaScript Example
// 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,

  });
});