MOCA GUIDE 사용자 개발자
MOCA · Standard Web UI/UX Framework

MOCA

사용자 가이드 & 개발자 가이드

MOCA 기반 업무 화면을 사용하는 방법과, MOCA Portable 및 MOCA IntelliSense를 활용해 반응형 업무 화면을 개발하는 방법을 설명합니다.

Version 4.4 · 2026-09-29 · 188×257mm

가이드 구성

이 가이드는 제품을 사용하는 사람과 화면을 개발하는 사람을 위한 두 개의 독립된 PART로 구성됩니다. 필요한 PART만 읽어도 이해할 수 있으며, 정확한 전체 API 규격은 MOCA API 문서에서 확인할 수 있습니다.

업무 사용자PART 1에서 메뉴, 조회, 그리드, 입력, 저장, 팝업과 모바일 화면의 공통 사용법을 익힙니다.
처음 시작하는 개발자PART 2의 Portable 빠른 시작부터 화면 개발 사이클까지 순서대로 진행합니다.
기존 웹 개발자스코프와 생명주기, 레이아웃, 컴포넌트 선택 기준, 공개 API와 보안 연동 계약을 중심으로 봅니다.
교육·평가 담당자제품 구성, IntelliSense, 컴포넌트 체계, 반응형·접근성·보안 절을 통해 제품 범위를 확인합니다.

가이드와 API 문서의 역할

문서담당하는 내용
사용자·개발자 가이드업무 흐름, 선택 기준, 개발 순서, 대표 사용법과 주의사항
MOCA API 문서34종 컴포넌트와 moca.$g·moca.$g.date·moca.$t·$p의 전체 속성·이벤트·메서드

차례

  1. PART 1 · 사용자 가이드
  2. U1가이드 소개
  3. U2로그인과 화면 구성
  4. U3메뉴와 작업 탭
  5. U4조회와 검색조건
  6. U5그리드 기본 사용
  7. U6그리드 편집과 집계
  8. U7입력 및 선택
  9. U8데이터 등록·수정·삭제
  10. U9파일 첨부와 다운로드
  11. U10문서 파일 바로 보기
  12. U11팝업과 새 창
  13. U12대시보드와 위젯
  14. U13달력과 일정
  15. U14트리와 차트
  16. U15모바일과 반응형 화면
  17. U16테마·키보드·접근성
  18. U17메시지와 문제 해결
  19. PART 2 · 개발자 가이드
  20. D1MOCA 소개
  21. D2MOCA Portable 시작하기
  22. D3MOCA IntelliSense
  23. D4화면 구성 모델
  24. D5스코프와 화면 생명주기
  25. D6표준 화면 개발 사이클
  26. D7레이아웃과 반응형 설계
  27. D8컴포넌트 소개
  28. D9화면 구조 컴포넌트
  29. D10폼·입력 컴포넌트
  30. D11업무 처리 컴포넌트
  31. D12시각화·계층 컴포넌트
  32. D13문서·파일 뷰어 컴포넌트
  33. D14표준 화면 패턴
  34. D15공개 API와 데이터 연동
  35. D16설정·테마·접근성
  36. D17프론트엔드 보안과 서버 연동 계약
  37. D18문제 해결과 체크리스트
PART 1

사용자 가이드

MOCA 기반 시스템에서 공통으로 제공하는 조회·입력·저장·탐색 기능을 설명합니다.

U1.가이드 소개

MOCA는 업무 시스템의 화면 구성과 조작 방식을 일관되게 제공하는 UI/UX 프레임워크입니다. 적용 시스템마다 메뉴명과 업무 데이터는 다르지만, 조회·그리드·입력·팝업·모바일 조작은 같은 원칙으로 동작합니다.

이 PART에서 익히는 것 — 원하는 화면을 열고, 조건을 조회하고, 목록을 정리하고, 값을 입력·저장하며, 모바일과 키보드에서도 같은 업무를 수행하는 방법

U2.로그인과 화면 구성

로그인 후 화면은 일반적으로 다음 영역으로 구성됩니다. 적용 시스템의 업무 특성에 따라 일부 영역은 생략되거나 위치가 달라질 수 있습니다.

MOCA 소개 영역과 아이디·비밀번호 입력 영역으로 구성된 로그인 화면
그림 U2-1. 로그인 화면에서 아이디와 비밀번호를 입력하고 데모 워크스페이스를 시작합니다.
영역주요 기능
헤더서비스 정보, 테마 선택, 사용자 메뉴, 로그아웃
메뉴업무 화면을 계층적으로 탐색하고 열기
작업영역여러 업무 화면을 탭으로 열고 전환하기
상태영역조회 건수, 처리시간, 진행 상태 등 확인
확인 — 로그인 후 헤더, 메뉴, 작업영역과 현재 사용자 정보를 확인합니다.
좌측 메뉴, 상단 테마 선택, 작업 영역과 위젯 대시보드가 보이는 MOCA 기본 화면
그림 U2-2. MOCA 기본 화면은 탐색 메뉴와 현재 작업 화면, 상태 정보를 한 화면에서 제공합니다.

U3.메뉴와 작업 탭

MDI 작업영역을 좌우로 분할해 위젯 대시보드와 Form 화면을 동시에 표시한 PC 화면
그림 U3-1. 화면분할을 사용하면 두 작업 탭을 좌우 영역에 배치하고 가운데 경계로 각 화면의 폭을 조절할 수 있습니다.

U5.그리드 기본 사용

그리드는 조회 결과를 표시하고 정렬·필터·페이징·엑셀·전체화면 기능을 제공하는 표입니다.

기능사용 방법
행 선택행을 선택하면 연결된 상세정보가 표시됩니다.
정렬컬럼 헤더의 정렬 버튼을 반복 선택하여 오름차순·내림차순·해제 순으로 전환합니다.
필터헤더의 필터 버튼에서 표시할 값을 선택합니다. 필터가 적용된 컬럼은 아이콘으로 구분됩니다.
컬럼 폭헤더 경계를 드래그하여 폭을 조절합니다.
잘린 값셀 위에 포인터를 두면 전체 내용을 확인할 수 있습니다.
페이징목록 아래의 처음·이전·페이지·다음·마지막 버튼으로 이동합니다.
엑셀현재 정렬·필터가 적용된 목록을 내려받습니다.
전체화면그리드만 확장하여 보고 다시 원래 화면으로 돌아옵니다.
행 상세보기툴바의 상세보기 버튼으로 선택한 행을 항목별 상세 화면으로 펼쳐 봅니다.

행 상세보기

컬럼이 많아 가로로 길게 늘어선 행은 상세보기로 한눈에 확인합니다. 행을 선택하고 툴바의 상세보기 버튼을 누르면 그 행의 모든 항목이 「항목명 — 값」 형태로 펼쳐집니다.

100,000건의 데이터를 페이지 단위로 조회하는 MOCA 페이징 그리드 화면
그림 U5-1. 대용량 목록도 페이지 이동과 정렬·필터 기능을 함께 사용해 필요한 데이터를 빠르게 탐색할 수 있습니다.
업무화면의 그리드 제목 컬럼에서 필터 목록을 펼친 PC 화면
그림 U5-2. 컬럼의 필터 버튼을 누르면 검색어, 전체 선택, 정렬 기준과 표시할 값 목록이 펼쳐집니다.

U6.그리드 편집과 집계

편집 가능한 그리드는 셀을 직접 수정하고 변경된 행만 저장할 수 있습니다. 화면 설정에 따라 상태 컬럼과 삭제 선택 컬럼이 표시됩니다.

표시의미
C새로 추가한 행
U기존 값을 수정한 행
D삭제 대상으로 선택한 행
빈 상태변경되지 않은 행
소계와 합계 행이 있는 판매실적 그리드 화면
그림 U6-1. 업무 목록에서 지역별 소계와 전체 합계를 함께 확인해 데이터의 집계 기준을 분명히 볼 수 있습니다.

U7.입력 및 선택

형태용도조작
입력문자·숫자 한 줄 입력화면에 따라 숫자, 영문, 대소문자 등의 입력 제한이 적용됩니다.
여러 줄 입력설명·메모·본문일반 텍스트 또는 서식 편집 도구를 사용합니다.
콤보정해진 목록에서 하나 선택펼침 버튼으로 목록을 엽니다.
검색 콤보많은 항목에서 하나 선택검색어를 입력하여 후보를 줄입니다.
라디오펼쳐진 항목 중 하나 선택한 항목만 선택할 수 있습니다.
체크박스하나 이상의 항목 선택여러 항목을 동시에 선택할 수 있습니다.
토글사용·미사용 같은 두 상태스위치를 선택하여 상태를 바꿉니다.
슬라이더범위 안의 연속값손잡이를 드래그하거나 방향키를 사용합니다.
날짜·기간날짜 한 개 또는 시작일~종료일직접 입력하거나 달력에서 선택합니다.
팝업 검색사원·거래처·품목처럼 검색조건이 필요한 값돋보기 버튼이나 Enter로 검색 화면을 엽니다.

표시 상태 — 필수 항목은 별도 테두리나 표식으로 구분되고, 읽기 전용 항목은 잠긴 형태로 표시됩니다.

텍스트, 선택, 토글, 날짜 입력 컴포넌트를 한 화면에서 보여주는 Form 화면
그림 U7-1. 입력·선택·날짜 컴포넌트의 상태와 형식을 일관된 화면 규칙으로 제공합니다.

U8.데이터 등록·수정·삭제

기능동작
신규새 데이터를 입력할 수 있도록 빈 상세영역이나 새 행을 준비합니다.
수정선택한 데이터의 편집 상태를 시작합니다.
저장필수값과 입력 형식을 확인한 뒤 변경내용을 반영합니다.
취소저장하지 않은 변경을 원래 상태로 되돌립니다.
삭제선택한 데이터를 확인 후 삭제합니다.
공통코드 목록과 선택 항목의 상세 입력 영역이 함께 보이는 화면
그림 U8-1. 목록에서 대상을 선택하고 상세 영역에서 내용을 확인·수정하는 업무 흐름을 제공합니다.

U9.파일 첨부와 다운로드

파일추가 버튼과 파일을 끌어다 놓는 영역이 있는 파일업로드 팝업
그림 U9-1. 업로드 팝업에서는 [파일추가]로 파일을 고르거나 점선 영역에 파일을 끌어다 놓아 첨부합니다.

U10.문서 파일 바로 보기

첨부 목록이나 게시물의 문서 파일은 내려받아 다른 프로그램으로 열지 않아도 화면에서 바로 확인할 수 있습니다. 파일명이나 [미리보기]를 선택하면 파일 형식에 맞는 뷰어가 열립니다. PC와 모바일에서 같은 방식으로 동작합니다.

형식확인할 수 있는 것
PDF원본 그대로의 쪽 모양. 쪽 이동, 확대·축소, 인쇄, 본문 글자 선택
이미지 (PNG·JPG·GIF·SVG·WebP·BMP)확대·회전·반전, 여러 장이면 슬라이드쇼
텍스트 (TXT·LOG·CSV·MD·JSON)수만 줄의 큰 파일도 빠르게 열람. 낱말 찾기, 줄 번호, 한글 인코딩 자동 인식
XML·HTML태그 구조를 접었다 펴는 트리로 서식·전문의 구조 확인
워드 (DOCX)쪽·표·머리말/꼬리말을 원본 배치대로
엑셀 (XLSX·XLS)시트 탭 전환, 컬럼 정렬·필터
파워포인트 (PPTX)슬라이드의 텍스트·표·기본 도형 — 내용 확인용
한글 (HWPX·HWP)HWPX는 글자 선택·복사까지 지원, 구형 HWP는 내용 확인용
압축 (ZIP)압축을 풀지 않고 폴더 구조를 트리로 확인, 항목별 [미리보기]·[받기]

뷰어 툴바는 형식이 달라도 같은 원칙으로 동작합니다.

모바일에서는 문서 스크롤이 뷰어 안에서만 움직여 화면 전체가 딸려 내려가지 않으며, 긴 문서는 오른쪽의 두꺼운 스크롤 막대를 잡아 끌어 원하는 위치로 바로 이동할 수 있습니다.

확인 — 애니메이션 등 원본과 똑같은 재현이 필요한 발표자료는 PDF로 내보낸 파일로 확인하는 것이 정확합니다.

U11.팝업과 새 창

구분용도닫기 결과
레이어 팝업검색·선택·간단한 등록처럼 현재 화면과 연결된 작업[선택]·[저장]은 결과 반영, [닫기]는 취소
브라우저 새 창원래 화면과 나란히 보거나 별도 창이 필요한 작업완료 버튼은 결과 반영, 창 닫기는 취소

새 창이 열리지 않으면 주소창의 팝업 차단 표시를 확인하고 현재 사이트의 팝업을 허용합니다.

현재 업무화면 위에 품목 검색 레이어 팝업을 연 PC 화면
그림 U11-1. 레이어 팝업은 현재 화면을 유지한 채 검색·선택 작업을 진행하고 선택 결과를 원래 화면에 반영합니다.

U12.대시보드와 위젯

대시보드는 KPI·차트·목록 등의 위젯을 한 화면에 배치합니다. 편집 기능이 제공되는 경우 다음과 같이 개인화할 수 있습니다.

  1. [편집]을 선택합니다.
  2. 위젯을 드래그하여 위치를 바꾸고 크기를 조절합니다.
  3. 필요한 위젯을 추가하거나 사용하지 않는 위젯을 제거합니다.
  4. [저장]으로 배치를 유지하거나 [취소]로 이전 상태로 돌아갑니다.
KPI 카드, 일정, 월별 매출 차트가 배치된 위젯 대시보드 화면
그림 U12-1. KPI와 일정, 핵심 지표 차트를 위젯으로 조합해 업무 현황을 한눈에 확인합니다.

U13.달력과 일정

날짜 선택 달력

InputCalendar 입력 필드와 단일 날짜 달력 팝업을 함께 보여주는 화면
그림 U13-1A. 날짜 입력의 달력 아이콘을 누르면 단일 날짜를 고르는 달력이 열립니다.
InputMultiCalendar 시작일과 종료일 달력이 좌우로 펼쳐진 PC 기간선택 화면
그림 U13-1B. 기간 입력은 시작일(From)과 종료일(To)을 좌우 달력에서 한 번에 선택합니다.
화면에 펼쳐진 Calendar에서 선택일과 공휴일·비영업일을 확인하는 PC 화면
그림 U13-1C. 화면에 항상 펼쳐진 Calendar는 선택일과 공휴일·비영업일을 범례와 함께 표시합니다.

일정 달력

월간 일정과 완료 상태, 여러 날짜에 걸친 일정이 표시된 일정달력 화면
그림 U13-2. 월 단위 일정과 기간 일정, 휴일 정보를 같은 달력 화면에서 확인합니다.

U14.트리와 차트

트리

조직 계층을 펼치고 직원을 선택해 상세정보를 확인하는 Treeview 화면
그림 U14-1. Treeview에서 조직을 단계별로 펼치고 선택한 직원의 상세정보를 같은 화면에서 확인합니다.

차트

세로 막대, 가로 막대, 라인, 누적 막대 차트를 함께 보여주는 MOCA 차트 화면
그림 U14-2. 업무 지표는 막대·라인·누적 차트로 시각화하고, 화면 폭 변화에도 읽기 쉽게 표시합니다.

U15.모바일과 반응형 화면

좁은 화면에서는 목록과 상세가 한 화면에 모두 표시되지 않고 단계적으로 전환될 수 있습니다.

  1. 목록에서 항목을 선택합니다.
  2. 상세가 전체 화면 형태로 열립니다.
  3. 상세의 [목록] 버튼으로 이전 목록에 돌아갑니다.
목록과 상세 영역을 나란히 표시한 MOCA 데스크톱 업무 화면
그림 U15-1A. 넓은 화면에서는 목록과 상세를 나란히 배치해 선택한 데이터를 한 화면에서 확인합니다.
검색, 목록, 상세 영역을 세로 흐름으로 전환한 MOCA 모바일 업무 화면
그림 U15-1B. 좁은 화면에서는 같은 업무 화면이 터치하기 쉬운 세로 흐름으로 전환되고 상세에 목록 복귀 버튼을 제공합니다.

U16.테마·키보드·접근성

테마

다크·라이트·고대비 테마는 같은 기능을 서로 다른 명도와 색상으로 제공합니다. 선택한 테마는 다음 접속에도 유지될 수 있습니다.

키보드

고대비

글자와 배경, 선택 상태와 경계를 더 명확하게 구분해야 할 때 고대비 테마를 사용합니다.

라이트 테마가 적용된 MOCA 위젯 대시보드
그림 U16-1A. 라이트 테마는 밝은 배경과 청록색 강조로 업무 정보와 선택 상태를 구분합니다.
다크 테마가 적용된 동일한 MOCA 위젯 대시보드
그림 U16-1B. 다크 테마에서도 동일한 배치와 정보 구조를 유지하면서 배경·문자·차트 색상을 함께 전환합니다.
고대비 테마가 적용된 동일한 MOCA 위젯 대시보드
그림 U16-1C. 고대비 테마는 밝은 윤곽선과 강조색을 사용해 패널 경계, 선택 상태와 조작 요소를 더 분명하게 표시합니다.

U17.메시지와 문제 해결

증상확인할 내용
입력할 수 없음읽기 전용 항목인지, 목록에서 선택해야 하는 항목인지 확인합니다.
저장되지 않음필수값 안내, 입력 형식, 실제 변경내용이 있는지 확인합니다.
팝업이 열리지 않음브라우저의 팝업 차단 상태를 확인합니다.
정렬·필터가 사라짐재조회로 목록 상태가 초기화된 것인지 확인합니다.
로그인 화면으로 이동함세션이 만료되었을 수 있으므로 다시 로그인합니다.
화면이 잠김무활동 보호 기능이 동작한 경우 다시 시작하여 접속합니다.
문의할 때 함께 전달할 내용 — 화면명, 수행한 작업, 입력조건, 표시된 메시지. 비밀번호나 인증정보는 전달하지 않습니다.
PART 2

개발자 가이드

무설치 개발환경에서 시작해 화면 구조, 공개 생명주기, 34종 컴포넌트와 실무 패턴을 익힙니다.

D1.MOCA 소개

MOCA는 표준 HTML·CSS·JavaScript 위에서 동작하는 프론트엔드 UI/UX 프레임워크입니다. 선언형 속성으로 업무 화면을 구성하고, 화면별 스코프와 공통 컴포넌트로 반복 코드를 줄입니다.

특징설명
선언형 UIdata-m-type과 data-m-* 속성으로 컴포넌트와 동작을 선언합니다.
화면별 스코프SPA 안에서 여러 화면이 같은 ID를 사용해도 $p가 화면 범위를 분리합니다.
업무 컴포넌트그리드·폼·팝업·파일·위젯·달력·트리·차트·문서 뷰어 등 34종을 제공합니다.
반응형·테마같은 화면 구조를 데스크톱·분할창·모바일과 다크·라이트·고대비 환경에서 사용합니다.
개발 도구자동완성, 화면 생성, 구조 탐색, 레이아웃·실행 미리보기를 제공합니다.
서버 독립성업무 서버의 기술과 분리되며, JSON 요청·응답과 보안 계약을 통해 연동합니다.
제품 경계 — MOCA는 화면 렌더링·상태·상호작용·프론트엔드 통신을 담당합니다. 업무 규칙, 데이터 저장, 사용자 권한 판정은 연동 시스템이 담당합니다.

D2.MOCA Portable 시작하기

MOCA Portable은 제품 평가·학습·화면 개발을 위한 무설치 통합 개발환경입니다. 압축을 해제한 폴더 안에 실행도구, 편집기, IntelliSense와 샘플 프로젝트가 함께 들어 있습니다.

빠른 시작

  1. 제공받은 ZIP 파일을 쓰기 가능한 폴더에 압축 해제합니다.
  2. MOCA-시작.bat을 실행하여 샘플 애플리케이션과 브라우저를 엽니다.
  3. MOCA-개발도구.bat을 실행하여 무설치 편집기와 작업공간을 엽니다.
  4. HTML 화면을 수정하고 저장한 뒤 브라우저를 새로고침하여 결과를 확인합니다.

패키지 구성

MOCA-시작.bat          샘플 애플리케이션 실행
MOCA-개발도구.bat       MOCA IntelliSense가 설치된 편집기 실행
README-사용법.txt      시작 방법과 라이선스 안내
editor\                무설치 편집기와 확장
runtime\               실행에 필요한 내장 런타임
workspace\             샘플 프로젝트와 MOCA 엔진
  src\main\webapp\
    vendor\moca\       MOCA 엔진·문서
    system\demo\       샘플 화면
      ui\page\         업무 화면 HTML
Portable에 포함된 실행환경은 학습과 기능 확인을 위한 샘플입니다. MOCA 프론트엔드 프레임워크가 특정 서버 기술을 요구한다는 의미는 아닙니다.

폴더별 책임

폴더개발자가 하는 일주의
editor\편집기와 IntelliSense가 들어 있습니다.프로젝트 소스가 아니므로 화면 개발 중 수정하지 않습니다.
runtime\Portable 실행에 필요한 도구를 제공합니다.시스템에 별도 설치할 필요가 없으며 직접 실행경로를 바꾸지 않습니다.
workspace\src\main\webapp\vendor\moca\MOCA 엔진, 공용 스타일, API·개발자 문서를 확인합니다.업무 화면과 엔진 파일을 구분합니다.
workspace\src\main\webapp\system\demo\ui\page\화면 HTML을 새로 만들거나 수정합니다.새 화면 만들기 기능이 생성하는 기본 위치입니다.
workspace\src\main\webapp\system\demo\images\해당 샘플 프로젝트에서만 사용하는 이미지를 둡니다.MOCA 공용 이미지와 섞지 않습니다.

첫 화면 수정 실습

  1. 편집기에서 ui\page 아래의 HTML 화면 하나를 엽니다.
  2. data-m-label 또는 검색영역의 문구를 바꾸고 저장합니다.
  3. 브라우저에서 해당 화면만 새로고침하여 변경 결과를 확인합니다.
  4. IntelliSense로 새 Input을 추가하고 data-m-placeholder를 입력합니다.
  5. 레이아웃 미리보기에서 새 컴포넌트가 어느 칸에 들어갔는지 확인합니다.

시작 문제 확인

증상확인
시작 창이 바로 닫힘압축을 완전히 해제했는지, 폴더가 쓰기 가능한지 확인합니다.
브라우저가 열리지 않음시작 창의 안내와 사용 중인 포트를 확인한 뒤 주소를 직접 엽니다.
편집기에 MOCA 표시가 없음HTML 파일을 하나 열고 상태표시줄의 MOCA 활성 표시를 확인합니다.
HTML을 저장해도 화면이 그대로임현재 브라우저 화면과 수정한 파일이 같은 샘플 화면인지 확인한 뒤 해당 화면을 새로고침합니다.

D3.MOCA IntelliSense

MOCA IntelliSense는 선언형 마크업과 공개 API를 편집기 안에서 탐색·작성·미리보기할 수 있게 하는 개발 도구입니다. VS Code 계열 편집기와 이클립스를 지원합니다. Portable에는 사전 설치되어 있으며, HTML 또는 JavaScript 파일을 열면 활성화됩니다. 아래 기능 표는 VS Code 확장 기준이고, 이클립스 지원 범위는 이 절 끝의 이클립스에서를 참고합니다.

VS Code에서 설치

MOCA IntelliSense는 마켓플레이스에 등록된 확장이 아니라 MOCA 소스 패키지의 vscode-moca 폴더에 소스로 포함되어 있습니다. Portable이 아닌 환경(소스 패키지를 직접 받은 PC)에서는 다음 순서로 설치합니다. 별도의 빌드나 의존성 설치는 필요 없습니다.

  1. 소스 패키지의 루트 폴더에서 PowerShell로 설치 스크립트를 실행합니다.
    powershell -ExecutionPolicy Bypass -File vscode-mocainstall.ps1
    확장이 %USERPROFILE%.vscodeextensionsmoca-intellisense-<버전>에 복사되며, 이전 버전이 있으면 함께 정리됩니다.
  2. VS Code에서 Ctrl+Shift+P → Developer: Reload Window를 실행합니다. 새 명령·메뉴가 보이지 않으면 한 번 더 실행합니다.
  3. 상태표시줄 오른쪽에 MOCA 24가 표시되면 정상입니다. 이 표시를 클릭하면 읽어들인 카탈로그 파일이 열립니다.

자동완성 후보의 출처 — 확장은 워크스페이스 안의 vendor/moca/js/catalog.js를 읽습니다. MOCA 소스 패키지를 열지 않은 창에서는 후보가 없으며, 다른 위치의 카탈로그를 쓰려면 설정 moca.catalogPath 또는 명령 팔레트의 MOCA: catalog.js 위치 지정으로 경로를 지정합니다. 제거는 설치 스크립트에 -Uninstall을 붙여 실행하거나 확장 폴더를 삭제합니다.

기능개발 효과
마크업 자동완성data-m-type과 컴포넌트 속성·이벤트·허용값을 제공합니다.
스크립트 자동완성$p, moca.$g, moca.$g.date, moca.$t의 공개 API를 제안합니다.
타입 인식$p.get('컴포넌트ID'). 입력 시 해당 컴포넌트의 메서드만 제안합니다.
호버·API 검색속성·메서드 설명을 즉시 확인하고 이름을 몰라도 기능으로 검색합니다.
MOCA OutlineHTML 태그 전체가 아니라 Layout·Frame·Grid·Form 등 화면 골격을 트리로 표시하고 클릭 위치로 이동합니다.
MOCA 팔레트카탈로그의 컴포넌트 목록입니다. 항목을 끌어 디자인뷰의 요소 앞·뒤나 칸 안에 놓으면 그 자리에 골격이 삽입되고, MOCA Outline 의 노드에 놓으면 그 노드 안(칸·폼·위젯·탭) 또는 바로 뒤에 정확히 들어갑니다. 더블클릭하면 편집기 커서 위치에 삽입됩니다.
MOCA 속성커서가 있는 컴포넌트의 속성을 왼쪽 이름·오른쪽 값의 표로 보여줍니다. 허용값이 정의된 속성은 목록에서 고르고, 값을 바꾸면 소스의 여는 태그가 함께 수정됩니다(비우면 속성 삭제). 미리보기·Outline 에서 고른 컴포넌트도 같은 표로 따라옵니다.
구조 색 표시레이아웃·프레임·그리드·폼·위젯·탭의 여는 태그를 종류별 색으로 구분합니다.
새 화면 만들기레이아웃을 시각적으로 분할하고 각 칸의 용도를 선택하여 표준 화면 템플릿을 생성합니다.
레이아웃 미리보기골격 모드와 실행 모드를 전환하고, 경계 드래그로 비율을 조절하며 소스 위치와 선택을 동기화합니다.

권장 사용 순서

  1. 명령 팔레트에서 MOCA: 새 화면 만들기를 실행합니다.
  2. 레이아웃 방향·비율과 칸별 컴포넌트를 선택합니다.
  3. Outline에서 화면 구조를 확인하고 각 컴포넌트의 속성을 자동완성으로 작성합니다.
  4. MOCA: 레이아웃 미리보기에서 골격과 실행 결과를 확인합니다.
  5. 정확한 세부 규격이 필요하면 API 문서를 엽니다.

자동완성 범위

입력 위치제공되는 후보예
data-m-type="34종 컴포넌트 타입grid, form, calendar
컴포넌트 여는 태그해당 타입에 유효한 속성·이벤트Grid의 data-m-rownum, Input의 data-m-keymask
속성값카탈로그에 정의된 허용값data-m-total="top", data-m-datetype="yyyyMMdd"
$p.화면 스코프 공개 APIget, openPop, getParameter
$p.get('id').HTML에서 찾은 ID의 컴포넌트 타입에 맞는 메서드Grid ID이면 drawGrid, getModifiedJSON
moca.$g.메시지·포맷·보안 문자열·공통 유틸리티alert, comma, sanitizeHtml
moca.$g.date.날짜 계산·비교·표시 APIgetToday, format, addDay
moca.$t.조회·저장·업로드 통신 APIexe, upload
Grid 컴포넌트에서 data-m 속성 이름 자동완성 목록을 표시한 편집기 화면
그림 D3-1A. Grid 선언부에서 data-m-을 입력하면 현재 컴포넌트에 유효한 속성과 이벤트가 제안됩니다.
Grid 컴포넌트의 data-m-total 속성값 자동완성 목록과 설명을 표시한 편집기 화면
그림 D3-1B. 속성값 입력 단계에서는 허용값과 각 값의 의미를 함께 확인할 수 있습니다.
Grid ID를 인식해 Grid 전용 메서드를 제안하는 MOCA API 자동완성 화면
그림 D3-2A. $p.get('grd_orders').에서 HTML의 ID와 타입을 판별해 Grid 전용 메서드만 제안합니다.
moca 전역 날짜 API의 메서드 자동완성 목록을 표시한 편집기 화면
그림 D3-2B. moca.$g.date.처럼 공개 API의 단계별 후보를 탐색하며 메서드를 선택할 수 있습니다.

새 화면 만들기

  1. 화면 ID와 제목을 입력합니다.
  2. 루트 Layout을 가로 또는 세로로 분할하고 비율·fit·auto 토큰을 지정합니다.
  3. 필요하면 각 칸을 다시 분할하여 중첩 구조를 만듭니다.
  4. 칸별로 검색영역·Grid·Form·Frame·빈 영역 등 기본 콘텐츠를 선택합니다.
  5. 생성 전 미리보기에서 HTML 골격을 확인하고 파일을 생성합니다.

레이아웃 미리보기의 세 모드

모드확인·편집할 수 있는 것
골격Layout의 방향, 칸 번호와 비율을 도식으로 확인합니다. 칸 경계를 드래그하면 소스의 비율 토큰도 함께 바뀝니다.
디자인서버 없이 소스만으로 화면을 목업(그리드 제목·컬럼 헤더, 폼·검색 행, 입력·콤보·버튼·달력·탭·프레임)으로 그립니다. 요소를 클릭하면 소스·속성 뷰가 따라오고, 텍스트를 더블클릭하면 고칠 수 있으며, 칸 경계 드래그로 비율을 조절합니다. 선택한 요소는 Ctrl+X / Ctrl+C / Ctrl+V / Delete로 잘라내기·복사·붙여넣기·삭제할 수 있고(붙여넣기는 칸이면 안, 요소면 뒤), 모든 편집은 Ctrl+Z / Ctrl+Y로 되돌리고 다시 실행합니다. 실제 동작이나 데이터 없이 배치와 문안을 자유롭게 편집할 때 씁니다.
실행실제 실행 화면을 데스크톱·태블릿·모바일 뷰포트로 확인합니다. 선택 모드에서는 화면 요소를 클릭해 소스 위치로 이동하며, 라벨이나 그리드 헤더 같은 텍스트를 클릭하면 그 문자열이 있는 자리로 이동하고, 더블클릭하면 미리보기 중앙에 수정 창이 열려 글자를 고친 뒤 Enter 또는 확인으로 소스에 반영할 수 있습니다.

편집 즉시 반영 — 실행 모드는 편집기에 열린 소스를 저장하기 전에도 그대로 그립니다. 타이핑, 속성 뷰의 값 변경, 미리보기 안의 텍스트 수정이 잠시 뒤 화면에 반영되며, 새 화면은 보이지 않는 곳에서 그려진 뒤 바꿔치기되므로 깜박이지 않습니다. 저장은 평소처럼 Ctrl+S로 하고, 공통 화면이나 서버 쪽을 고쳤을 때는 새로고침(↻)으로 전체를 다시 불러옵니다.

실행 모드와 로그인 — 실행 모드는 로컬 서버가 미리보기 인증 모드로 기동되어 있어야 로그인 없이 화면을 그립니다. 편집기 태스크 MOCA: 서버 기동이나 F5 디버그로 띄운 서버는 이 모드로 시작되며, 직접 기동할 때는 환경변수 MOCA_PREVIEW=1을 줍니다. 이 모드는 같은 PC 에서 온 미리보기 요청에만 적용되고, 샘플 애플리케이션 런처로 띄운 서버는 로그인이 필요한 제품 모드로 동작합니다.

MOCA 화면 소스와 Layout 골격 미리보기를 나란히 표시한 편집기 화면
그림 D3-5. 소스와 골격 미리보기를 나란히 열어 Layout의 칸 구조와 컴포넌트 배치를 즉시 확인합니다.

세 방향 선택 동기화 — 소스 커서, 미리보기에서 선택한 칸·컴포넌트, MOCA Outline 항목은 같은 대상을 가리킵니다. HTML이 길어져도 현재 작업 위치와 화면 구조를 잃지 않게 해줍니다.

이클립스에서 — MOCA IntelliSense for Eclipse

SI 현장의 표준 개발환경인 이클립스(전자정부표준프레임워크 포함)를 위한 플러그인입니다. VS Code 확장과 같은 컴포넌트 규격(카탈로그)을 읽으므로, 어느 편집기에서 작성하든 제안 내용이 서로 어긋나지 않습니다.

설치
  1. 플러그인 파일(jar)을 내려받아 이클립스 설치 폴더의 dropins 폴더에 복사합니다.
  2. 이클립스를 완전히 종료했다가 다시 시작합니다.
  3. HTML 편집기에서 moca를 입력하고 Ctrl+Space — 설치된 버전과 규격 파일 경로가 표시되면 정상입니다.
기능사용 방법
새 화면 템플릿New → HTML File 마법사에서 MOCA 업무화면 템플릿을 선택하면 화면 표준 뼈대($p 스코프 · onpageload · Layout 골격)로 시작합니다.
컴포넌트 골격본문에서 m + 컴포넌트 이름(mgrid, mform …) 뒤 Ctrl+Space. 27종이 제공되며, 삽입 후 Tab으로 id·label 등 채울 자리를 이동합니다. 들여쓰기는 넣는 자리에 맞춰 자동으로 정렬됩니다.
속성 자동완성태그 안에서 data-m- 뒤 Ctrl+Space. 커서가 있는 컴포넌트에 유효한 속성만 설명과 함께 제안합니다. Layout의 칸이나 Grid의 컬럼처럼 타입이 없는 자식 태그 안에서도 부모 컴포넌트를 인식합니다.
속성값 자동완성값 따옴표 안(data-m-celltype=" ")에서 Ctrl+Space. 그 속성이 받는 허용값을 의미와 함께 제안합니다.
MOCA OutlineWindow → Show View → Other → MOCA. HTML 태그 전체가 아니라 Layout·Frame·Grid·Form 등 화면 골격만 트리로 표시하고, 항목을 고르면 소스의 그 태그로 이동합니다.
MOCA 디자인뷰같은 메뉴에서 엽니다. data-m-layout 골격을 도식으로 그리며 — 칸 클릭 = 소스 이동, 소스 커서 = 칸 선택 표시, 칸 경계 드래그 = 소스의 비율 토큰 수정. 편집하면 도식이 즉시 따라옵니다.
이클립스 New HTML File 마법사에서 MOCA 업무화면 템플릿을 선택하는 화면
그림 D3-6A. 새 파일 마법사에서 MOCA 업무화면 템플릿을 고르면 표준 뼈대로 시작합니다.
MOCA 업무화면(레이아웃 포함) 템플릿으로 생성된 화면 소스
그림 D3-6B. 생성된 화면 — $p 스코프와 Layout 골격, 칸별 다음 작업 안내가 함께 들어 있습니다.
이클립스 편집기에서 mgrid 입력 후 Ctrl+Space 로 그리드 골격이 제안되는 화면
그림 D3-6C. mgrid + Ctrl+Space — 그리드 골격 한 벌이 미리보기와 함께 제안됩니다.
Grid 컬럼 태그 안에서 data-m 속성이 설명과 함께 제안되는 화면
그림 D3-6D. Grid 컬럼 안에서는 Grid에 유효한 속성만 설명과 함께 나옵니다.
data-m-celltype 속성값 후보가 의미 설명과 함께 제안되는 화면
그림 D3-6E. 속성값 자리에서는 허용값(input·selectbox·combobox …)을 의미와 함께 고릅니다.
이클립스에서 소스·MOCA 디자인뷰·MOCA Outline 을 나란히 열고 같은 컴포넌트를 가리키는 화면
그림 D3-6F. 소스 · 디자인뷰 · MOCA Outline — 세 곳이 같은 대상을 가리키며 동기화됩니다.

규격 자동 반영 — 플러그인은 프로젝트의 vendor/moca/docs/moca-catalog.json을 실행 중에 읽습니다. 엔진 규격이 갱신되면 재설치 없이 자동완성에 반영되며, 프로젝트에서 규격 파일을 찾지 못하면 플러그인에 내장된 사본으로 동작합니다.

D4.화면 구성 모델

MOCA 화면은 Layout 안에 Frame과 컴포넌트를 배치하고, 각 Frame에 독립된 화면 스코프를 부여하는 구조입니다.

구성요소역할
Layout상하·좌우·중첩 비율을 선언하고 반응형 화면 골격을 만듭니다.
Frame화면 HTML을 불러오고 독립된 스코프와 생명주기를 생성합니다.
Scope$p로 표현되는 화면별 함수·상태·컴포넌트 접근 범위입니다.
Componentdata-m-type으로 선언하는 입력·그리드·달력·차트 등의 UI 단위입니다.
Public API$p, moca.$g, moca.$t와 컴포넌트 인스턴스 메서드입니다.
<div data-m-type="layout" data-m-layout="vfit:auto" data-m-layout-part="root">
  <div data-m-layout-part="1">검색영역</div>
  <div data-m-layout-part="2" data-m-type="grid" id="grd_main">...</div>
</div>

구성 흐름

업무 화면 HTML
  └─ Layout: 화면 공간과 반응형 규칙
      ├─ Frame: 공통·자식 화면과 독립 Scope
      ├─ Form / Input 계열: 상세 데이터와 상태
      ├─ Grid: 목록·편집·선택·집계
      └─ Calendar / Tree / Widget / Echart: 고급 표현

화면 스크립트
  ├─ $p: 현재 화면
  ├─ $p.get(id): 현재 화면의 컴포넌트
  ├─ moca.$g: 공통 기능
  └─ moca.$t: 데이터 통신

선언과 명령의 역할

구분담당예
선언형 마크업변하지 않는 구조·옵션·연결관계레이아웃 비율, 필수값, Grid 컬럼, Form-Grid 참조
화면 스크립트조회·저장·업무 조건과 동적 변화조회 파라미터, 결과 렌더링, 팝업 결과 반영
컴포넌트반복 상태·렌더링·검증·표준 상호작용행상태, 필터, 버튼 상태, 날짜 범위, 위젯 배치

D5.스코프와 화면 생명주기

SPA에는 여러 화면이 동시에 존재하므로 전역 함수나 전역 DOM 탐색을 사용하면 같은 ID가 충돌할 수 있습니다. 모든 화면 함수와 컴포넌트 접근은 현재 화면의 $p를 기준으로 작성합니다.

작업권장사용하지 않음
함수 정의$p.fn_search = function(){...}전역 함수
컴포넌트 접근$p.get('grd_main')전역 ID·문서 전체 탐색
초기 진입$p.onpageload화면별 window.onload
파라미터$p.getParameter()내부 속성 직접 접근

공개 생명주기

애플리케이션 시작
  → Frame 화면 로드
  → 화면별 $p 스코프 생성
  → 컴포넌트 초기화
  → 자식 Frame 로딩 완료
  → 부모 $p.onpageload
  → 화면 표시 시 $p.onactivate
  → 화면 비활성화 시 $p.ondeactivate
훅시점주요 용도
$p.onpageload자식 Frame과 현재 화면 컴포넌트가 준비된 뒤 최초 1회컴포넌트 참조 보관, 최초 조회, 이벤트 초기화
$p.onactivate최초 표시 및 탭으로 돌아올 때최신 상태 재조회, 타이머 재개
$p.ondeactivate다른 화면으로 전환하거나 닫을 때타이머 중지, 임시 상태 정리
$p.onpageload = function() {
  $p.grid = $p.get('grd_main');
  $p.fn_search();
};
$p.onactivate = function() { /* 화면이 다시 보일 때 */ };
$p.ondeactivate = function() { /* 화면이 가려질 때 */ };

주요 $p API

API설명
$p.get(id)현재 Frame 안에서 ID를 찾아 컴포넌트 인스턴스 또는 요소를 반환합니다.
$p.findAll(selector)현재 화면 범위 안에서만 여러 요소를 찾습니다.
$p.getParameter()탭·팝업·Frame을 열 때 전달된 파라미터를 반환합니다.
$p.getParent()부모 Frame 요소를 반환합니다. 부모 화면 스코프는 이어서 getScope()로 얻습니다.
$p.openPop(option)레이어 팝업을 열고 결과 콜백을 받습니다.
$p.openWin(option)같은 화면을 브라우저 새 창으로 엽니다.
$p.close(result)현재 팝업·탭·새 창을 닫습니다. 결과를 넘기면 호출측 콜백이 실행됩니다.

부모·자식 화면 접근

// 부모가 자식 Frame의 Grid 사용
var child = $p.get('frm_list').getScope();
var grid = child.get('grd_child');

// 자식이 부모 화면의 공개 함수 호출
var parent = $p.getParent().getScope();
parent.fn_refresh();
내부 속성 직접 접근 금지 — frame.scope나 $p.parameter 같은 내부 표현을 읽지 않습니다. 반드시 getScope(), getParameter() 같은 공개 메서드를 사용합니다.

D6.표준 화면 개발 사이클

  1. 화면 유형 결정 — 조회·목록, 배치편집, 목록·상세, 팝업, 대시보드 중 하나를 고릅니다.
  2. 화면 생성 — 새 화면 만들기로 표준 HTML과 루트 Layout을 생성합니다.
  3. 레이아웃 구성 — 검색·목록·상세 영역의 방향과 비율을 선언합니다.
  4. 컴포넌트 선택 — 값을 입력·선택·표시하는 목적에 맞는 기존 컴포넌트를 고릅니다.
  5. 스코프 코드 작성 — 함수와 상태를 $p에 두고 공개 API로 컴포넌트에 접근합니다.
  6. 데이터 연동 — moca.$t 또는 프로젝트 통신 어댑터를 사용해 JSON 데이터를 연결합니다.
  7. 상태·검증 연결 — Form·Grid·ButtonGroup의 상태관리와 필수값 검증을 활용합니다.
  8. 품질 확인 — 넓은 화면·좁은 화면과 다크·라이트·고대비 테마에서 확인합니다.
단계완료 기준주로 쓰는 도구
화면 유형데이터 한 행에 1:N 상세가 있는지 판단하여 배치편집·목록상세를 구분표준 패턴 표
골격모든 콘텐츠가 Layout 칸 안에 있고 fit·auto·비율이 목적과 일치새 화면 만들기·골격 미리보기
컴포넌트직접 만든 UI 없이 기존 컴포넌트로 요구사항을 충족API 검색·자동완성
화면 코드전역 함수·전역 ID 접근 없이 $p 기반으로 작성스크립트 자동완성·Outline
데이터조회·저장 결과와 실패상태를 공통 통신 흐름으로 처리moca.$t
상태·검증필수값, R/U/C, C/U/D, 취소 복구가 컴포넌트와 연결Form·Grid·ButtonGroup
품질화면 폭·테마·키보드·보안 문자열 처리 확인실행 미리보기·체크리스트

D7.레이아웃과 반응형 설계

업무 화면의 골격은 Layout 컴포넌트로 작성합니다. 선언은 방향 문자 + 칸별 크기 토큰 하나로 끝납니다 — v는 세로(위·아래) 분할, h는 가로(좌·우) 분할이고, 토큰을 :로 나열한 개수가 곧 칸 수입니다. 2분할뿐 아니라 h4:3:3처럼 3칸 이상도 같은 방식으로 선언합니다.

크기 토큰 4종

토큰의미대표 용도
숫자칸끼리의 상대 비율입니다. 합이 10일 필요가 없어 2:8과 1:4는 같은 결과입니다(합을 10으로 쓰면 퍼센트처럼 읽혀 관례로 즐겨 쓸 뿐입니다). 0을 주면 그 칸이 접힙니다.h3:7 좌측 목록·우측 상세
숫자px고정 크기 — 가로 분할이면 폭, 세로 분할이면 높이가 고정됩니다.h240px:auto 고정 사이드바
fit내용 크기만큼만 차지합니다(여백이 남지 않음).vfit:auto 상단 검색영역
auto고정 칸(px·fit)을 뺀 남은 공간 전부를 채웁니다.v200px:auto 가변 본문

실행 중 비율 변경

조회 조건이나 사용자 조작에 따라 분할을 바꿔야 하면 setRatio()를 사용합니다. 같은 문법의 토큰을 넘기며, 방향 문자를 붙이면 방향까지 바뀝니다. 한쪽을 0으로 주면 그 칸이 접혀 사이드 영역 토글에 쓸 수 있습니다.

$p.get('lay_body').setRatio('7:3');    // 비율만 변경
$p.get('lay_body').setRatio('v3:7');   // 방향까지 변경
$p.get('lay_body').setRatio('h0:10');  // 왼쪽 칸 접기
구조 규칙 — Layout의 직계 자식은 모두 data-m-layout-part를 가진 칸이어야 하며, Form·Grid·Frame 등의 콘텐츠는 반드시 그 칸 안에 둡니다.

모바일 상세 전환

목록·상세 화면의 상세 칸에 data-m-mobileview="pop"을 지정하면 좁은 화면에서 목록을 우선 표시하고, 행 선택 시 상세를 전체화면 오버레이로 전환할 수 있습니다.

자주 쓰는 골격

화면 유형루트·본문 Layout설명
검색 + 목록vfit:auto검색은 내용 높이, Grid는 남은 높이를 모두 사용합니다.
좌 목록 + 우 상세vfit:auto 안에 h4:6상단 검색 아래에 좌우 목록·상세를 배치합니다.
상 목록 + 하 상세vfit:4:6검색 아래에서 목록과 상세를 세로로 나눕니다.
Grid + Charth5:5동일 데이터를 목록과 시각화로 비교합니다.
고정 사이드 + 본문h240px:auto사이드 메뉴 폭을 고정하고 본문이 나머지를 채웁니다.
단일 콘텐츠v1Grid·달력 등 하나의 컴포넌트가 화면 전체를 채웁니다.

레이아웃 점검

D8.컴포넌트 소개

MOCA 컴포넌트는 화면을 구성하는 표준 UI 단위입니다. 표준 HTML의 div에 타입과 속성을 선언하고, $p.get()으로 인스턴스를 가져와 사용합니다. 이 장에서는 개별 컴포넌트를 살펴보기 전에 공통 사용법을 설명합니다.

<div data-m-type="input" id="ipt_title"
     data-m-required="true"></div>

<script>
$p.fn_read = function() {
  return $p.get('ipt_title').getValue();
};
</script>
원칙설명
기존 컴포넌트 우선직접 UI를 만들기 전에 API 문서나 IntelliSense 검색에서 같은 기능을 찾습니다.
동작은 속성으로표준 class는 MOCA가 부여합니다. 표시나 동작을 바꾸는 값은 class가 아니라 data-m-* 속성으로 지정합니다.
공개 API 사용컴포넌트 내부 속성이 아니라 문서화된 메서드로 값을 읽고 설정합니다.
최소 선언기본값과 다른 동작만 속성으로 선언하여 화면의 의도를 분명하게 유지합니다.
전체 규격 분리가이드에서는 선택 기준과 대표 사용법을, API 문서에서는 전체 속성·이벤트·메서드를 확인합니다.

속성·이벤트·메서드 구분

구분사용 시점예
속성화면이 처음 만들어질 때 정해지는 구조와 기본 동작data-m-required, data-m-readonly
이벤트사용자 조작이나 컴포넌트 상태 변화에 화면 함수를 연결data-m-onchange="$p.fn_changed"
메서드조회 결과나 업무 조건에 따라 런타임 동작을 제어$p.get('cmb_type').setValue('A')

공통 연결 규칙

표준 class는 MOCA가 부여합니다

컴포넌트의 표준 스타일 class는 타입에 맞춰 MOCA가 자동으로 부여하므로 화면에서 적지 않습니다. 화면이 class에 적는 것은 정렬·여백 같은 프로젝트 전용 class뿐입니다. 표시나 동작을 바꾸는 값은 class가 아니라 속성으로 지정합니다. 속성은 값이 정해져 있어 잘못 쓰면 콘솔이 알려주지만, class는 틀려도 아무 알림 없이 모양만 달라집니다.

타입MOCA가 부여하는 표준 class
inputmoca_input
textareamoca_textarea
selectboxmoca_selectbox
comboboxmoca_combobox
inputCalendar·inputMultiCalendarmoca_ica
tabmoca_tab
gridmoca_grid와 남은 높이를 채우는 fauto입니다. 화면이 지정한 class와 무관하게 항상 부여하며, 높이 채우기를 끄려면 data-m-fill="false"를 지정합니다.
formdata-m-variant 값에 따라 moca_table_form(상세) 또는 moca_table_search(검색)

컴포넌트 도판 위치

하나의 화면에 함께 배치되는 입력 컴포넌트는 공통 도판으로 묶고, 구조·업무·시각화 컴포넌트는 대표 동작이 보이는 도판에 연결했습니다.

컴포넌트도판확인할 장면
LayoutD9-1Layout 골격 미리보기
FrameD3-5, U2-2Layout 칸의 자식 화면과 실행 셸
MDIU2-2여러 업무 화면 탭
TabD9-3화면 내부 게시판 탭 전환
FormD10-1제목·검증 버튼·입력 행
InputD10-2문자·전화번호·숫자·금액 입력
TextareaD10-3여러 줄 PATH 입력
SelectboxD10-4정해진 후보 목록 펼침
ComboboxD10-5검색 가능한 후보 목록 펼침
RadioD10-6단일 선택 그룹
CheckboxGroupD10-7복수 선택 그룹
ToggleD10-8ON·OFF 전환
SliderD10-9현재값과 범위 눈금
InputCalendar·InputMultiCalendarD10-10날짜·기간 입력과 달력 팝업
InputPopD10-11검색 입력과 돋보기 버튼
GridD11-1셀 타입·툴바·행 편집
ButtonGroupD11-2Form 상태에 따른 신규·수정·삭제 버튼
FileUploadD11-3파일 선택과 드래그앤드롭
CalendarD12-1화면에 펼쳐진 날짜 선택 달력
ScheduleCalendarD12-2월간·기간 일정 표시
TreeviewD12-3일반 조직 계층과 선택 상세
VirtualTreeD12-410,010개 노드의 가상 렌더링
WidgetD12-5대시보드 조회·편집 상태
EchartD12-6막대·라인·누적 차트
Pdfviewer 등 뷰어 8종D13형식별 담당 뷰어와 장착 방법

D9.화면 구조 컴포넌트

화면 구조 컴포넌트는 콘텐츠를 직접 입력받기보다 화면의 공간과 이동 단위를 정의합니다. Layout과 Frame은 모든 업무 화면의 기반이며, Tab과 MDI는 여러 화면을 전환하는 컨테이너입니다.

D9-1. Layout — 화면 골격

layout은 화면을 상하·좌우·중첩 구조로 나누는 필수 골격 컴포넌트입니다. 직접 flex 비율이나 높이를 계산하지 않고 화면의 의도를 토큰으로 선언합니다.

속성설명대표 값
data-m-layout방향과 칸별 크기를 지정합니다. 첫 글자 v는 세로, h는 가로입니다.vfit:auto, h3:7, v200px:auto
data-m-layout-part칸의 위치를 표시합니다. 루트는 root, 하위 칸은 1, 2.1처럼 적습니다.root, 2.1
data-m-width루트 Layout의 고정 폭 기준입니다. 숫자만 쓰면 px로 처리됩니다.1200
data-m-height루트 Layout의 고정 높이 기준입니다. 팝업처럼 기준 높이가 필요한 화면에 사용합니다.560
data-m-mobileview좁은 화면에서 해당 칸을 전체화면 상세 오버레이로 전환합니다.pop
data-m-mobileheight모바일 세로 배치에서 특정 칸의 높이를 px 기준으로 정합니다.360
크기 토큰동작
숫자남은 공간을 숫자 비율로 나눕니다. h3:7은 좌우 30%:70%에 해당합니다.
숫자px주축 방향으로 고정 크기를 사용합니다.
fit헤더·검색영역처럼 콘텐츠 크기만큼만 차지합니다.
auto고정·fit 칸을 제외한 나머지 공간을 채웁니다.
0해당 칸을 접습니다. setRatio()와 함께 사이드 패널 토글에 사용할 수 있습니다.
<div data-m-type="layout" id="lay_page"
     data-m-layout="vfit:auto" data-m-layout-part="root">
  <div data-m-layout-part="1">검색영역</div>
  <div data-m-layout-part="2" id="lay_body"
       data-m-type="layout" data-m-layout="h4:6">
    <div data-m-layout-part="2.1">목록</div>
    <div data-m-layout-part="2.2" data-m-mobileview="pop">상세</div>
  </div>
</div>

<script>
// 본문 Layout의 좌측 칸을 접고 우측 칸을 확장
$p.get('lay_body').setRatio('h0:1');
</script>
직계 자식 규칙 — Layout 바로 아래 요소는 모두 data-m-layout-part를 가져야 합니다. Grid·Form·Frame을 Layout과 형제로 두거나 칸 표시 없이 바로 넣으면 높이와 반응형 계산이 깨집니다.

레이아웃 구조 확인

루트 Layout 오른쪽 아래의 [레이아웃 구조 보기] 버튼을 누르면 현재 화면의 중첩 방향과 비율 토큰이 각 영역 위에 표시됩니다. 화면 골격을 확인한 뒤 같은 버튼을 다시 누르면 원래 업무 화면으로 돌아옵니다.

레이아웃 구조 보기 버튼을 눌러 vfit:auto, v5:5, h3:7 등의 영역 비율을 표시한 PC 화면
그림 D9-1. 레이아웃 구조 보기는 중첩된 Layout의 방향·비율과 칸 경계를 화면 위에서 바로 확인하는 기능입니다.

D9-2. Frame — 자식 화면 로드와 스코프 생성

frame은 다른 HTML 화면을 현재 화면에 포함하고, 포함된 화면마다 독립된 $p 스코프를 생성합니다.

속성설명
id부모 화면에서 Frame을 찾는 식별자입니다.
data-m-src불러올 화면 HTML 경로입니다. 동적으로 바꾸어 다시 로드할 수 있습니다.
data-m-label자식 화면에 전달하는 간단한 라벨입니다. 공통 제목 Frame 등에 사용합니다.
data-m-scopeid엔진이 부여하는 스코프 ID입니다. 업무 화면에서 직접 선언하지 않습니다.
data-m-scopepath부모부터 이어지는 스코프 경로입니다. 엔진 관리 속성입니다.
data-m-kind메인·팝업·새 창 등 Frame의 용도를 나타내는 엔진 관리 표식입니다.
<div data-m-type="frame" id="frm_title"
     data-m-src="./common/title.html"
     data-m-label="사용자 관리"></div>

<script>
// 자식 화면 로드 완료 후 자식 스코프의 공개 함수 호출
var childScope = $p.get('frm_title').getScope();
if (childScope) childScope.fn_refresh();
</script>

초기화 순서 — 자식 Frame의 컴포넌트와 onpageload가 끝난 뒤 부모 화면의 onpageload가 실행됩니다. 따라서 부모 초기화 시 자식의 스코프와 컴포넌트를 바로 가져올 수 있습니다.

D9-3. Tab — 화면 내부 패널 전환

tab은 하나의 업무 화면 안에서 여러 패널을 전환합니다. 선언 탭과 동적 탭을 함께 사용할 수 있습니다.

속성·이벤트설명
data-m-target탭 버튼이 활성화할 패널 ID이며 탭 식별자로도 사용됩니다.
data-m-src패널이 선택될 때 Frame 방식으로 불러올 화면 경로입니다.
data-m-closabletrue이면 탭에 닫기 버튼을 표시합니다.
data-m-disabledtrue이면 탭 전환을 막습니다.
data-m-ontabclick탭 헤더를 누른 직후, 선택 확정 전에 호출합니다. false를 반환하면 전환을 취소할 수 있습니다.
data-m-ontabchange클릭 또는 API 호출로 활성 탭이 바뀐 뒤 호출합니다.
메서드설명
selectTab(indexOrId)인덱스 또는 탭 ID로 활성 탭을 변경합니다.
addTab(option)id, text, src, param, closable, select 등을 지정하여 탭을 추가합니다.
removeTab(indexOrId)지정 탭을 제거합니다. 생략하면 현재 탭을 제거합니다.
reloadTab(indexOrId)탭에 로드된 화면을 같은 경로와 파라미터로 다시 불러옵니다.
getSelectedIndex(), getTabId()선택된 인덱스와 탭 ID를 조회합니다.
getTabCount(), getTabIds()탭 개수와 전체 ID 목록을 조회합니다.
getTabTitle(), setTabTitle()탭 제목을 읽거나 변경합니다.
setTabDisabled(id, bool), isTabDisabled()탭 잠금 상태를 설정하거나 확인합니다.
var tab = $p.get('tab_detail');

tab.addTab({
  id: 'tabHistory',
  text: '변경이력',
  src: './history.html',
  closable: true,
  select: true
});

tab.setTabDisabled('tabHistory', true);
tab.setTabTitle('tabHistory', '변경이력(12)');
게시판 탭 두 개와 선택된 탭의 목록·상세 화면
그림 D9-3. Tab은 한 업무 화면 안에서 패널을 전환하고 선택된 탭의 목록·상세 상태를 유지합니다.

D9-4. MDI — 애플리케이션 업무 탭

mdi는 애플리케이션 전체의 업무 화면 탭을 관리하는 셸 전용 컴포넌트입니다. 일반 업무 화면 안에서는 직접 만들기보다 이미 구성된 MDI의 공개 메서드를 사용합니다.

메서드설명
openTab(url, param)업무 화면을 열고, 이미 같은 화면이 열려 있으면 해당 탭을 활성화합니다.
closeTab(tabId)지정한 업무 탭을 닫습니다.
getActiveTab()현재 활성 탭의 정보를 반환합니다.

D10.폼·입력 컴포넌트

입력 컴포넌트는 값의 종류와 선택 방식에 맞게 고릅니다. Form의 data-m-ref 매핑을 사용하면 한 행의 데이터를 필드에 일괄 설정하고 수정값을 Grid와 자동으로 동기화할 수 있습니다.

D10-1. Form — 입력영역·상태·검증

주요 속성설명
data-m-label, data-m-sublabel폼 제목과 보조 제목을 표시합니다.
data-m-addition타이틀바 좌우에 추가할 버튼·라벨을 JSON 배열로 정의합니다.
data-m-readonly내부 입력 컴포넌트를 일괄 읽기 전용으로 시작합니다.
data-m-statusR(조회), U(수정), C(신규) 상태를 나타냅니다.
data-m-refgrid연결할 Grid ID 또는 표현식입니다. 행 선택→폼 채움, 폼 변경→선택행 반영을 자동 처리합니다.
data-m-variant폼 변형을 지정합니다. form은 상세 입력용, search는 조회조건용 모양입니다.
data-m-toolbarfoldtrue이면 폼 접기·펼치기 버튼을 표시합니다.
data-m-showrowselection폼 행 클릭 선택을 사용할지 지정합니다.
data-m-oncellclick, data-m-onfoldclick행·셀 클릭과 접기 상태 변경 이벤트입니다.
메서드설명
setRowJSON(row)행 데이터를 내부의 data-m-ref 필드에 일괄 설정합니다.
setStatus(status), getStatus()R/U/C 상태를 설정·조회합니다.
setReadOnly(bool)내부 입력 컴포넌트를 한 번에 잠그거나 해제합니다.
validate()data-m-required="true"인 필드를 검사하고 실패 위치로 포커스를 이동합니다.
reset()폼 값을 초기 상태로 비웁니다.
getFormObj(id), setFormValue(id, value)폼 내부 컴포넌트를 찾거나 값을 지정합니다.
<div data-m-type="form" id="fom_detail"
     data-m-variant="form"
     data-m-refgrid="grd_main"
     data-m-readonly="true">
  <div data-m-type="input" id="ipt_name"
       data-m-ref="NAME"
       data-m-required="true"></div>
</div>

D10-2. Input — 한 줄 입력

속성설명
data-m-value초기 입력값입니다.
data-m-inputtypepassword를 지정하면 입력 문자를 가립니다.
data-m-requiredForm·Grid 검증 시 필수 입력으로 판정합니다.
data-m-readonly, data-m-innerdisabled읽기 전용 또는 비활성 상태를 지정합니다.
data-m-keymask숫자·금액·실수·전화번호·대문자·소문자 등 입력 가능한 문자를 제어합니다.
data-m-displayfunction원본값을 바꾸지 않고 콤마·전화번호·백분율 등 표시만 가공합니다.
data-m-displayfunctionapplyrealtime이면 입력 중에도 표시함수를 적용합니다.
data-m-maxlength, data-m-placeholder최대 길이와 안내 문구를 지정합니다.
data-m-refForm의 행 데이터와 연결할 필드명입니다.
data-m-inneronblur, data-m-callfunction포커스 이탈 또는 사용자 정의 호출 이벤트입니다.
메서드반환·동작
getValue()표시 가공 전 원본값을 반환합니다.
getDisplayValue()화면에 표시된 가공값을 반환합니다.
setValue(value)원본값을 저장하고 표시함수를 적용합니다.
setReadOnly(bool)읽기 전용 상태를 변경합니다.
<div data-m-type="input" id="ipt_amount"
     data-m-keymask="onlyNumber"
     data-m-displayfunction="moca.$g.comma"
     data-m-required="true" data-m-maxlength="12"></div>
Form 화면에 배치된 문자·전화번호·숫자·금액 Input 입력 영역
그림 D10-2. Input은 문자·전화번호·숫자·금액 등 한 줄 업무값을 형식에 맞게 입력합니다.

D10-3. Textarea — 여러 줄 입력

속성설명
data-m-value초기 본문입니다.
data-m-readonly, data-m-innerdisabled읽기 전용·비활성 상태입니다.
data-m-placeholder, data-m-maxlength, data-m-rows안내 문구, 길이와 표시 행 수를 지정합니다.
data-m-refForm 데이터 필드와 연결합니다.
data-m-rendertypetextarea 또는 div 방식 등 렌더 유형을 지정합니다.
data-m-inneronblur포커스를 잃을 때 호출할 함수입니다.

getValue(), setValue(), setReadOnly()로 값을 관리합니다.

선택 컴포넌트 화면에 배치된 Textarea 입력 영역
그림 D10-3. Textarea는 여러 줄 본문을 입력하고 읽기 전용·길이·행 수를 설정할 수 있습니다.

D10-4. Selectbox — 정해진 목록 선택

속성설명
data-m-itemset목록 JSON 배열입니다. 기본 코드·라벨 키는 cd와 nm입니다.
data-m-cdkey, data-m-nmkey목록에서 코드와 표시명을 읽을 필드명을 바꿉니다.
data-m-codeopt‘전체’·‘선택’ 같은 앞쪽 기본 옵션을 지정합니다.
data-m-displayformat[value]와 [label] 토큰으로 표시형식을 정의합니다.
data-m-parentcomp, data-m-parentkey부모 선택값에 따라 목록을 필터링하는 연동 Selectbox를 구성합니다.
data-m-defaultvalue초기 기본 선택값입니다.
data-m-readonly, data-m-disabled읽기 전용·비활성 상태입니다.
data-m-onchange사용자가 선택을 바꾼 뒤 호출할 함수입니다.
메서드설명
getValue(), getLabel()선택 코드와 표시 라벨을 반환합니다.
setValue(value)코드값으로 선택을 변경합니다.
getList()추가 옵션을 제외한 원본 목록을 반환합니다.
draw(options)목록·키·부모 연동 설정을 합쳐 다시 렌더링합니다.
setReadOnly(bool)잠금 상태를 변경합니다.
<div data-m-type="selectbox" id="cmb_useYn"
     data-m-itemset='[{"cd":"Y","nm":"사용"},{"cd":"N","nm":"미사용"}]'
     data-m-defaultvalue="Y"
     data-m-onchange="$p.fn_useChanged"></div>
PC 화면의 Selectbox 컴포넌트에서 후보 항목 목록을 펼친 화면
그림 D10-4. Selectbox는 선택 필드 아래로 정해진 후보를 펼쳐 한 항목을 선택합니다.

D10-5. Combobox — 검색 가능한 목록 선택

후보가 많아 사용자가 글자를 입력해 좁혀야 할 때 사용합니다. 기본 목록 키와 부모 연동 규칙은 Selectbox와 같습니다.

주요 속성설명
data-m-itemset검색 대상 목록입니다.
data-m-cdkey, data-m-nmkey코드·라벨 필드명입니다.
data-m-value, data-m-text현재 선택 코드와 표시 텍스트입니다.
data-m-parentcomp, data-m-parentkey부모 컴포넌트 값에 따른 목록 필터입니다.
data-m-readonly입력·선택을 잠급니다.
data-m-inneronchange선택 변경 후 추가로 실행할 함수입니다.

getValue(), getLabel(), getList(), setValue(), setReadOnly(), draw(), setList()를 제공합니다.

Selectbox와의 차이 — Combobox의 draw()에는 chooseOption을 전달하지 않습니다. ‘선택’ 항목이 필요하면 데이터 목록에 명시적으로 포함합니다.
Combobox의 검색 입력과 후보 목록을 펼친 확대 화면
그림 D10-5. Combobox는 입력값으로 후보를 좁히면서 목록에서 선택합니다.

D10-6. Radio — 단일 선택

속성설명
data-m-itemset화면에 펼쳐서 표시할 라디오 항목 배열입니다.
data-m-disabled전체 항목을 비활성화합니다.
data-m-inneronclick항목 선택 시 호출할 함수입니다.

getValue(), getLabel(), setValue(), setReadOnly(), redraw()를 제공합니다.

선택 컴포넌트 화면에 배치된 Radio 단일 선택 영역
그림 D10-6. Radio는 펼쳐진 항목 가운데 하나의 값을 선택합니다.

D10-7. CheckboxGroup — 복수·독립 선택

속성설명
data-m-checktypecheckbox는 단일, checkboxGroup은 다중 선택입니다.
data-m-label단일 체크박스의 라벨입니다.
data-m-itemset그룹 항목 배열입니다. 각 항목에 label·value·checked·onclick·disabled를 지정할 수 있습니다.
data-m-directionvertical이면 항목을 세로로 배치합니다.
data-m-disabled전체 선택을 비활성화합니다.

getValue()는 단일형이면 boolean, 그룹형이면 선택된 값의 배열을 반환합니다. setValue(), setReadOnly(), redraw()도 제공합니다.

선택 컴포넌트 화면에 배치된 CheckboxGroup 복수 선택 영역
그림 D10-7. CheckboxGroup은 여러 항목을 독립적으로 선택합니다.

D10-8. Toggle — 두 상태 전환

속성설명
data-m-label토글 옆에 표시할 라벨입니다.
data-m-onoff초기 상태입니다. on 또는 off를 사용합니다.
data-m-truevalue, data-m-falsevalueON·OFF일 때 getValue()가 반환할 업무값입니다.
data-m-readonly사용자 조작을 막습니다.
data-m-onchange클릭으로 상태가 바뀐 뒤 fn(comp, onoff) 형태로 호출됩니다.

isOn(), getValue(), setValue(), setReadOnly()를 제공합니다.

<div data-m-type="toggle" id="tog_use"
     data-m-label="사용"
     data-m-truevalue="Y" data-m-falsevalue="N"
     data-m-onchange="$p.fn_toggleChanged"></div>
선택 컴포넌트 화면에 배치된 Toggle 상태 전환 영역
그림 D10-8. Toggle은 ON·OFF 두 상태를 직관적으로 전환합니다.

D10-9. Slider — 범위값 선택

속성설명
data-m-min, data-m-max선택 가능한 최솟값과 최댓값입니다.
data-m-step키보드·드래그 조작 시 증감 단위입니다.
data-m-value초기값이며 조작 시 현재값으로 갱신됩니다.
data-m-unit값과 눈금에 표시할 단위입니다.
data-m-showvalue, data-m-showscale현재값과 양끝 눈금 표시 여부입니다.
aria-label화면 라벨이 없을 때 제공해야 하는 접근성 이름입니다.
data-m-oninput, data-m-onchange조작 중과 값 확정 시 호출할 이벤트입니다.

getValue(), setValue(), setReadOnly()를 제공합니다.

선택 컴포넌트 화면에 배치된 Slider 범위값 선택 영역
그림 D10-9. Slider는 정해진 범위 안에서 현재값을 드래그하거나 키보드로 조정합니다.

D10-10. InputCalendar·InputMultiCalendar — 날짜·기간 입력

속성설명
data-m-typeinputCalendar는 단일 날짜, inputMultiCalendar는 시작일~종료일입니다.
data-m-datetype일·월·연·일시 등 선택 단위와 값 자릿수를 정합니다.
data-m-displayformat# 자리표시자를 사용해 날짜 표시형식을 지정합니다.
data-m-defaultvalue초기 날짜값입니다.
data-m-datemin, data-m-datemax달력과 직접입력 모두에 적용되는 선택 가능 범위입니다.
data-m-showradiooption, data-m-selecteritem오늘·당월 같은 기간 빠른선택 옵션을 구성합니다.
data-m-maxtermbyday, data-m-maxtermbymonth, data-m-maxtermbyyear기간 선택의 최대 길이를 제한합니다.
data-m-ondateselected날짜 선택이 확정되면 호출됩니다.
메서드설명
getValue(), setValue(value)단일 날짜값을 숫자 문자열로 읽고 설정합니다.
setFrom(value), setTo(value)기간의 시작일과 종료일을 설정합니다.
setMultiCalendar({from,to})기간을 한 번에 초기화합니다.
setReadOnly(bool)입력과 달력 선택을 잠급니다.
<div data-m-type="inputCalendar" id="cal_workDt"
     data-m-datetype="yyyyMMdd"
     data-m-displayformat="####-##-##"
     data-m-datemin="20260101" data-m-datemax="20261231"></div>
InputMultiCalendar 달력 아이콘을 눌러 시작일과 종료일 달력이 좌우로 펼쳐진 PC 기간선택 화면
그림 D10-10A. PC에서는 기간 입력의 달력 아이콘을 누르면 시작일(From)과 종료일(To) 달력이 좌우로 펼쳐져 범위를 한 번에 선택할 수 있습니다.
InputCalendar 입력 필드와 달력 팝업을 함께 보여주는 확대 화면
그림 D10-10B. 달력 버튼을 누르면 현재 값과 선택 가능한 날짜를 팝업에서 확인할 수 있습니다.

D10-11. InputPop — 팝업 검색 입력

속성·이벤트설명
data-m-value초기 표시값입니다.
data-m-placeholder, data-m-maxlength안내 문구와 최대 길이입니다.
data-m-refForm 데이터 필드와 연결합니다.
data-m-readonly직접입력과 팝업 호출을 잠급니다.
data-m-onclick돋보기나 Enter 입력 시 fn(comp) 형태로 호출됩니다.

openPop(option), getValue(), setValue(), setReadOnly()를 제공합니다.

선택 컴포넌트 화면에 배치된 InputPop 검색 입력 영역
그림 D10-11. InputPop은 입력값과 팝업 호출 버튼을 함께 제공합니다.

D10-12. Ckeditor — 리치 텍스트(HTML) 본문

게시글·공지·메일 본문처럼 글꼴·표·이미지가 들어가는 본문은 data-m-type="ckeditor"로 넣습니다. CKEditor 4를 감싼 컴포넌트이므로 화면에 <script> 태그를 넣지 않습니다 — 화면에 선언이 있으면 MOCA가 필요할 때 불러옵니다. 값은 HTML 문자열로 주고받습니다.

속성설명
id컴포넌트 이름입니다. 접두사는 edt_를 씁니다(예: edt_body). 같은 화면이 탭·MDI에 여러 번 열려도 내부 에디터 ID는 MOCA가 화면별로 구분합니다.
data-m-readonly"true"이면 잠긴 상태로 시작합니다.
data-m-toolbar툴바 구성을 고정합니다. 지정하지 않으면 PC는 Default, 모바일은 Mobile(짧은 툴바)을 자동으로 고릅니다. View는 보기 전용입니다 — 툴바·하단 경로 없이 항상 읽기 전용으로, 받은 메일·게시글처럼 남이 쓴 HTML을 보여 줄 때 씁니다(아래 4).
data-m-fill남은 높이 채우기입니다. 기본은 채우고, 내용 높이만 쓰려면 "false"를 줍니다.
메서드설명
getValue() · setValue(html)본문 HTML을 읽고 씁니다. 에디터가 준비되기 전에 넣은 값은 보관했다가 준비되는 순간 반영합니다.
setReadOnly(bool)읽기 전용을 전환합니다.
getEditor(fn) · onReady(fn)에디터가 준비되면 CKEditor 인스턴스를 넘겨 줍니다. 아직 만들어지지 않았으면 이 호출이 에디터를 만듭니다.
getEditorObj()이미 만들어진 인스턴스를 바로 돌려줍니다(없으면 null).

1) 넣는 자리 — 상세 폼의 한 행. 에디터는 상세 폼(data-m-variant="form")의 td에 넣고 폭과 높이를 적지 않습니다(style="width:…; height:…" 없이). 에디터는 칸의 가로를 끝까지 채우고, 상세 폼은 칸의 남는 높이를 스스로 채우면서 에디터·Textarea가 든 행에 그 높이를 줍니다. 그래서 창 크기가 바뀌거나 모바일로 넘어가도 에디터가 카드에 맞춰 가로·세로로 늘고 줄어듭니다.

<div data-m-type="form" data-m-variant="form" id="fom_detail" data-m-label="게시글">
  <div data-m-body="tbody">
    <div data-m-row="tr">
      <div data-m-cell="th">제목</div>
      <div data-m-cell="td"><div data-m-type="input" id="ipt_title" data-m-ref="TITLE"></div></div>
    </div>
    <div data-m-row="tr">
      <div data-m-cell="th">내용</div>
      <div data-m-cell="td"><div data-m-type="ckeditor" id="edt_body"></div></div>   <!-- 높이 없음 — 이 행이 늘어난다 -->
    </div>
  </div>
</div>

에디터가 아닌 다른 행을 늘리고 싶을 때만 폼에 class="flex", 늘릴 행에 class="flex-grow1"을 줍니다. 화면 전체는 레이아웃 컴포넌트로 짜고, 에디터 폼이 든 칸은 auto(남는 높이)로 둡니다 — 예: data-m-layout="vfit:auto"의 두 번째 칸, 좌우 분할이면 h5:5의 한쪽.

2) 값 다루기. 조회한 본문은 setValue(html), 저장할 본문은 getValue()로 받습니다. 본문은 다른 필드와 달리 data-m-ref로 묶지 않고 저장 직전에 따로 읽어 요청에 싣습니다.

$p.onpageload = function () {
  $p.edt = $p.get('edt_body');
  $p.edt.getEditor();                       // 빈 본문으로 시작하는 화면이면 에디터를 바로 만든다
};
$p.fn_save = function () {
  var _row = $p.get('fom_detail').getRowJSON();
  _row.CONTENT = $p.edt.getValue();         // 본문 HTML
  // … 저장 요청
};
에디터 오른쪽이 비어 보일 때 — 에디터를 폼 td나 한 줄(.moca_row) 바로 안에 두었는지 확인합니다. 그 자리에서는 MOCA가 에디터를 칸 폭 전체로 늘립니다. 에디터를 다른 div로 한 겹 더 감싸면 그 div가 툴바 폭만큼만 차지해 넓은 화면에서 오른쪽이 빈칸으로 남습니다 — 감싸지 말고 td에 바로 둡니다. 화면이 폭을 px로 고정해도 같은 일이 생깁니다.
에디터가 뜨지 않고 작은 입력칸만 보일 때 — Ckeditor는 필요할 때 만들어집니다. 값이 있는 setValue()나 getEditor()가 불릴 때 생성되므로, 새 글 쓰기처럼 빈 본문으로 시작하는 화면은 onpageload에서 getEditor()를 한 번 불러 에디터를 띄웁니다(빈 값의 setValue('')로는 만들어지지 않습니다). 또 에디터는 화면에 보일 때 만들어집니다 — 닫힌 모바일 상세창이나 뒤쪽 탭 안에 있으면 그 칸이 열리는 순간 생성되고, 그사이 넣은 값은 그대로 반영됩니다.

3) 기본 본문·서명. 본문을 미리 채우려면 화면이 열릴 때 setValue()로 넣습니다(예: 빈 줄 + 서명 이미지). 메일처럼 밖으로 보내는 HTML에 이미지를 넣을 때는 받는 쪽이 인터넷에서 읽을 수 있도록 https://로 시작하는 절대주소를 쓰고, 메일 프로그램은 스타일시트를 읽지 않으므로 크기는 <img width="360" style="max-width:100%">처럼 태그에 직접 적습니다.

4) 보기 전용(data-m-toolbar="View"). 남이 쓴 HTML(받은 메일, 외부에서 온 본문)은 편집하지 않는 에디터로 보여 줍니다. 에디터는 자기 iframe 안에 본문을 그리므로 본문의 스타일이 화면을 흔들지 않고, 화면의 스타일도 본문을 흔들지 않습니다. 넣기 전에 moca.$g.sanitizeHtml(html)로 실행되는 것(script·이벤트 속성)을 걷어낸 뒤 setValue()합니다. 보기 전용 에디터는 폼 td가 아니라 레이아웃 칸에 바로 두어도 칸의 가로·세로를 채웁니다 — 팝업에서 머리 정보(폼) 아래 본문 칸을 auto로 두면 본문이 남는 높이를 가져갑니다.

<div data-m-type="layout" data-m-layout="vfit:auto:fit" data-m-layout-part="root" data-m-height="680">
  <div data-m-layout-part="1"> … 보낸 사람·날짜 보기 폼 … </div>
  <div data-m-layout-part="2"><div data-m-type="ckeditor" id="edt_view" data-m-toolbar="View"></div></div>
  <div data-m-layout-part="3" class="bd_modal_btns pop_btn_area"> … [삭제] [목록] … </div>
</div>
$p.get('edt_view').setValue(moca.$g.sanitizeHtml(mailHtml));

5) 테마·모바일. 다크·라이트·고대비 테마 색은 MOCA가 에디터 안쪽까지 맞추므로 화면이 색을 정하지 않습니다. 좁은 화면에서는 툴바가 짧은 구성으로 바뀌고, 폼이 세로로 쌓이면서 에디터 행이 남는 높이를 계속 채웁니다.

D11.업무 처리 컴포넌트

Grid, ButtonGroup, FileUpload, FloatingButton은 조회·편집·저장 중심의 업무 화면을 구성합니다. 이 가운데 Grid는 속성이 가장 많으므로 그리드 전체, 헤더, 데이터 셀로 나누어 이해하는 것이 좋습니다.

D11-1. Grid — 선언 구조

<div data-m-type="grid" id="grd_main"
     data-m-label="사용자 목록"
     data-m-rownum="true"
     data-m-rowstatus="true"
     data-m-delcheck="true"
     data-m-toolbarbtnpc='{"addrow":"true","delrow":"true","exdn":"true","full":"true"}'
     data-m-onrowselected="$p.fn_rowSelected">
  <div data-m-body="tbody">
    <div data-m-row="tr">
      <div data-m-cell="th" data-m-sortable="true">이름</div>
      <div data-m-cell="th" data-m-filterable="true">상태</div>
    </div>
    <div data-m-row="tr">
      <div data-m-cell="td" id="NAME"
           data-m-celltype="input"
           data-m-required="true"
           data-m-maxlength="50"></div>
      <div data-m-cell="td" id="USE_YN"
           data-m-celltype="selectbox"
           data-m-itemset='[{"code":"Y","codeNm":"사용"},{"code":"N","codeNm":"미사용"}]'></div>
    </div>
  </div>
</div>
Checkbox, Radio, Selectbox, Combobox와 입력 셀이 포함된 편집 Grid
그림 D11-1. Grid는 셀 타입, 행 상태, 정렬·필터와 공통 툴바를 하나의 목록·편집 컴포넌트로 제공합니다.

Grid 전체 속성

속성설명
data-m-label, data-m-sublabel그리드 제목과 보조 제목입니다.
data-m-defaultcellheight기본 행 높이 기준입니다.
data-m-rowselectedcolor선택행 색상을 화면별로 지정할 때 사용합니다.
data-m-rownum순번 컬럼을 자동 생성합니다.
data-m-rowstatusC/U/D 행상태 컬럼을 자동 생성합니다.
data-m-delcheck삭제선택 컬럼과 헤더 전체선택을 자동 생성합니다.
data-m-autoselectfirst데스크톱에서 조회 후 첫 행을 자동 선택합니다.
data-m-editguard편집 중 다른 행으로 이동할 때 변경 유실 확인을 표시합니다.
data-m-editguardtarget마스터 행 이동 시 변경 여부를 감시할 상세 Grid를 지정합니다.
data-m-editguardmsg편집 유실 확인 메시지를 바꿉니다.
data-m-paging번호 목록 등 페이징 옵션을 JSON으로 지정합니다.
data-m-onscrollend스크롤 끝에 도달할 때 호출할 함수를 지정합니다.
data-m-filterdistinctlimit필터 후보의 고유값이 지나치게 많을 때 필터 생성을 중단하는 보호 기준입니다.
data-m-subtotal소계를 나눌 그룹 컬럼 ID입니다.
data-m-total합계행 위치를 top, bottom, false로 지정합니다.
data-m-subtotallabel, data-m-totallabel소계·합계 라벨을 바꿉니다.

툴바 속성

속성설명
data-m-fill남은 높이를 채울지 여부입니다. 지정하지 않으면 채우며, 내용 높이만 쓰려면 false를 지정합니다.
data-m-toolbar툴바(제목줄) 노출 여부입니다. 지정하지 않으면 노출하며, 조회 전용 팝업처럼 툴바가 필요 없으면 false를 지정합니다.
data-m-toolbarbtnpc데스크톱의 상세·엑셀·행추가·행삭제·전체화면·컬럼표시·더보기 등의 기본 버튼을 JSON으로 설정합니다.
data-m-toolbarbtnmobile모바일에서 사용할 기본 버튼 구성을 별도로 지정합니다.
data-m-toolbarleft, data-m-toolbarright좌우 영역에 사용자 정의 도구 항목 배열을 추가합니다.
data-m-toolbarbtn*라벨과 onclick을 가진 사용자 버튼을 추가합니다.
data-m-toolbarlabel*, data-m-toolbarspan*일반 라벨 또는 라벨+값+단위를 표시합니다.
data-m-toolbarinput*, data-m-toolbarselectbox*툴바에 입력칸이나 콤보를 추가합니다.
data-m-toolbarradio*, data-m-toolbarcheckbox*라디오·체크박스 선택 도구를 추가합니다.

툴바의 행 상세보기는 detail 키로 켭니다. 값에 따라 동작이 갈립니다.

<div data-m-type="grid" id="grd_main"
     data-m-toolbarbtnpc='{"detail":"true","exdn":"true","full":"true"}'
     data-m-toolbarbtnmobile='{"detail":"true"}'>

컬럼·헤더 속성

위치속성설명
coldata-m-columnkey폭을 적용할 데이터 셀 ID와 col을 연결합니다.
coldata-m-hide기기와 무관하게 해당 컬럼을 숨깁니다.
coldata-m-mobilehide모바일에서만 컬럼을 숨깁니다.
thdata-m-sortable정렬 버튼을 표시합니다.
thdata-m-filterable값 목록 필터 버튼을 표시합니다.
thdata-m-required필수 컬럼 표식을 표시합니다.
thdata-m-celltype="checkbox"헤더 전체선택 체크박스를 렌더링합니다.

데이터 셀 속성

속성설명
id행 데이터의 필드명과 연결되는 컬럼 식별자입니다.
data-m-celltypeinput, checkbox, button, radio, selectbox, combobox, tree 등 셀 편집·표시 유형입니다.
data-m-readonly셀 편집 가능 여부입니다.
data-m-requiredvalidate()에서 검사할 필수 셀입니다.
data-m-keymaskInput과 동일한 숫자·금액·전화·대소문자 입력제어를 적용합니다.
data-m-displayfunction원본 셀값은 유지하고 화면 표시만 가공합니다.
data-m-displayformatSelectbox·코드 셀의 [value]·[label] 표시형식입니다.
data-m-maxlength편집 셀의 최대 입력 길이입니다.
data-m-alignleft, center, right 정렬입니다.
data-m-itemsetSelectbox·Combobox 셀의 목록입니다.
data-m-cdfield, data-m-nmfieldGrid 목록 항목의 코드·라벨 키입니다. 기본값은 code·codeNm입니다.
data-m-parentcol, data-m-parentkey같은 행 안의 부모 컬럼과 연결하여 단계형 Selectbox를 구성합니다.
data-m-onselectchangedSelectbox·Combobox 셀의 값 변경 이벤트입니다.
data-m-truevalue, data-m-falsevalue체크박스 셀의 체크·해제 저장값입니다.
data-m-btnlabel버튼 셀에 표시할 라벨입니다.
data-m-popupurl, data-m-popupdata팝업 셀에서 호출할 URL과 전달 데이터입니다.
data-m-callfunction셀 동작 시 호출할 화면 함수입니다.
data-m-calcsum, count, avg, min, max 집계 연산입니다.
data-m-colmerge, data-m-colmergealign연속 같은 값의 세로 병합과 병합 셀의 세로 정렬을 지정합니다.

Grid 이벤트

이벤트호출 시점
data-m-onrowselected행 선택 후 Grid, 실제 행 인덱스, 셀 정보와 인스턴스를 전달합니다.
data-m-onbeforeclick클릭에 따른 데이터 반영 전 호출합니다. false 또는 Promise로 후속 처리를 제어할 수 있습니다.
data-m-onafterclick클릭에 따른 데이터 반영 후 호출합니다.
data-m-ondblclick행 더블클릭 시 행·컬럼 정보를 전달합니다.
data-m-onselectchangedSelectbox·Combobox 셀값 변경 시 이전·새 값과 라벨을 전달합니다.
data-m-onscrollend무한스크롤에서 마지막 위치에 도달했을 때 호출합니다.
data-m-onpageclick번호 페이징의 페이지 선택 시 호출합니다.

Grid 주요 메서드

분류메서드설명
렌더drawGrid(list), draw(list,response), redrawGrid()목록을 렌더링하거나 현재 목록을 다시 그립니다.
행addRow(), removeRow(), restoreRow()신규행 추가, 삭제 상태 처리, 원본값 복구를 수행합니다.
선택setRowSelect(), clearSelect(), getSelectedRowIndex(), getSelectedRowJSON()선택 상태와 선택행 데이터를 관리합니다.
셀getCellData(), getCellOriData(), setCellData(), setFocus()현재값·원본값을 읽고 값을 변경하거나 포커스를 이동합니다.
변경행getModifiedJSON(), getCreateJSON(), getUpdateJSON(), getDeleteJSON()C/U/D 전체 또는 상태별 행을 추출합니다.
검증validate()필수 셀을 검사하고 실패 위치로 이동합니다.
목록setCellList()Selectbox·Combobox 컬럼의 원본 목록과 선택 옵션을 설정합니다.
페이징getCurrentPage(), setTotalCnt(), pagingFirst/Prev/Next/Last()현재 페이지, 총건수와 페이지 이동을 제어합니다.
필터doFilter(), filterRemoveAll()필터 적용과 전체 해제를 수행합니다.
툴바getToolbarObj(), getBtn(), clickBtn()사용자 도구와 기본 버튼에 접근합니다.

집계 예

<div data-m-type="grid" id="grd_sales"
     data-m-subtotal="REGION_NM"
     data-m-total="top"
     data-m-subtotallabel="소계"
     data-m-totallabel="총계">
  ...
  <div data-m-cell="td" id="SALE_QTY"
       data-m-celltype="input" data-m-readonly="true"
       data-m-displayfunction="moca.$g.comma"
       data-m-calc="sum"></div>
</div>

D11-2. ButtonGroup — Form 상태 기반 버튼

속성설명
data-m-form연결할 Form ID입니다.
data-m-buttons라벨|후속함수 형식의 버튼 목록입니다. 수정·취소처럼 공통처리만 필요한 버튼은 함수명을 생략할 수 있습니다.
data-m-titleR/U/C 상태에 따라 문구를 자동 변경할 제목 요소 ID입니다.

applyStatus()는 Form 상태를 다시 읽어 버튼과 제목을 갱신하고, getButton(label)은 특정 버튼 엘리먼트를 반환합니다.

<div data-m-type="buttonGroup" id="btg_detail"
     data-m-form="fom_detail" data-m-title="detailTitle"
     data-m-buttons="신규|$p.fn_new,수정,저장|$p.fn_save,취소,삭제|$p.fn_delete"></div>
상세 Form 위에 신규·수정·삭제 버튼이 표시된 ButtonGroup 화면
그림 D11-2. ButtonGroup은 연결된 Form 상태에 맞춰 신규·수정·저장·취소·삭제 버튼과 상세 제목을 자동 전환합니다.

D11-3. FileUpload — 첨부파일 목록과 저장

속성·이벤트설명
data-m-label첨부영역 제목입니다.
data-m-uploadurl해당 화면에서 사용할 업로드 팝업 경로입니다. 프로젝트 공통 설정이 있으면 생략합니다.
data-m-selectquery, data-m-insertquery, data-m-updatequery연동 어댑터가 사용하는 파일 조회·신규·설명수정 식별자입니다.
data-m-autoheight첨부 개수에 맞춰 높이를 자동 조절할지 지정합니다.
data-m-ondblclick파일 행을 더블클릭했을 때 호출할 함수입니다.
메서드설명
load(contentId)업무 콘텐츠 ID로 파일목록을 조회해 표시합니다.
setData(files, contentId)이미 조회한 파일목록을 직접 설정합니다.
save(contentId)설명 변경과 신규 파일을 저장하며 Promise를 반환합니다.
setEditable(bool)업로드 가능 상태와 버튼 노출을 변경합니다.
openUploadPopup()업로드 팝업을 엽니다.
reset(), getList()초기화하거나 현재 첨부목록을 반환합니다.
FileUpload 파일추가 버튼과 드래그앤드롭 영역이 표시된 업로드 팝업
그림 D11-3. 업로드 팝업에서 파일 선택과 드래그앤드롭을 동일한 흐름으로 처리합니다.

D11-4. FloatingButton — 화면 위에 떠 있는 액션 버튼

FloatingButton은 화면 위에 떠 있는 원형·알약형 액션 버튼(FAB)입니다. 기본은 우측 하단 고정이며, 라벨을 지정하면 아이콘 옆에 텍스트가 붙는 알약형이 됩니다. 버튼을 길게 누르면 드래그 모드로 전환되어 원하는 위치로 옮길 수 있고, 짧게 누르면 그대로 클릭으로 동작합니다. ButtonGroup이 모바일 목록 위에 자동으로 만드는 신규 버튼과 레이아웃 골격 미리보기 버튼도 이 컴포넌트로 렌더링됩니다.

속성설명
data-m-label아이콘 옆 텍스트입니다. 지정하면 알약형, 생략하면 원형이 되며 접근성 이름(aria-label)으로도 사용합니다. 라벨을 생략한 경우 마크업에 직접 지정한 aria-label은 보존됩니다.
data-m-icon아이콘 세 가지 형태를 지원합니다 — 내장 plus(기본), 이미지 파일 경로, 이모지 등 글리프 문자열.
data-m-iconmode경로 아이콘의 렌더 방식입니다. 기본 img는 파일 원색으로 그리고, mask를 지정하면 현재 글자색으로 채워 테마·상태 색을 자동으로 따라갑니다.
data-m-bgcolor, data-m-color배경과 아이콘·글자 색입니다. 기본은 테마 변수라 테마를 자동으로 따릅니다.
data-m-position초기 모서리 위치입니다 — rb(우하단, 기본)·lb·rt·lt.
data-m-draggablefalse로 지정하면 길게 눌러 이동하는 기능을 끕니다. 드래그로 옮긴 위치는 화면이 유지되는 동안만 보존됩니다.
data-m-onclick클릭 시 호출할 화면 함수입니다. 드래그로 이동한 직후의 클릭은 호출되지 않습니다.

show()·hide() 메서드로 표시 여부를 제어합니다.

<div data-m-type="floatingButton" id="fab_new" data-m-label="신규"
     data-m-icon="plus" data-m-onclick="$p.fn_new"></div>

<!-- 파일 아이콘 + 테마 색 자동 추종 -->
<div data-m-type="floatingButton" id="fab_search" aria-label="일정 찾기"
     data-m-icon="/vendor/moca/images/icon_search.svg" data-m-iconmode="mask"
     data-m-onclick="$p.fn_searchOpen"></div>

D12.시각화·계층 컴포넌트

날짜·일정·계층·대시보드·차트는 복잡한 렌더링을 컴포넌트가 담당하도록 데이터와 표시 옵션을 분리합니다.

D12-1. Calendar — 붙박이 날짜 선택

속성설명
data-m-datetype일·월·연 등 선택 단위와 값 자릿수를 정합니다.
data-m-value, data-m-startym선택값과 최초 표시 연월입니다.
data-m-header, data-m-todaybutton내부 이동 헤더와 오늘 버튼의 표시 여부입니다.
data-m-weekendoff토·일을 비영업일 형태로 표시합니다.
data-m-legend오늘·선택·공휴일·비영업일 범례를 표시합니다.
data-m-datemin, data-m-datemax선택 가능한 날짜 범위입니다.
data-m-readonly, data-m-ref선택 잠금과 Form 데이터 연결입니다.
data-m-onselect사용자가 값을 확정하면 fn(comp,value,view)로 호출됩니다.
data-m-onviewchange표시 월·연·연대가 바뀔 때 fn(comp,ym,view)로 호출됩니다.
메서드설명
getValue(), setValue(), clear()선택값을 읽고 설정하거나 해제합니다.
setData({dayInfo})날짜별 공휴일·비영업일·뱃지·추가 class를 설정합니다.
setDateRange(), getDateRange()선택범위를 동적으로 변경하거나 조회합니다.
getDayInfo(ymd)특정 날짜의 업무 표시 데이터를 반환합니다.
getViewYm(), setViewYm()현재 표시 연월을 읽고 이동합니다.
today(), next(), prev()오늘·다음·이전 기간으로 이동합니다.
refresh(), setReadOnly()다시 렌더링하거나 선택을 잠급니다.
공휴일·비영업일·범례와 선택 날짜가 표시된 Calendar 컴포넌트 화면
그림 D12-1. Calendar는 화면에 펼쳐진 달력에서 날짜를 고르고 공휴일·비영업일과 선택 상태를 함께 표시합니다.

D12-2. ScheduleCalendar — 월간 일정

속성·이벤트설명
data-m-startym최초 표시 월입니다.
data-m-header이전·연월·다음·오늘 헤더를 표시할지 지정합니다.
data-m-dayrenderer날짜 칸에 추가 HTML을 넣는 렌더러 함수입니다.
data-m-todayflag오늘 칸에 TODAY 깃발을 표시합니다.
data-m-menubutton, data-m-onmenuclick헤더의 메뉴 버튼과 클릭 이벤트입니다.
data-m-onmonthchange스와이프·버튼·API로 월이 바뀔 때 호출됩니다.
data-m-ondayclick일 칸 클릭 시 날짜 객체를 전달합니다.

setData({schedules,dayInfo,hideOutside})로 일정과 날짜 메타를 그립니다. getDayItems(), getDayInfo(), getYm(), setYm(), today(), next(), prev(), refresh(), setDayRenderer()를 제공합니다.

$p.get('sch_plan').setData({
  schedules: [
    { start:'20260810', end:'20260812', title:'제품 심사', crucial:true },
    { start:'20260815', title:'결과 정리', done:true }
  ],
  dayInfo: {
    '20260815': { holi:'광복절' }
  }
});
월간 일정, 기간 일정, 완료 상태와 휴일이 표시된 ScheduleCalendar 화면
그림 D12-2. ScheduleCalendar는 한 달의 단일·기간 일정과 상태·휴일 정보를 날짜 칸에 연속해서 표시합니다.

D12-3. Treeview — 일반 계층

전체 노드를 한 번에 렌더링해도 부담이 없는 메뉴·조직·분류 데이터에 사용합니다.

메서드설명
setData(data)노드 배열을 설정하고 렌더링합니다.
getData()현재 노드 데이터를 반환합니다.
setOnSelect(fn)노드 선택 콜백을 등록합니다.
selectById(id)특정 노드를 선택합니다.
조직 Treeview의 펼친 노드와 선택한 직원 상세정보 화면
그림 D12-3. Treeview는 전체 계층을 렌더링하고 노드 펼침·선택 결과를 상세 영역과 연동합니다.

D12-4. VirtualTree — 대용량 계층

속성설명
data-m-rowheight스크롤 위치 계산에 사용하는 고정 행 높이입니다. CSS 행 높이와 일치해야 합니다.
data-m-indent깊이 한 단계의 들여쓰기 폭입니다.
data-m-guideline깊이 연결선 표시 여부입니다.
data-m-defaultexpandall, none 또는 숫자 깊이로 최초 펼침 범위를 지정합니다.
data-m-onselect노드 선택 시 fn(node,comp)로 호출됩니다.

setData(), getData(), getSelectedNode(), selectById(), scrollToId(), expand/collapse/toggle(), expandAll/collapseAll(), getVisibleCount(), getTotalCount(), getRenderedCount(), refresh(), destroy()를 제공합니다.

가상화 확인 — 전체 노드가 10,000개여도 getRenderedCount()는 현재 보이는 영역과 여유분만 반환해야 정상입니다.
VirtualTree에서 선택된 노드와 상세 정보, 렌더링 행 수를 보여주는 확대 화면
그림 D12-4. 10,010개 노드 중 화면에는 28행만 렌더링하면서 선택 결과를 상세 영역과 연동합니다.

D12-5. Widget — 개인화 대시보드

속성설명
data-m-cols대시보드의 전체 컬럼 수입니다.
data-m-pageid사용자 배치를 저장할 화면 식별자입니다.
data-m-editbutton, data-m-editgroup조회상태의 편집 버튼과 편집상태의 추가·저장·취소 버튼그룹 ID입니다.
data-m-widget-definition위젯 정의 화면의 루트 표식입니다.
data-m-widgetid레지스트리에서 사용할 위젯 식별자입니다.
data-m-defaultcols, data-m-defaultrows위젯의 기본 너비와 높이입니다.
data-m-addicon, data-m-addtype추가 패널에 표시할 아이콘과 분류입니다.
data-m-showheader공통 카드 제목 헤더 표시 여부입니다.
data-m-defaultvisible저장 배치가 없을 때 기본으로 포함할지 지정합니다.
메서드 분류메서드
초기화load(), draw(), setRegistry(), setLayout(), render()
조회getLayout(), refresh(id), showEmpty()
편집startEdit(), saveEdit(), cancelEdit()
추가 패널showAddPanel(), closeAddPanel()
배치 변경addWidget(), removeWidget(), moveWidget(), resizeWidget()
KPI 카드, 달력과 차트 위젯을 배치한 Widget 대시보드
그림 D12-5A. Widget은 KPI·달력·차트 같은 독립 콘텐츠를 저장된 대시보드 배치로 구성합니다.
위젯 이동 손잡이, 크기와 제거 버튼이 표시된 Widget 편집 화면
그림 D12-5B. 편집 상태에서는 위젯의 이동·크기조절·추가·제거 후 저장하거나 취소할 수 있습니다.

D12-6. Echart — 데이터 시각화

속성·메서드설명
data-m-theme적용할 ECharts 테마명입니다.
setValue(option), setData(option)차트 option 전체를 설정하고 필요할 때 인스턴스를 생성합니다.
getValue(), getData()현재 option을 반환합니다.
clear()차트를 비웁니다.
getChart(callback), onReady(callback)준비된 ECharts 인스턴스를 콜백으로 전달합니다.
getChartObj()이미 생성된 인스턴스를 즉시 반환합니다.
resize()즉시 크기 조정이 필요한 경우 수동으로 다시 계산합니다.
destroy()동적으로 제거하기 전에 관찰자와 차트 인스턴스를 해제합니다.
세로·가로 막대, 라인 영역과 누적 막대를 함께 보여주는 Echart 화면
그림 D12-6. Echart 래퍼는 업무 데이터를 막대·라인·영역·누적 차트로 표시하고 화면 크기와 테마 변화에 맞춰 다시 그립니다.
$p.get('cht_sales').setData({
  tooltip: { trigger:'axis' },
  xAxis: { type:'category', data:['1월','2월','3월'] },
  yAxis: { type:'value' },
  series: [{ name:'매출', type:'bar', data:[120,180,150] }]
});

D13.문서·파일 뷰어 컴포넌트

뷰어 컴포넌트는 업무 파일을 내려받지 않고 화면 안에서 바로 보여줍니다. 다른 컴포넌트와 같이 div에 타입을 선언하면 장착이 끝나며, 형식별로 필요한 렌더링 라이브러리는 엔진이 해당 뷰어를 처음 사용할 때 자동으로 로드하므로 화면에 <script src>를 추가하지 않습니다.

타입담당 형식특징
pdfviewerPDF쪽 이동·확대·인쇄·다운로드, 본문 텍스트 선택
imageviewerPNG·JPG·GIF·SVG·WebP·BMP확대·회전·반전·슬라이드쇼, 단일·갤러리 모드
textviewerTXT·LOG·CSV·JSON·XML·HTML대용량도 보이는 구간만 그려 빠름. 찾기, 인코딩 자동 판별(EUC-KR 포함), XML·HTML 접기 트리
excelviewerXLSX·XLS시트를 뷰어 전용 경량 그리드로 렌더 — 시트 탭·정렬·필터 제공
docviewerDOCX쪽·표·머리말/꼬리말을 원본 레이아웃대로
pptviewerPPTX텍스트·표·기본 도형 — 내용 확인용(애니메이션·SmartArt 재현 안 됨)
hwpviewerHWPX·HWPHWPX는 직접 렌더(텍스트 선택 가능), 구형 HWP는 내용 확인용. 형식은 파일 내용으로 자동 판별
zipviewerZIP압축을 풀지 않고 트리로 탐색, 항목별 미리보기는 그 형식의 담당 뷰어로 연결

D13-1. 장착 방법

가장 기본은 화면 레이아웃 칸에 직접 배치하는 것입니다. 뷰어는 부모가 준 높이를 100% 채우므로 높이가 관리되는 레이아웃 칸에 두면 별도 크기 계산이 필요 없습니다.

<div data-m-layout-part="1" data-m-type="pdfviewer" id="pdv_main"
     data-m-src="/files/manual.pdf"></div>

문서를 실행 중에 바꿀 때는 load()를 사용합니다. 조회 결과의 파일 경로를 그대로 전달합니다.

$p.get('pdv_main').load('/common/download.do?fileId=' + row.FILE_ID);

첨부 목록처럼 여러 형식의 파일을 다루는 화면은 형식 판별과 팝업 구성을 직접 만들지 않고 공용 API 한 줄로 엽니다. 확장자에 맞는 뷰어를 골라 레이어 팝업으로 띄우며, 소스·설정·전문처럼 담당 뷰어가 따로 없는 텍스트성 파일과 미지의 확장자는 텍스트 뷰어로 열립니다 — 내용이 바이너리로 판별되면 뷰어가 안내와 함께 스스로 내려받기로 전환합니다. 확장자만으로 바이너리가 확실한 파일(실행 파일·동영상 등)만 false를 반환하므로 그때 내려받기로 폴백합니다.

if (!moca.$g.openFileViewer({ url: _url, name: row.FILE_NAME })) {
  $p.fn_download(row);   // 확장자만으로 바이너리가 확실한 형식(실행 파일 등)만 여기로 온다
}

모달 대신 화면 안에서 열 수도 있습니다 — target에 영역(요소 또는 id)을 주면 확장자에 맞는 뷰어가 그 자리에 열리고, 다른 파일을 다시 열면 이전 뷰어를 정리한 뒤 교체합니다. 목록 옆 미리보기 패널처럼 행을 옮길 때마다 바로바로 보여주는 화면에 적합하며, 영역은 레이아웃 칸처럼 높이가 관리되는 자리에 둡니다.

moca.$g.openFileViewer({ url: _url, name: row.FILE_NAME, target: 'pnl_preview' });

D13-2. 공통 규약

구분내용
문서 지정data-m-src 선언 또는 load(url)·setValue(url). 파일은 같은 출처(same-origin)여야 하며 외부 파일은 서버 프록시를 경유합니다.
이벤트data-m-onloaded(로드 완료), data-m-onerror(실패 — 형식 오류·경로 오류를 화면이 안내)
툴바기본 표시. data-m-toolbar="false"로 감출 수 있으며 확대·내려받기·도움말은 툴바가 담당합니다.
도움말 연결data-m-help에 화면 설명 요소를 지정하면 뷰어의 [?] 도움말 모달에 화면 설명과 조작법이 함께 표시됩니다.
공통 메서드load()·reload()·clear()·download()·showHelp()·destroy()

D13-3. 형식별 대표 옵션

뷰어대표 속성·메서드
pdfviewerdata-m-page(시작 쪽), goPage()·fitWidth()·print()
textviewerdata-m-mode(auto·text·xml), data-m-encoding(자동·UTF-8·EUC-KR), find()·goLine()
excelviewerdata-m-sheet(시작 시트), data-m-maxrows(대용량 상한), getRows()·setSheet()
docviewerdata-m-breakpages(쪽 나눔), goPage()·fitWidth()
pptviewerdata-m-notice(재현 한계 안내 표시), goSlide()
imageviewerdata-m-mode(단일·갤러리), add()·rotate()·play()
zipviewergetFileList()·preview()·downloadEntry()

속성·이벤트·메서드의 전체 규격은 MOCA API 문서의 각 뷰어 항목에서 확인합니다.

확인 — 원본과 똑같은 재현이 필요한 문서는 PDF로 받아 pdfviewer로 여는 구성이 가장 정확합니다. PPTX·구형 HWP 뷰어는 내용 확인용이라는 한계를 화면에서 안내합니다.

D14.표준 화면 패턴

표준 화면 패턴은 화면마다 조회·선택·편집 상태를 새로 구현하지 않기 위한 조합 규칙입니다. 먼저 사용자가 처리할 데이터 단위와 편집 위치를 결정한 뒤 가장 가까운 패턴을 선택합니다.

패턴구성선택 기준핵심 상태
조회·목록검색 Form + Grid조건으로 목록을 탐색하고 읽는 화면검색조건, 선택행, 페이지
배치편집편집 Grid + Grid 도구영역행 데이터만으로 등록·수정·삭제가 끝나는 화면C/U/D 행상태, 변경분
목록·상세Grid + Form + ButtonGroup선택행의 상세정보나 하위 데이터가 있는 화면읽기·편집, 선택행, 원본값
팝업 검색검색 Form + 조회 Grid + 선택·닫기원래 화면에 한 건 또는 여러 건의 결과를 반환전달조건, 반환값, 취소
대시보드Widget + KPI·Echart·목록여러 현황을 한 화면에서 요약배치, 표시여부, 새로고침

D14-1. 조회·목록

검색조건은 Form으로 묶고 결과는 Grid에 전달합니다. 검색 버튼과 Enter 입력은 같은 조회 함수를 호출하게 하여 검색 경로가 달라도 결과와 진행 상태가 같도록 구성합니다.

$p.fn_search = async function(page) {
  var _form = $p.get('fom_search');
  var _grid = $p.get('grd_main');
  var _res = await moca.$t.exe({
    url: '/api/items',
    data: {
      page: page || 1,
      keyword: $p.get('ipt_keyword').getValue(),
      useYn: $p.get('cmb_useYn').getValue()
    },
    progressMsg: '조회 중입니다.'
  });

  _grid.draw(_res.items || [], _res);
};
검색조건 유지 — 상세 화면이나 팝업에서 돌아왔을 때 조건을 무조건 초기화하지 않습니다. 다시 보여질 때 갱신이 필요하면 $p.onactivate에서 현재 조건으로 조회합니다.

D14-2. Grid 배치편집

한 행이 하나의 처리 단위이고 별도 상세 Form이 필요 없다면 Grid 안에서 편집합니다. Grid가 관리하는 C(신규)·U(수정)·D(삭제) 상태를 저장 요청의 변경분으로 사용합니다.

$p.fn_add = function() {
  $p.get('grd_main').addRow(0, { USE_YN:'Y' });
};

$p.fn_save = async function() {
  var _grid = $p.get('grd_main');
  if (!_grid.validate()) return;

  var _changes = _grid.getModifiedJSON();
  if (!_changes.length) {
    moca.$g.alert('변경된 내용이 없습니다.');
    return;
  }
  await moca.$t.exe({ url:'/api/items/batch', data:{ items:_changes } });
  await $p.fn_search();
};

행 삭제는 DOM을 직접 제거하지 않고 removeRow()를 사용합니다. 신규행은 목록에서 제거되고, 기존행은 삭제 상태로 관리되어 저장 대상에 포함됩니다.

D14-3. 목록·상세 자동 연동

Form의 참조 Grid와 ButtonGroup을 연결하면 행 선택에 따른 폼 채움, 읽기·편집 상태, 버튼 전환과 취소 복구를 공통 컴포넌트가 처리합니다.

<div data-m-type="grid" id="grd_main" data-m-editguard="true">...</div>

<div data-m-type="form" id="fom_detail" data-m-variant="form"
     data-m-refgrid="grd_main" data-m-readonly="true">...</div>

<div data-m-type="buttonGroup" id="btg_detail"
     data-m-form="fom_detail"
     data-m-buttons="신규|$p.fn_new,수정,저장|$p.fn_save,취소,삭제|$p.fn_delete"></div>
사용자 동작Form 상태권장 처리
행 선택선택행 값 표시, 읽기참조 Grid 자동 연동을 사용합니다.
신규빈값 또는 기본값, 편집reset() 후 기본값을 설정합니다.
수정현재값 유지, 편집읽기 전용을 해제하고 첫 입력에 포커스를 둡니다.
취소원본값 복구, 읽기직접 값을 다시 조립하지 않고 Form의 취소 흐름을 사용합니다.
저장·삭제처리 완료 후 읽기목록을 갱신하고 처리한 행을 다시 선택합니다.

D14-4. 팝업 검색

팝업은 독립된 MOCA 화면입니다. 여는 화면은 초기 조건을 data로 보내고, 팝업은 $p.getParameter()로 읽습니다. 사용자가 확정한 경우에만 $p.close(result)로 값을 반환합니다.

// 여는 화면
$p.openPop({
  url: '/ui/POP_ITEM.html',
  title: '품목 검색',
  width: '720px',
  data: { keyword: $p.get('ipt_itemNm').getValue() },
  callback: function(row) {
    $p.get('ipt_itemCd').setValue(row.ITEM_CD);
    $p.get('ipt_itemNm').setValue(row.ITEM_NM);
  }
});

// 팝업 화면
$p.onpageload = function() {
  var _param = $p.getParameter();
  $p.get('ipt_keyword').setValue(_param.keyword || '');
  $p.fn_search();
};
$p.fn_select = function() {
  var _row = $p.get('grd_result').getSelectedRowJSON();
  if (_row) $p.close(_row);
};
취소와 확정 구분 — 닫기·취소는 $p.close(), 선택 완료는 $p.close(value)를 사용합니다. 취소 시 여는 화면의 callback은 호출되지 않습니다.

D14-5. 대시보드

Widget은 배치와 편집 상태를 관리하고, 각 카드의 실제 내용은 독립 Frame 화면으로 구성합니다. 목록·KPI·차트는 자신의 조회와 렌더링만 책임지며, 크기가 바뀔 때 필요한 처리는 생명주기 훅에 둡니다.

$p.onwidgetrefresh = function(ctx) {
  $p.fn_loadWidget(ctx.id);
};

$p.onwidgetresize = function() {
  var _chart = $p.get('cht_summary');
  if (_chart) _chart.resize();
};

$p.onwidgetdestroy = function() {
  clearInterval($p.refreshTimer);
};

패턴 선택 체크

  1. 사용자가 저장하는 최소 데이터 단위가 행인지 상세 객체인지 정합니다.
  2. 읽기와 편집 상태가 분리되어야 하면 Form과 ButtonGroup 조합을 사용합니다.
  3. 다른 화면에 값을 돌려주어야 하면 팝업 검색 패턴을 사용합니다.
  4. 크기 변경과 부분 새로고침이 독립적이어야 하면 Widget 카드로 분리합니다.
  5. 직접 상태 전환 코드를 만들기 전에 컴포넌트의 참조·검증·변경분 API를 확인합니다.

D15.공개 API와 데이터 연동

화면 코드는 전역 DOM 탐색보다 현재 화면 스코프의 공개 API를 사용합니다. 컴포넌트 접근은 $p, 공통 표현과 검증은 moca.$g, 날짜는 moca.$g.date, 서버 통신은 moca.$t가 담당합니다.

API 영역역할
$p현재 화면의 컴포넌트, 파라미터, 부모화면, 팝업·창, 화면 생명주기
moca.$g메시지, 값 변환, 포맷, 보안 문자열 처리, 공통 화면 유틸리티
moca.$g.date오늘·현재시각, 날짜 계산·비교·포맷, 달력 데이터
moca.$tJSON 조회·저장·업로드와 진행 상태, Promise 기반 비동기 처리
컴포넌트 인스턴스$p.get('id')로 얻는 각 컴포넌트의 값·목록·상태·렌더링 API

D15-1. $p — 현재 화면의 경계

호출용도주의사항
$p.get(id)현재 화면의 컴포넌트 또는 요소 조회같은 ID가 다른 Frame에 있어도 현재 화면 안에서만 찾습니다.
$p.findAll(selector)현재 화면 안의 여러 요소 조회공개 컴포넌트 API로 해결할 수 없는 단순 표시 제어에 사용합니다.
$p.getParameter()Frame·탭·팝업으로 전달된 초기값 조회값이 없으면 빈 객체이므로 개별 키를 확인합니다.
$p.getParent()부모 Frame 요소 조회부모 기능은 getScope()를 거쳐 호출합니다.
$p.openPop(option)레이어 팝업 열기결과는 callback으로 받고 팝업은 $p.close(value)로 닫습니다.
$p.openWin(option)독립 브라우저 창 열기원래 화면을 계속 보아야 하는 업무에 제한적으로 사용합니다.
$p.code(config, callback)공통 코드 목록 바인딩Selectbox·Combobox·Grid 코드셀을 한 번에 설정할 수 있습니다. 옵션은 공통코드 그룹 { code } 또는 업무 쿼리 { queryId, body }이고, allOption·selectedValue·cdField·nmField를 더할 수 있습니다. 그 밖의 키는 무시되어 목록이 비게 됩니다.
$p.onpageload = function() {
  var _param = $p.getParameter();
  $p.get('ipt_keyword').setValue(_param.keyword || '');

  $p.code({
    'cmb_useYn': { code: 'USE_YN' },
    'cmb_type':  { queryId: 'selectItemTypeCombo', allOption: { value: '', label: '전체' } }
  }, $p.fn_search);
};

D15-2. moca.$g — 메시지·값·표시 유틸리티

분류대표 API적용 예
사용자 메시지alert, error, confirm완료·실패 안내와 삭제 확인
값 판정isEmpty, isNumeric, nul, getNumber입력값 검사와 안전한 기본값
표시 변환comma, phoneWithDashFormatter, percentFormatterdata-m-displayfunction에 연결
화면·환경getUserInfo, isMobileView현재 사용자 표시와 폭 기반 UI 분기
안전한 문자열escapeHtml, escapeAttr, sanitizeHtml문자·속성·제한된 HTML 문맥별 처리
$p.fn_delete = function() {
  moca.$g.confirm('선택한 항목을 삭제하시겠습니까?', async function() {
    try {
      await moca.$t.delete({
        url: '/api/items',
        data: { list: $p.get('grd_main').getSelectedRowJSON() }
      });
      await $p.fn_search();
    } catch (e) {
      moca.$g.error('삭제 처리 중 오류가 발생했습니다.');
    }
  });
};

D15-3. moca.$g.date — 숫자 문자열 날짜 규약

날짜 값은 yyyyMMdd, 연월은 yyyyMM, 일시는 yyyyMMddHHmmss 숫자 문자열을 사용합니다. 화면 표시 형식은 값 자체와 분리하고 format() 또는 컴포넌트 표시 속성으로 지정합니다.

목적API예
오늘·현재시각getToday([pattern])getToday() → 20260804
표시 형식format(value, pattern)format('20260804','yyyy-MM-dd')
일·월 계산addDay, addMonth, addYm일주일 전, 다음달 말일 보정
기간 계산diffDays, diffMonths두 일자 간 일수와 두 연월 간 개월 수
기간 경계getFirstDayOfMonth, getLastDayOfMonth, getQuarterTerm월간·분기 조회조건 생성
검증isDate, isTime, inRange실재 일자와 선택 가능 범위 확인
var _today = moca.$g.date.getToday();
$p.get('cal_from').setValue(moca.$g.date.addDay(_today, -7));
$p.get('cal_to').setValue(_today);

var _label = moca.$g.date.format(_today, 'yyyy년 M월 d일 (E)');

D15-4. moca.$t — 공통 통신

메서드용도주요 입력·반환
exe(options)일반 조회·저장url, data, callback, progress, Promise
insert(options)단건 등록data.list에 생성 상태를 부여하고 완료 메시지를 처리합니다.
update(options)단건 수정data.list에 수정 상태를 부여합니다.
delete(options)단건 삭제data.list에 삭제 상태를 부여합니다.
upload(options)파일 업로드formData를 전달하고 공통 진행·오류 처리를 사용합니다.
getResList(res, ids)다중 목록 응답 추출조회 식별자 목록에 해당하는 배열을 반환합니다.
getResOne(res, key)단건 응답 추출지정 키 또는 기본 단건 데이터를 반환합니다.
$p.fn_load = async function() {
  var _result = await moca.$t.exe({
    url: '/api/items',
    data: { keyword: $p.get('ipt_keyword').getValue() },
    progressMsg: '조회 중입니다.'
  });
  $p.get('grd_main').drawGrid(_result.items || []);
};

callback과 await를 모두 지원하지만 한 함수 안에서는 한 방식을 선택합니다. 여러 요청을 순서대로 처리하거나 오류를 한 곳에서 다룰 때는 async/await가 읽기 쉽습니다.

D15-5. 데이터 계약과 오류 처리

계약 항목화면에서 정할 내용
요청필드명, 자료형, 필수값, 날짜 형식, 페이징 번호를 명확히 합니다.
성공 응답목록 배열, 단건 객체, 총건수, 업무 메시지의 위치를 고정합니다.
빈 결과목록은 빈 배열, 단건은 빈 객체 또는 null 중 하나로 일관되게 처리합니다.
검증 오류사용자가 수정할 수 있는 항목과 메시지를 구분하여 표시합니다.
인증·권한 오류공통 흐름에 맡기고 화면이 임의로 성공 상태를 만들지 않습니다.
재시도중복 저장 가능성이 있는 요청은 자동 재시도하지 않습니다.

연동 원칙

D16.설정·테마·접근성

프로젝트 공통값은 화면마다 반복하지 않고 MOCA 설정에 둡니다. 개별 화면 속성은 해당 화면만 달라야 할 때 사용하며, 테마와 접근성은 기능 구현이 끝난 뒤가 아니라 컴포넌트 선택과 화면 구조 단계에서 함께 결정합니다.

프로젝트 설정

설정용도개별 화면 재정의
mocaHome, vendorHomeMOCA 엔진과 외부 라이브러리의 기준경로하지 않음
componentSizeInput·Selectbox 등 컴포넌트 종류별 공통 폭요소의 width 속성·스타일
calendarDateRange프로젝트 공통 최소·최대 일자data-m-datemin, data-m-datemax
fileUploadPopup프로젝트 공통 파일 선택·업로드 화면data-m-uploadurl
loginUrl인증 만료 시 이동할 로그인 화면공통 처리 권장
idleLock무활동 시간이 지난 뒤 화면 잠금공통 처리 권장
winShell$p.openWin()이 사용할 창 컨테이너호출 옵션의 화면 URL
var mconfig = {
  mocaHome: '/vendor/moca',
  vendorHome: '/vendor',
  componentSize: {
    input: '180px',
    selectbox: '180px',
    inputCalendar: '150px'
  },
  calendarDateRange: { min:'20000101', max:'20991231' },
  loginUrl: '/login.html'
};
설정 우선순위 — 달력 범위와 파일 업로드 화면처럼 공통값과 화면 속성이 모두 있는 기능은 엔진 기본값 → 프로젝트 설정 → 개별 화면 속성 순으로 구체화됩니다.

테마

색상은 의미 기반 테마 변수로 정의하고 컴포넌트는 동일한 변수를 사용합니다. 새 화면은 다크·라이트·고대비에서 텍스트, 경계, 선택, 오류 상태가 구분되는지 확인합니다.

의미확인 대상판정 기준
기본 본문페이지·Form·Grid의 문자와 배경장시간 읽어도 구분되고 비활성 문자와 혼동되지 않아야 합니다.
강조·선택선택행, 활성 탭, 주요 버튼색상뿐 아니라 테두리·굵기·아이콘으로도 상태가 드러나야 합니다.
오류·경고필수값, 유효성 오류, 경고 메시지성공·정보 상태와 명확히 구분되어야 합니다.
포커스입력, 버튼, Grid 셀, 팝업배경색이 달라도 키보드 포커스 윤곽이 보여야 합니다.
시각화Echart 범례와 계열색고대비와 색각 차이에서도 계열을 구별할 수 있어야 합니다.

반응형 화면

CSS와 JavaScript가 서로 다른 폭 기준을 사용하면 같은 화면에서 표시와 동작이 어긋납니다. 코드에서 폭 기반 동작을 결정할 때는 moca.$g.isMobileView(element)를 사용합니다.

접근성

검사 항목구현 기준
키보드 이동Tab 순서가 화면의 읽기 순서와 일치하고, 주요 기능을 마우스 없이 실행할 수 있어야 합니다.
포커스 이동팝업이 열리면 팝업 안으로, 닫히면 열었던 요소로 포커스가 돌아와야 합니다.
이름과 설명아이콘만 있는 버튼에는 기능을 알 수 있는 이름을 제공하고 입력에는 연결된 라벨을 둡니다.
오류 안내오류가 난 항목을 문자로 설명하고 확인 후 해당 입력으로 포커스를 이동합니다.
상태 표현선택·필수·오류·비활성 상태를 색상 하나에만 의존하지 않습니다.
명도대비본문, 보조문자, 경계선, 포커스 윤곽이 각 테마에서 식별되는지 확인합니다.
확대·축소브라우저 확대 시 문자가 잘리거나 주요 버튼이 화면 밖으로 사라지지 않아야 합니다.

화면 완료 전 조합 검사

  1. 프로젝트 공통값을 화면마다 중복 선언하지 않았는지 확인합니다.
  2. 넓은 화면과 좁은 화면에서 정보 우선순위와 동작이 유지되는지 확인합니다.
  3. 라이트·다크·고대비 테마에서 선택·오류·포커스를 구분합니다.
  4. 키보드만으로 검색, 행 선택, 편집, 저장, 팝업 닫기를 수행합니다.

D17.프론트엔드 보안과 서버 연동 계약

MOCA는 화면 렌더링과 공통 통신에서 반복되는 보안 처리를 제공합니다. 서버는 인증·권한·토큰 검증과 업로드 정책을 반드시 별도로 적용해야 하며, 화면에서 버튼을 숨기는 것만으로 권한을 보장할 수 없습니다.

보안 책임 경계

영역MOCA 화면의 책임서버 연동 계약
출력외부 값을 문맥에 맞게 텍스트·속성·제한된 HTML로 처리저장된 값도 신뢰하지 않고 응답 형식과 자료형을 보장
요청공통 통신을 사용하고 CSRF 토큰 헤더를 전달상태 변경 요청마다 토큰의 유효성과 사용자 세션을 검증
인증만료 응답을 공통 흐름으로 처리하고 로그인 화면으로 이동보호 자원 접근 전 인증 상태를 판정
권한권한에 따라 버튼·메뉴를 표시하여 잘못된 조작을 줄임모든 조회·변경 요청에서 최종 권한을 다시 판정
파일허용 확장자·크기 안내와 선택 단계 검증파일 내용·크기·이름·저장경로를 최종 검증

XSS 무해화

// 일반 텍스트
element.textContent = row.TITLE;

// 제한된 표시 마크업
element.innerHTML = moca.$g.sanitizeHtml(row.CONTENT);

CSRF 연동

구간요구사항
서버사용자 세션과 연결된 CSRF 토큰을 발급하고 상태 변경 요청의 토큰을 검증합니다.
MOCA 통신moca.$t를 사용하면 토큰 헤더를 공통으로 첨부합니다.
직접 통신불가피하게 직접 요청할 때 moca.$g.csrfHeaders()로 헤더를 구성합니다.
// 공통 통신을 사용할 때 토큰 헤더는 자동 적용됩니다.
await moca.$t.exe({
  url: '/api/items',
  data: { item: _item }
});

// 직접 요청이 불가피한 경우에만 헤더를 명시합니다.
await fetch('/api/items', {
  method: 'POST',
  headers: moca.$g.csrfHeaders({ 'Content-Type':'application/json' }),
  body: JSON.stringify({ item:_item })
});

인증과 권한

파일 업로드

민감정보와 오류 메시지

보안 연동 완료 체크

  1. 외부 값이 들어가는 모든 위치를 텍스트·속성·HTML 문맥으로 구분했는가?
  2. 상태를 바꾸는 요청이 공통 통신 또는 CSRF 헤더를 사용하는가?
  3. 화면의 버튼 표시와 별개로 서버가 조회·저장·삭제 권한을 검증하는가?
  4. 인증 만료 시 부분 화면에 오류만 남지 않고 공통 로그인 흐름으로 이동하는가?
  5. 업로드 제한이 화면 안내에만 머물지 않고 서버에서도 검증되는가?
  6. 오류 메시지와 로그에 민감정보가 포함되지 않는가?

D18.문제 해결과 체크리스트

증상부터 코드를 넓게 바꾸기보다 로드 → 스코프 → 선언 → 데이터 → 상태 → 반응형 순서로 범위를 좁힙니다. 같은 ID가 여러 화면에 있을 수 있으므로 오류가 발생한 Frame과 그 화면의 $p를 먼저 확인합니다.

D18-1. 진단 순서

  1. 화면 로드 — HTML과 필요한 리소스 요청이 성공했고 $p.onpageload까지 실행되었는지 확인합니다.
  2. 화면 스코프 — 현재 화면의 $p.get(id)가 기대한 컴포넌트를 반환하는지 확인합니다.
  3. 컴포넌트 선언 — data-m-type, 구조 태그와 연결 ID를 확인합니다.
  4. 입력 데이터 — API 응답의 필드명·자료형·배열 위치가 컴포넌트 계약과 맞는지 확인합니다.
  5. 상태 전환 — 읽기·신규·수정 상태와 선택행, Grid의 C/U/D 상태를 확인합니다.
  6. 폭과 테마 — 넓은 화면에서 정상인 뒤 좁은 화면과 각 테마에서 같은 기능을 확인합니다.

D18-2. 증상별 확인표

증상먼저 확인할 내용관련 절
입력 컴포넌트가 기본 브라우저 모양data-m-type 값의 철자와, 해당 영역이 MOCA 화면으로 정상 로드되었는지 확인합니다.D8, D10
컴포넌트 인스턴스를 찾지 못함ID 오타, 현재 Frame, $p.get(id) 호출 시점을 확인합니다.D4, D5
다른 화면의 같은 ID가 선택됨전역 탐색 대신 현재 화면의 $p.get(id)를 사용하는지 확인합니다.D5
부모 화면 함수 호출 오류$p.getParent().getScope() 경로와 부모 로드 완료 여부를 확인합니다.D5, D6
자식 값을 너무 일찍 읽음자식 Frame의 onpageload 완료 뒤 호출되는 구조인지 확인합니다.D6
Layout 높이가 0이거나 겹침루트·하위 data-m-layout-part와 직계 자식 구조를 확인합니다.D7, D9
좁은 화면에서 상세가 열리지 않음data-m-mobileview="pop", Layout 칸 구조, 상세 표시 트리거를 확인합니다.D7, D16
Grid가 비어 있음응답의 실제 배열, 필드명, drawGrid에 전달한 값을 확인합니다.D11, D15
Grid 수정행이 저장 대상에 없음DOM을 직접 바꾸지 않고 setCellData()로 값을 반영했는지 확인합니다.D11, D14
Form과 Grid 값이 다름data-m-refgrid, 필드의 data-m-ref, 선택행을 확인합니다.D10, D14
Selectbox 라벨이 비거나 코드만 보임목록의 코드·명칭 키와 data-m-valuefield·data-m-labelfield를 확인합니다.D10
달력 입력을 확정할 수 없음값 형식과 data-m-datemin·data-m-datemax 범위를 확인합니다.D10, D15
팝업 callback이 호출되지 않음팝업이 취소 $p.close()가 아니라 $p.close(value)로 닫혔는지 확인합니다.D14, D15
Echart 크기가 맞지 않음부모 Layout 크기 확정 후 렌더되었는지, 필요하면 resize()를 호출했는지 확인합니다.D12
상태 변경 요청이 거부됨공통 통신 사용 여부, 인증 상태와 CSRF 헤더를 확인합니다.D15, D17
자동완성 후보가 없음HTML·JavaScript 파일인지, 상태표시줄에 MOCA 활성 상태가 표시되는지 확인합니다.D3
미리보기와 실행화면이 다름원본 미리보기와 런타임 미리보기의 차이, 프로젝트 설정 로드 여부를 확인합니다.D3, D16

D18-3. 구현 단계별 완료 체크리스트

단계완료 기준
골격Layout의 모든 직계 자식이 칸으로 선언되고 목록·상세·도구영역의 책임이 분리되었습니다.
컴포넌트주요 속성, 이벤트 함수, 컴포넌트 간 연결 ID가 정확합니다.
생명주기초기 조회는 onpageload, 재활성화와 정리는 해당 훅에 배치되었습니다.
데이터요청·응답 필드, 날짜 형식, 빈 결과, 페이징 총건수의 계약이 정해졌습니다.
편집필수값 검증, 신규·수정·삭제 상태, 취소 복구, 중복 저장 방지가 동작합니다.
보안출력 무해화, CSRF, 인증·권한, 업로드 제한의 화면·서버 책임이 확인되었습니다.
사용성좁은 화면, 테마, 키보드, 포커스, 빈 데이터와 오류 상황을 확인했습니다.

최종 확인

  1. 화면 골격을 Layout으로 구성했는가?
  2. 기존 34종 컴포넌트에서 필요한 기능을 먼저 찾았는가?
  3. 함수와 상태를 $p에 두고 공개 API로 접근했는가?
  4. data-m-* 속성을 자동완성 또는 API 문서에서 확인했는가?
  5. 직접 DOM에 외부 값을 넣는 위치를 안전하게 처리했는가?
  6. 넓은 화면과 좁은 화면에서 목록·상세 전환을 확인했는가?
  7. 다크·라이트·고대비에서 텍스트·아이콘·상태가 구분되는가?
  8. 키보드만으로 주요 입력과 버튼에 접근할 수 있는가?
  9. 조회 결과가 0건이거나 요청이 실패해도 화면 상태가 일관되는가?
  10. 팝업 취소, 편집 취소, 탭 전환 뒤 복귀 흐름을 확인했는가?
  11. 콘솔 오류 없이 화면 로드와 주요 사용자 흐름이 끝나는가?
MOCA 사용자 가이드 & 개발자 가이드 · v4.4 · 2026-09-29  |  MOCA API 문서  |  teammoca.co.kr