AI Neo Lab
스킬

Univer로 AI 에이전트가 쓸 오피스 환경 직접 만드는 법

AI 에이전트에 엑셀·워드·PPT·PDF 편집 기능을 붙이려면 직접 렌더링 엔진과 수식 엔진을 짜야 해서 진입 장벽이 높습니다. Univer는 캔버스 기반 렌더링과 플러그인 구조, 단일 파사드 API로 브라우저와 Node.js 어디서든 돌아가는 오피스 SDK를 한 번에 제공합니다. 이 자료는 Univer 핵심 개념부터 설치·초기화·문서 로드·플러그인 확장까지 실무 적용 단계를 정리합니다.

LLM 에이전트가 스프레드시트에서 피벗 테이블을 돌리고, 문서에서 표를 편집하고, 프레젠테이션 슬라이드를 생성하게 하려면 오피스 런타임이 필요합니다. Univer는 18.3k 스타를 받은 아파치 2.0 라이선스 SDK로, 시트·독·슬라이드·보드·릴레이셔널 테이블·PDF를 단일 런타임에서 다루게 해줍니다.

Univer란 무엇인가요

Univer는 AI 에이전트가 직접 쓸 수 있는 오피스 환경을 한 런타임에 모아 둔 오픈소스 SDK예요. 스프레드시트(Sheet)·문서(Doc)·프레젠테이션(Slide)·관계형 테이블(Base)·화이트보드(Board)·PDF까지 6대 모듈을 하나의 패키지로 제공하니, 에이전트가 표 계산·문서 작성·슬라이드 생성·데이터 조회·자유 캔버스 드로잉·PDF 리딩을 따로 라이브러리 붙이지 않고도 바로 수행할 수 있어요.

모듈주요 용도
Sheet스프레드시트 그리드·수식·차트·피벗
Doc리치 텍스트·트랙 체인지·목차·내보내기
Slide슬라이드 마스터·애니메이션·발표자 노트
Base관계형 테이블·SQL 라이크 쿼리·뷰
Board무한 캔버스·스티키·커넥터·마인드맵
PDF렌더링·텍스트 추출·어노테이션(준비 중)
터미널에서 실행
npm i @univerjs/core @univerjs/sheet @univerjs/doc @univerjs/slide @univerjs/base @univerjs/board

프로젝트 현황 한눈에 보기

  • 저장소: dream-num/univer
  • 스타 18,368개 · 포크 1,561개 · 주 언어 TypeScript
  • 라이선스: Apache-2.0
  • 처음 만들어진 시점: 4년 전(2022년 9월)
  • 마지막 업데이트: 이번 달(2026년 9월)

왜 Univer를 쓰나요

Univer를 선택하는 가장 큰 이유는 브라우저와 Node.js에서 똑같은 API(Facade API)로 돌아간다는 점입니다. 프론트엔드에서 사용자에게 시트를 보여주면서, 백엔드에서는 헤드리스(Headless) 모드로 같은 문서를 열고 수식을 계산하거나 PDF로 내보내는 작업을 별도 코드 없이 수행할 수 있어요. AI 에이전트가 툴콜(Tool-call)로 "시트 열고 → 데이터 쓰고 → 수식 돌리고 → 결과 내보내기"를 한 번에 처리하려면 런타임 차이가 없어야 하는데, Univer가 이 지점을 네이티브로 해결해 줍니다.

항목내용
런타임브라우저 + Node.js 단일 Facade API
확장플러그인 아키텍처(코어/시트/도큐먼트/슬라이드/PDF)

플러그인 기반 아키텍처 덕분에 에이전트 전용 기능을 끼워 넣기 좋습니다. 코어(@univerjs/core) 위에 시트·도큐먼트·슬라이드·PDF 플러그인을 조립하고, 필요하면 커스텀 플러그인으로 "에이전트 전용 툴바", "자동 데이터 검증", "외부 API 연동 커스텀 함수" 등을 주입할 수 있어요. 플러그인은 생명주기(onInit, onReady, onDispose)와 의존성 주입(Dependency Injection)을 표준으로 따르므로, 여러 에이전트 기능이 서로 충돌하지 않게 격리해 로드·언로드할 수 있습니다.

  1. 에이전트 툴콜 연동 흐름 예시

    1. 에이전트 → Univer Facade API 호출 (브라우저/Node.js 공통) 2. 헤드리스 모드면 Canvas 렌더링 생략, 수식 엔진만 가동 3. 플러그인 훅(FormulaCalculation, DataValidation 등)에서 커스텀 로직 수행 4. 결과(JSON/CSV/PDF/XLSX)를 에이전트에 반환

  2. 커스텀 함수 등록

    1. 플러그인에서 Injector.get(FormulaEngineService) 획득 2. registerFunction('AGENT_FETCH', async (url) => await fetch(url).then(r=>r.json())) 3. 시트에서 =AGENT_FETCH("https://api.example.com/data") 바로 사용

설치·초기화·첫 문서 로드 5단계

Univer를 프로젝트에 넣으려면 npm으로 핵심 패키지를 한 번에 설치해요. 스프레드시트·문서·슬라이드·기본 UI·한국어 로케일까지 모두 포함하면 아래 명령어 하나로 끝납니다.

터미널에서 실행
npm i @univerjs/core @univerjs/sheets @univerjs/sheets-ui @univerjs/docs @univerjs/docs-ui @univerjs/slides @univerjs/slides-ui @univerjs/ui @univerjs/locale-ko-KR

설치가 끝나면 Univer 인스턴스를 생성하고, 워크북·시트·문서·슬라이드를 마운트할 컨테이너를 HTML에 준비해요. 각 컨테이너는 id를 줘서 나중에 마운트 포인트로 씁니다.

index.html — 컨테이너 준비
<div id="sheet-root" style="width:100%;height:400px;"></div>
<div id="doc-root" style="width:100%;height:400px;"></div>
<div id="slide-root" style="width:100%;height:400px;"></div>

1️⃣ Univer 인스턴스 만들기

new Univer({ locale: localeKoKR })로 런타임을 띄우고, 플러그인은 withSheets, withDocs, withSlides 순으로 체인하면 됩니다. 테마·언어·기본 폰트 등은 옵션 객체로 한 번에 넘겨요.

main.ts — 인스턴스 생성
import { Univer } from '@univerjs/core';
import { UniverSheetsPlugin } from '@univerjs/sheets';
import { UniverSheetsUIPlugin } from '@univerjs/sheets-ui';
import { UniverDocsPlugin } from '@univerjs/docs';
import { UniverDocsUIPlugin } from '@univerjs/docs-ui';
import { UniverSlidesPlugin } from '@univerjs/slides';
import { UniverSlidesUIPlugin } from '@univerjs/slides-ui';
import { UniverUIPlugin } from '@univerjs/ui';
import { localeKoKR } from '@univerjs/locale-ko-KR';

const univer = new Univer({
  locale: localeKoKR,
  theme: 'default',
});

univer.with(UniverSheetsPlugin)
      .with(UniverSheetsUIPlugin)
      .with(UniverDocsPlugin)
      .with(UniverDocsUIPlugin)
      .with(UniverSlidesPlugin)
      .with(UniverSlidesUIPlugin)
      .with(UniverUIPlugin);

2️⃣ 워크북·시트 마운트하기

univer.createWorkbook({ id: 'workbook-1', name: '첫 시트', sheets: [{ name: 'Sheet1' }] })로 워크북을 만들고, univer.getUnit('workbook-1').mount('sheet-root')로 컨테이너에 붙여요. 시트 데이터는 배열로 바로 넣거나 loadWorkbook으로 JSON을 불러올 수 있습니다.

main.ts — 시트 마운트
const workbook = univer.createWorkbook({
  id: 'workbook-1',
  name: '첫 시트',
  sheets: [{ name: 'Sheet1', rowCount: 20, columnCount: 10 }],
});

workbook.mount('sheet-root');

3️⃣ 문서(Doc) 마운트하기

문서는 createDoc으로 본문·스타일·초기 커서 위치까지 정의한 뒤 mount('doc-root')로 올립니다. 마크다운이나 HTML을 바로 넣으려면 별도 파서 플러그인을 쓰면 됩니다.

main.ts — 문서 마운트
const doc = univer.createDoc({
  id: 'doc-1',
  name: '첫 문서',
  body: { dataStream: 'Univer로 작성한 첫 문서입니다.' },
});

doc.mount('doc-root');

4️⃣ 슬라이드 마운트하기

슬라이드는 createSlide로 페이지 배열을 넘기고 mount('slide-root')로 붙입니다. 각 페이지는 elements 배열로 도형·텍스트·이미지를 배치해요.

main.ts — 슬라이드 마운트
const slide = univer.createSlide({
  id: 'slide-1',
  name: '첫 프레젠테이션',
  pages: [
    { id: 'page-1', elements: [{ type: 'text', text: '첫 슬라이드' }] },
  ],
});

slide.mount('slide-root');

5️⃣ 데이터 로드·이벤트 리스닝

외부 JSON·CSV·XLSX를 불러올 땐 univer.loadWorkbook(data) 또는 univer.loadDoc(data)를 쓰고, 사용자 편집·선택 변경·수식 계산 완료 등은 workbook.on(EventType.XXX, handler)로 구독해요. 아래는 시트 값 변경 시 콘솔에 찍는 예시입니다.

main.ts — 이벤트 구독
import { EventType } from '@univerjs/sheets';

workbook.on(EventType.CELL_VALUE_CHANGED, (evt) => {
  console.log('셀 변경:', evt.unitId, evt.subUnitId, evt.range, evt.newValue);
});

한눈에 보는 핵심 API 치트시트

AI 에이전트가 직접 활용할 수 있게 설계된 Univer SDK의 핵심 API를 한눈에 정리했어요. Facade API인 Univer.getInstance 하나만 호출하면 브라우저와 Node.js 환경 모두에서 워크북, 시트, 문서, 슬라이드 모델에 접근하고, 수식 엔진을 실행하며, 셀·범위·스타일을 조작하고, xlsx·csv·pdf·markdown 등 다양한 포맷을 임포트·익스포트할 수 있습니다.

API 영역주요 기능
Facade APIUniver.getInstance – 브라우저·Node.js 공통 진입점
워크북·시트·문서·슬라이드모델 객체를 반환해 데이터 조회·수정 가능
수식 엔진스프레드시트 수식 파싱·계산 지원
셀·범위·스타일셀 값, 범위 선택, 스타일 적용 메서드 제공
임포트·익스포트xlsx·csv·pdf·markdown 포맷 입출력 지원
Facade API
Univer.getInstance

위 표와 코드를 참고해서 필요할 때마다 해당 메서드를 찾아 쓰면, 복잡한 문서·스프레드시트 작업도 몇 줄의 코드로 해결할 수 있습니다. 자세한 사용법은 공식 문서와 API 레퍼런스를 확인해 보세요.

주의할 점과 운영 팁

인스턴스를 만들었으면 dispose 패턴으로 정리하는 습관을 들이세요. univer.dispose() 또는 workbook.dispose()를 호출하면 캔버스 컨텍스트·이벤트 리스너·웹워커·공유 메모리 버퍼가 한꺼번에 해제돼 메모리 누수를 막을 수 있어요. SPA에서 라우트 전환 시 onBeforeUnmount 훅이나 useEffect 클린업 함수에 넣어 두면 안전합니다.

next.config.js 예시
// canvas 폴리필
externals: ['canvas'],
webpack: (config, { isServer }) => {
  if (isServer) config.externals.push('canvas');
  return config;
}

라이선스·업그레이드 체크리스트

  • 라이선스: Apache-2.0 — 상용 임베드·수정·재배포 모두 자유롭지만, NOTICE 파일에 원저작자 표기는 유지해야 해요.
  • 메이저 버전 업그레이드 시 마이그레이션 가이드(GitHub Releases → MIGRATION.md 또는 docs.univer.ai/guide/migration)부터 읽으세요. Facade API 시그니처 변경·플러그인 네임스페이스 이동·기본 설정값 변경 등이 버전별로 정리돼 있습니다.
  • 패치·마이너 버전은 npm i @univerjs/core@latest 후 타입스크립트 컴파일만 돌려도 breaking change가 바로 드러나요. CI에 tsc --noEmit 단계를 넣어두면 안전합니다.
  • 플러그인 직접 작성했다면 PluginCreator 타입 변경 여부를 꼭 확인하세요. 0.x → 1.x 때는 onStarting·onReady 라이프사이클 훅 이름이 바뀌어 전체 리팩터링이 필요했습니다.
  1. 릴리스 노트·마이그레이션 문서 열기

    GitHub Releases 페이지에서 해당 버전 태그 클릭 → MIGRATION.md 링크 또는 문서 사이드바 'Migration Guide' 확인

  2. 타입 체크로 breaking change 잡기

    npm i @univerjs/core@<target> @univerjs/sheets@<target> … 후 npx tsc --noEmit 실행

  3. 자동 테스트·시각 회귀 테스트 돌리기

    시트 렌더링 스냅샷(testing-library + pixelmatch) 비교로 레이아웃 깨짐 사전 차단

  4. 카나리 배포로 실사용자 트래픽 소량 검증

    NEXT_PUBLIC_UNIVER_VERSION=next 같은 플래그로 1% 유저만 새 버전 로드

정리: 다음 단계로 나아가기

dream-num/univer 저장소는 AI 에이전트를 위한 오피스 환경을 한 런타임에 제공하는 오픈소스 SDK예요. 스프레드시트·문서·프레젠테이션·베이스·보드·PDF(곧 제공) 등을 지원하고, 고성능과 플러그인 아키텍처, 캔버스 기반 렌더링, 수식 엔진, 브라우저와 Node.js 모두에서 동작하는 단일 Facade API를 제공해요. 현재 스타는 18,368개, 포크는 1,561개이며, 주 언어는 TypeScript이고 Apache-2.0 라이선스를 따릅니다. 프로젝트는 4년 전(2022년 9월) 시작돼 이번 달(2026년 9월)까지 활발히 업데이트되고 있습니다.


이런 글도 있어요