본문 바로가기

프로그래밍/spreadjs

SpreadJS Designer Component 커스터마이징: 리본·컨텍스트 메뉴 확장과 배포 템플릿 가이드

반응형

왜 Designer 커스터마이징이 먼저일까요

 

스프레드시트 기능은 같아 보여도, 업무 화면에서 쓰는 버튼과 메뉴는 팀마다 다릅니다. SpreadJS Designer Component를 그대로 쓰면 학습은 빠르지만, 리본과 컨텍스트 메뉴가 현장 용어·흐름과 어긋나 체류 시간과 효율이 떨어질 수 있습니다.

 

이 글은 리본 탭/그룹 추가와 우클릭 메뉴 확장, 그리고 배포용 템플릿 구성까지 초보자 관점에서 차근히 설명합니다. 기본 버튼을 숨기고 필요한 기능만 남기는 가벼운 커스터마이징부터 시작해 점진적으로 확장하는 방식을 다룹니다.

 

처음 적용한다면 다음 상황에서 도움이 됩니다.
- 불필요한 서식·차트 옵션이 많아 사용자가 길을 잃을 때
- 특정 매크로나 회사 규격을 버튼 한 번으로 실행해야 할 때
- 동일한 UI 구성을 여러 프로젝트에 재사용해 배포해야 할 때

 

> 팁: 기능을 많이 넣는 것이 항상 이득은 아닙니다. 메뉴가 복잡해지면 유지보수 비용이 커지므로, 핵심 작업 흐름 3~5가지만 우선 노출하는 구성이 안전합니다.
추가 정보나 최신 사양은 SpreadJS 공식 제품 페이지에서 확인하는 편이 좋습니다.

 

리본·컨텍스트 메뉴를 왜, 어디까지 바꾸나

 

업무별로 자주 쓰는 동작이 다르기 때문에, 리본은 “정해진 흐름을 안내하는 상단 메뉴”, 컨텍스트 메뉴는 “현재 셀 상황에서 바로 쓰는 우클릭 명령”으로 역할이 갈립니다. 초보 사용자는 리본에서 단계별 버튼을 찾고, 숙련 사용자는 우클릭에서 즉시 실행을 기대합니다.

 

예를 들어 견적서 화면이라면 리본에 ‘규격 서식 적용’, ‘품목 불러오기’를 한 그룹으로 묶고, 우클릭에는 ‘행 복제’, ‘단가 일괄 반영’을 배치합니다. 이렇게 하면 사용자는 마우스 이동을 줄이고, 화면 전환 없이 필요한 작업을 끝낼 수 있습니다.

 

적용 범위를 정할 때는 다음 기준이 도움이 됩니다.
- 리본: 전사 규칙·표준 서식·승인 흐름처럼 단계가 있는 작업
- 컨텍스트: 선택 영역에 즉시 적용되는 편집·서식·스크립트 실행
- 공통: 너무 많은 항목을 넣지 말고 상위 5~7개 동작만 노출

 

> 안티패턴: 기본 메뉴를 모두 숨기고 사내 명령만 남기면 온보딩이 어려워집니다. 기본 편집·되돌리기 같은 공용 기능은 유지하고, 도메인 전용 기능만 커스텀으로 추가하세요.

 

빠른 적용: 리본·우클릭 확장과 템플릿 배포

 

작게 바꾸고 바로 확인하세요. 메뉴를 늘린 뒤 마지막에 템플릿으로 묶어 배포하면 안전합니다.

 

- 목표 고르기: 핵심 기능 5~7개만 선정(리본=순차 작업, 우클릭=즉시 실행)
- 기본 정리: 안 쓰는 탭·버튼 숨김
- 명령 추가: 리본 그룹·버튼 만들고 클릭 동작(핸들러=실행 함수) 연결
- 우클릭 확장: 선택한 영역 기준으로 필요한 명령만 노출
- 템플릿화: 초기 리본·메뉴·스타일·스크립트를 JSON/모듈로 분리
- 검증: 키보드 포커스, 다국어, 권한별 노출 점검
- 배포: 공통 템플릿 로드 후 프로젝트 설정으로 덮어쓰기

 

아래 코드는 구조를 보여주는 예시입니다. 리본에 “규격 서식”, 우클릭에 “행 복제”를 추가합니다.

 

// 리본 커스터마이징
designer.ribbon.addTab({
  id: 'companyTab',
  label: '회사',
  groups: [{
    id: 'formatGroup',
    label: '규격',
    items: [{
      type: 'button',
      id: 'applyStdFormat',
      label: '규격 서식',
      onClick: () => applyStandardFormat(spread)
    }]
  }]
});

// 우클릭 메뉴 확장
designer.contextMenu.addItem({
  id: 'dupRow',
  text: '행 복제',
  group: 'edit',
  command: () => duplicateSelectedRow(spread)
});

// 배포 템플릿(초기 주입)
const designerTemplate = {
  hiddenTabs: ['Data','Formulas'],
  customTabs: ['companyTab'],
  contextItems: ['dupRow']
};
initDesigner(spread, designerTemplate);

 

UI 정의를 코드와 분리하면 템플릿만 교체해 화면을 재사용할 수 있습니다. 공통 모듈에 두고 프로젝트별로 버튼만 추가하면 유지 비용이 줄어듭니다.

 

> 체크포인트
> - 명령 ID는 중복 없이 짓고 단축키 충돌을 확인하세요.
> - 선택이 없을 때는 명령을 비활성화하세요.
> - 조직 배포 시 템플릿 버전과 변경 로그를 함께 배포하세요.

 

흔한 실수와 선택 기준 한눈에 정리

 

리본·우클릭을 커스터마이징할 때 가장 흔한 실수는 “많이 넣기”입니다. 사용 빈도가 낮은 항목을 채워 넣으면 찾기 시간이 늘고 교육 비용이 커집니다.

 

선택 기준은 단순하게 두 가지로 자르세요. 리본에는 단계형 업무(전사 규칙·승인 흐름), 우클릭에는 현재 선택에 즉시 적용되는 명령만 남깁니다.

 

중복 명령은 한쪽만 유지합니다.

 

- 과밀 구성: 탭/그룹/버튼이 7개를 넘기면 숨기기 또는 하위 메뉴로 이관
- 중복 배치: 같은 명령을 리본과 우클릭에 동시에 두지 않기(유지보수 비용 증가)
- 의미 불명 라벨: 내부 용어 대신 사용자 문장형 라벨 사용(예: “규격 서식 적용”)

 

> 안티패턴: 기본 메뉴를 전면 비활성화하고 사내 스크립트만 남기는 구성은 장애 시 복구 경로가 사라집니다. 최소한의 기본 편집·실행 명령은 유지하세요.

 

권한·상황별 노출을 나누지 않는 것도 잦은 실수입니다. 역할별로 가시성을 분리하면 클릭 오류와 실수 편집을 줄일 수 있고, 네트워크 비용 관점에서도 초기 로드가 가벼워집니다.

 

- 역할 기반: 관리자/작성자/검토자별 표시 토글
- 상황 기반: 선택 영역(행·열·표·피벗) 감지 후 관련 명령만 표시
- 안전 장치: 되돌리기 가능 작업만 우클릭에 배치하고, 파괴적 작업은 확인 모달 추가

 

지금 바로 적용할 실행 순서

 

리본·우클릭 확장과 템플릿화는 작게 시작해 반복 개선하면 됩니다. 아래 체크리스트대로 한 번에 끝까지 밀지 말고 단계별로 검증하세요.

 

- 최상위 5~7개 동작 선정(리본=절차형, 우클릭=즉시형)
- 기본 탭/버튼 숨기기로 화면 단순화
- 커스텀 명령 추가 및 클릭 핸들러 연결
- 선택 영역 기준 우클릭 노출 조건 설정
- 리본·우클릭·스타일을 템플릿(JSON/모듈)으로 분리
- 역할별 노출, 다국어 라벨, 단축키 점검
- 샌드박드(테스트 앱)에서 회귀 테스트 후 배포

 

처음 배포는 공통 템플릿을 메인 앱에서 로드하고 프로젝트 설정으로 덮어쓰는 구조가 안전합니다. 변경 흐름은 템플릿 수정 -> 테스트 빌드 -> 사용자 파일 백업 -> 점진 배포 순으로 가져가세요.

 

> 실무 팁: 메뉴를 비우기 전, 복구 경로를 남기세요. 숨김/비활성화 목록을 별도 설정 파일로 유지하면 장애 시 즉시 원복할 수 있습니다.

 

리본·우클릭으로 빠르게 서식·행 복제

 

리본은 반복 작업을 한 번에 처리할 때 알맞습니다. 예시는 ‘회사 규격 서식’ 버튼과 우클릭 ‘행 복제’ 명령을 최소 구성으로 넣는 방법입니다.

 

처음에는 제한된 범위에만 적용하고, 버튼·메뉴 이름은 실제 업무 용어로 바꿔 혼란을 줄이세요.

 

아래 코드는 구조 예시이며, 클릭 시 선택 영역에 서식을 적용하고, 우클릭으로 선택 행을 복제합니다.

 

// 리본: '회사' 탭 > '규격 서식' 버튼
designer.ribbon.addTab({
  id: 'companyTab',
  label: '회사',
  groups: [{
    id: 'formatGroup',
    label: '규격',
    items: [{
      type: 'button',
      id: 'applyCorpStyle',
      label: '규격 서식',
      iconClass: 'gc-spread-icons-fill-color',
      command: () => {
        const sheet = designer.getWorkbook().getActiveSheet();
        const range = sheet.getSelections()[0] || { row: 0, col: 0, rowCount: sheet.getRowCount(), colCount: sheet.getColumnCount() };
        sheet.getRange(range.row, range.col, range.rowCount, range.colCount)
             .backColor('#F7F9FC')
             .font('12px Pretendard')
             .hAlign(1)
             .vAlign(1);
      }
    }]
  }]
});

// 우클릭: 선택 행을 바로 아래로 복제
designer.contextMenu.addItem({
  id: 'duplicateRow',
  text: '행 복제',
  iconClass: 'gc-spread-icons-insert-row',
  visible: ctx => ctx.selection && ctx.selection.rowCount === 1,
  execute: () => {
    const sheet = designer.getWorkbook().getActiveSheet();
    const r = sheet.getSelections()[0].row;
    sheet.addRows(r + 1, 1);
    sheet.copyTo(r, 0, r + 1, 0, 1, sheet.getColumnCount(), 3);
  }
});

 

- 선택 영역을 기준으로 적용 범위를 정하세요.
- 버튼·메뉴 라벨은 사용자 용어로 작성하세요.
- 배포 전 테스트 파일로 서식 영향과 복제 기준(숨김 열 포함 여부)을 확인하세요.

 

> 안티패턴: 우클릭 메뉴를 과도하게 늘리면 찾기 어려워집니다. 자주 쓰는 5~7개만 두고, 나머지는 리본이나 하위 메뉴로 옮기세요.

반응형