MOCA 기반 업무 화면을 사용하는 방법과, MOCA Portable 및 MOCA IntelliSense를 활용해 반응형 업무 화면을 개발하는 방법을 설명합니다.
이 가이드는 제품을 사용하는 사람과 화면을 개발하는 사람을 위한 두 개의 독립된 PART로 구성됩니다. 필요한 PART만 읽어도 이해할 수 있으며, 정확한 전체 API 규격은 MOCA API 문서에서 확인할 수 있습니다.
| 문서 | 담당하는 내용 |
|---|---|
| 사용자·개발자 가이드 | 업무 흐름, 선택 기준, 개발 순서, 대표 사용법과 주의사항 |
| MOCA API 문서 | 34종 컴포넌트와 moca.$g·moca.$g.date·moca.$t·$p의 전체 속성·이벤트·메서드 |
MOCA 기반 시스템에서 공통으로 제공하는 조회·입력·저장·탐색 기능을 설명합니다.
MOCA는 업무 시스템의 화면 구성과 조작 방식을 일관되게 제공하는 UI/UX 프레임워크입니다. 적용 시스템마다 메뉴명과 업무 데이터는 다르지만, 조회·그리드·입력·팝업·모바일 조작은 같은 원칙으로 동작합니다.
로그인 후 화면은 일반적으로 다음 영역으로 구성됩니다. 적용 시스템의 업무 특성에 따라 일부 영역은 생략되거나 위치가 달라질 수 있습니다.
| 영역 | 주요 기능 |
|---|---|
| 헤더 | 서비스 정보, 테마 선택, 사용자 메뉴, 로그아웃 |
| 메뉴 | 업무 화면을 계층적으로 탐색하고 열기 |
| 작업영역 | 여러 업무 화면을 탭으로 열고 전환하기 |
| 상태영역 | 조회 건수, 처리시간, 진행 상태 등 확인 |
검색영역에 조건을 입력한 뒤 [조회]를 선택합니다. 입력칸에서 Enter를 눌러 조회할 수도 있습니다.
그리드는 조회 결과를 표시하고 정렬·필터·페이징·엑셀·전체화면 기능을 제공하는 표입니다.
| 기능 | 사용 방법 |
|---|---|
| 행 선택 | 행을 선택하면 연결된 상세정보가 표시됩니다. |
| 정렬 | 컬럼 헤더의 정렬 버튼을 반복 선택하여 오름차순·내림차순·해제 순으로 전환합니다. |
| 필터 | 헤더의 필터 버튼에서 표시할 값을 선택합니다. 필터가 적용된 컬럼은 아이콘으로 구분됩니다. |
| 컬럼 폭 | 헤더 경계를 드래그하여 폭을 조절합니다. |
| 잘린 값 | 셀 위에 포인터를 두면 전체 내용을 확인할 수 있습니다. |
| 페이징 | 목록 아래의 처음·이전·페이지·다음·마지막 버튼으로 이동합니다. |
| 엑셀 | 현재 정렬·필터가 적용된 목록을 내려받습니다. |
| 전체화면 | 그리드만 확장하여 보고 다시 원래 화면으로 돌아옵니다. |
| 행 상세보기 | 툴바의 상세보기 버튼으로 선택한 행을 항목별 상세 화면으로 펼쳐 봅니다. |
컬럼이 많아 가로로 길게 늘어선 행은 상세보기로 한눈에 확인합니다. 행을 선택하고 툴바의 상세보기 버튼을 누르면 그 행의 모든 항목이 「항목명 — 값」 형태로 펼쳐집니다.
편집 가능한 그리드는 셀을 직접 수정하고 변경된 행만 저장할 수 있습니다. 화면 설정에 따라 상태 컬럼과 삭제 선택 컬럼이 표시됩니다.
| 표시 | 의미 |
|---|---|
C | 새로 추가한 행 |
U | 기존 값을 수정한 행 |
D | 삭제 대상으로 선택한 행 |
| 빈 상태 | 변경되지 않은 행 |
| 형태 | 용도 | 조작 |
|---|---|---|
| 입력 | 문자·숫자 한 줄 입력 | 화면에 따라 숫자, 영문, 대소문자 등의 입력 제한이 적용됩니다. |
| 여러 줄 입력 | 설명·메모·본문 | 일반 텍스트 또는 서식 편집 도구를 사용합니다. |
| 콤보 | 정해진 목록에서 하나 선택 | 펼침 버튼으로 목록을 엽니다. |
| 검색 콤보 | 많은 항목에서 하나 선택 | 검색어를 입력하여 후보를 줄입니다. |
| 라디오 | 펼쳐진 항목 중 하나 선택 | 한 항목만 선택할 수 있습니다. |
| 체크박스 | 하나 이상의 항목 선택 | 여러 항목을 동시에 선택할 수 있습니다. |
| 토글 | 사용·미사용 같은 두 상태 | 스위치를 선택하여 상태를 바꿉니다. |
| 슬라이더 | 범위 안의 연속값 | 손잡이를 드래그하거나 방향키를 사용합니다. |
| 날짜·기간 | 날짜 한 개 또는 시작일~종료일 | 직접 입력하거나 달력에서 선택합니다. |
| 팝업 검색 | 사원·거래처·품목처럼 검색조건이 필요한 값 | 돋보기 버튼이나 Enter로 검색 화면을 엽니다. |
표시 상태 — 필수 항목은 별도 테두리나 표식으로 구분되고, 읽기 전용 항목은 잠긴 형태로 표시됩니다.
| 기능 | 동작 |
|---|---|
| 신규 | 새 데이터를 입력할 수 있도록 빈 상세영역이나 새 행을 준비합니다. |
| 수정 | 선택한 데이터의 편집 상태를 시작합니다. |
| 저장 | 필수값과 입력 형식을 확인한 뒤 변경내용을 반영합니다. |
| 취소 | 저장하지 않은 변경을 원래 상태로 되돌립니다. |
| 삭제 | 선택한 데이터를 확인 후 삭제합니다. |
첨부 목록이나 게시물의 문서 파일은 내려받아 다른 프로그램으로 열지 않아도 화면에서 바로 확인할 수 있습니다. 파일명이나 [미리보기]를 선택하면 파일 형식에 맞는 뷰어가 열립니다. PC와 모바일에서 같은 방식으로 동작합니다.
| 형식 | 확인할 수 있는 것 |
|---|---|
| 원본 그대로의 쪽 모양. 쪽 이동, 확대·축소, 인쇄, 본문 글자 선택 | |
| 이미지 (PNG·JPG·GIF·SVG·WebP·BMP) | 확대·회전·반전, 여러 장이면 슬라이드쇼 |
| 텍스트 (TXT·LOG·CSV·MD·JSON) | 수만 줄의 큰 파일도 빠르게 열람. 낱말 찾기, 줄 번호, 한글 인코딩 자동 인식 |
| XML·HTML | 태그 구조를 접었다 펴는 트리로 서식·전문의 구조 확인 |
| 워드 (DOCX) | 쪽·표·머리말/꼬리말을 원본 배치대로 |
| 엑셀 (XLSX·XLS) | 시트 탭 전환, 컬럼 정렬·필터 |
| 파워포인트 (PPTX) | 슬라이드의 텍스트·표·기본 도형 — 내용 확인용 |
| 한글 (HWPX·HWP) | HWPX는 글자 선택·복사까지 지원, 구형 HWP는 내용 확인용 |
| 압축 (ZIP) | 압축을 풀지 않고 폴더 구조를 트리로 확인, 항목별 [미리보기]·[받기] |
뷰어 툴바는 형식이 달라도 같은 원칙으로 동작합니다.
모바일에서는 문서 스크롤이 뷰어 안에서만 움직여 화면 전체가 딸려 내려가지 않으며, 긴 문서는 오른쪽의 두꺼운 스크롤 막대를 잡아 끌어 원하는 위치로 바로 이동할 수 있습니다.
| 구분 | 용도 | 닫기 결과 |
|---|---|---|
| 레이어 팝업 | 검색·선택·간단한 등록처럼 현재 화면과 연결된 작업 | [선택]·[저장]은 결과 반영, [닫기]는 취소 |
| 브라우저 새 창 | 원래 화면과 나란히 보거나 별도 창이 필요한 작업 | 완료 버튼은 결과 반영, 창 닫기는 취소 |
새 창이 열리지 않으면 주소창의 팝업 차단 표시를 확인하고 현재 사이트의 팝업을 허용합니다.
대시보드는 KPI·차트·목록 등의 위젯을 한 화면에 배치합니다. 편집 기능이 제공되는 경우 다음과 같이 개인화할 수 있습니다.
좁은 화면에서는 목록과 상세가 한 화면에 모두 표시되지 않고 단계적으로 전환될 수 있습니다.
다크·라이트·고대비 테마는 같은 기능을 서로 다른 명도와 색상으로 제공합니다. 선택한 테마는 다음 접속에도 유지될 수 있습니다.
글자와 배경, 선택 상태와 경계를 더 명확하게 구분해야 할 때 고대비 테마를 사용합니다.
| 증상 | 확인할 내용 |
|---|---|
| 입력할 수 없음 | 읽기 전용 항목인지, 목록에서 선택해야 하는 항목인지 확인합니다. |
| 저장되지 않음 | 필수값 안내, 입력 형식, 실제 변경내용이 있는지 확인합니다. |
| 팝업이 열리지 않음 | 브라우저의 팝업 차단 상태를 확인합니다. |
| 정렬·필터가 사라짐 | 재조회로 목록 상태가 초기화된 것인지 확인합니다. |
| 로그인 화면으로 이동함 | 세션이 만료되었을 수 있으므로 다시 로그인합니다. |
| 화면이 잠김 | 무활동 보호 기능이 동작한 경우 다시 시작하여 접속합니다. |
무설치 개발환경에서 시작해 화면 구조, 공개 생명주기, 34종 컴포넌트와 실무 패턴을 익힙니다.
MOCA는 표준 HTML·CSS·JavaScript 위에서 동작하는 프론트엔드 UI/UX 프레임워크입니다. 선언형 속성으로 업무 화면을 구성하고, 화면별 스코프와 공통 컴포넌트로 반복 코드를 줄입니다.
| 특징 | 설명 |
|---|---|
| 선언형 UI | data-m-type과 data-m-* 속성으로 컴포넌트와 동작을 선언합니다. |
| 화면별 스코프 | SPA 안에서 여러 화면이 같은 ID를 사용해도 $p가 화면 범위를 분리합니다. |
| 업무 컴포넌트 | 그리드·폼·팝업·파일·위젯·달력·트리·차트·문서 뷰어 등 34종을 제공합니다. |
| 반응형·테마 | 같은 화면 구조를 데스크톱·분할창·모바일과 다크·라이트·고대비 환경에서 사용합니다. |
| 개발 도구 | 자동완성, 화면 생성, 구조 탐색, 레이아웃·실행 미리보기를 제공합니다. |
| 서버 독립성 | 업무 서버의 기술과 분리되며, JSON 요청·응답과 보안 계약을 통해 연동합니다. |
MOCA Portable은 제품 평가·학습·화면 개발을 위한 무설치 통합 개발환경입니다. 압축을 해제한 폴더 안에 실행도구, 편집기, IntelliSense와 샘플 프로젝트가 함께 들어 있습니다.
MOCA-시작.bat을 실행하여 샘플 애플리케이션과 브라우저를 엽니다.MOCA-개발도구.bat을 실행하여 무설치 편집기와 작업공간을 엽니다.MOCA-시작.bat 샘플 애플리케이션 실행
MOCA-개발도구.bat MOCA IntelliSense가 설치된 편집기 실행
README-사용법.txt 시작 방법과 라이선스 안내
editor\ 무설치 편집기와 확장
runtime\ 실행에 필요한 내장 런타임
workspace\ 샘플 프로젝트와 MOCA 엔진
src\main\webapp\
vendor\moca\ MOCA 엔진·문서
system\demo\ 샘플 화면
ui\page\ 업무 화면 HTML
| 폴더 | 개발자가 하는 일 | 주의 |
|---|---|---|
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 공용 이미지와 섞지 않습니다. |
ui\page 아래의 HTML 화면 하나를 엽니다.data-m-label 또는 검색영역의 문구를 바꾸고 저장합니다.data-m-placeholder를 입력합니다.| 증상 | 확인 |
|---|---|
| 시작 창이 바로 닫힘 | 압축을 완전히 해제했는지, 폴더가 쓰기 가능한지 확인합니다. |
| 브라우저가 열리지 않음 | 시작 창의 안내와 사용 중인 포트를 확인한 뒤 주소를 직접 엽니다. |
| 편집기에 MOCA 표시가 없음 | HTML 파일을 하나 열고 상태표시줄의 MOCA 활성 표시를 확인합니다. |
| HTML을 저장해도 화면이 그대로임 | 현재 브라우저 화면과 수정한 파일이 같은 샘플 화면인지 확인한 뒤 해당 화면을 새로고침합니다. |
MOCA IntelliSense는 선언형 마크업과 공개 API를 편집기 안에서 탐색·작성·미리보기할 수 있게 하는 개발 도구입니다. VS Code 계열 편집기와 이클립스를 지원합니다. Portable에는 사전 설치되어 있으며, HTML 또는 JavaScript 파일을 열면 활성화됩니다. 아래 기능 표는 VS Code 확장 기준이고, 이클립스 지원 범위는 이 절 끝의 이클립스에서를 참고합니다.
MOCA IntelliSense는 마켓플레이스에 등록된 확장이 아니라 MOCA 소스 패키지의 vscode-moca 폴더에 소스로 포함되어 있습니다.
Portable이 아닌 환경(소스 패키지를 직접 받은 PC)에서는 다음 순서로 설치합니다. 별도의 빌드나 의존성 설치는 필요 없습니다.
powershell -ExecutionPolicy Bypass -File vscode-mocainstall.ps1
확장이 %USERPROFILE%.vscodeextensionsmoca-intellisense-<버전>에 복사되며, 이전 버전이 있으면 함께 정리됩니다.자동완성 후보의 출처 — 확장은 워크스페이스 안의 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 Outline | HTML 태그 전체가 아니라 Layout·Frame·Grid·Form 등 화면 골격을 트리로 표시하고 클릭 위치로 이동합니다. |
| MOCA 팔레트 | 카탈로그의 컴포넌트 목록입니다. 항목을 끌어 디자인뷰의 요소 앞·뒤나 칸 안에 놓으면 그 자리에 골격이 삽입되고, MOCA Outline 의 노드에 놓으면 그 노드 안(칸·폼·위젯·탭) 또는 바로 뒤에 정확히 들어갑니다. 더블클릭하면 편집기 커서 위치에 삽입됩니다. |
| MOCA 속성 | 커서가 있는 컴포넌트의 속성을 왼쪽 이름·오른쪽 값의 표로 보여줍니다. 허용값이 정의된 속성은 목록에서 고르고, 값을 바꾸면 소스의 여는 태그가 함께 수정됩니다(비우면 속성 삭제). 미리보기·Outline 에서 고른 컴포넌트도 같은 표로 따라옵니다. |
| 구조 색 표시 | 레이아웃·프레임·그리드·폼·위젯·탭의 여는 태그를 종류별 색으로 구분합니다. |
| 새 화면 만들기 | 레이아웃을 시각적으로 분할하고 각 칸의 용도를 선택하여 표준 화면 템플릿을 생성합니다. |
| 레이아웃 미리보기 | 골격 모드와 실행 모드를 전환하고, 경계 드래그로 비율을 조절하며 소스 위치와 선택을 동기화합니다. |
| 입력 위치 | 제공되는 후보 | 예 |
|---|---|---|
data-m-type=" | 34종 컴포넌트 타입 | grid, form, calendar |
| 컴포넌트 여는 태그 | 해당 타입에 유효한 속성·이벤트 | Grid의 data-m-rownum, Input의 data-m-keymask |
| 속성값 | 카탈로그에 정의된 허용값 | data-m-total="top", data-m-datetype="yyyyMMdd" |
$p. | 화면 스코프 공개 API | get, openPop, getParameter |
$p.get('id'). | HTML에서 찾은 ID의 컴포넌트 타입에 맞는 메서드 | Grid ID이면 drawGrid, getModifiedJSON |
moca.$g. | 메시지·포맷·보안 문자열·공통 유틸리티 | alert, comma, sanitizeHtml |
moca.$g.date. | 날짜 계산·비교·표시 API | getToday, format, addDay |
moca.$t. | 조회·저장·업로드 통신 API | exe, upload |
data-m-을 입력하면 현재 컴포넌트에 유효한 속성과 이벤트가 제안됩니다.
$p.get('grd_orders').에서 HTML의 ID와 타입을 판별해 Grid 전용 메서드만 제안합니다.
moca.$g.date.처럼 공개 API의 단계별 후보를 탐색하며 메서드를 선택할 수 있습니다.| 모드 | 확인·편집할 수 있는 것 |
|---|---|
| 골격 | Layout의 방향, 칸 번호와 비율을 도식으로 확인합니다. 칸 경계를 드래그하면 소스의 비율 토큰도 함께 바뀝니다. |
| 디자인 | 서버 없이 소스만으로 화면을 목업(그리드 제목·컬럼 헤더, 폼·검색 행, 입력·콤보·버튼·달력·탭·프레임)으로 그립니다. 요소를 클릭하면 소스·속성 뷰가 따라오고, 텍스트를 더블클릭하면 고칠 수 있으며, 칸 경계 드래그로 비율을 조절합니다. 선택한 요소는 Ctrl+X / Ctrl+C / Ctrl+V / Delete로 잘라내기·복사·붙여넣기·삭제할 수 있고(붙여넣기는 칸이면 안, 요소면 뒤), 모든 편집은 Ctrl+Z / Ctrl+Y로 되돌리고 다시 실행합니다. 실제 동작이나 데이터 없이 배치와 문안을 자유롭게 편집할 때 씁니다. |
| 실행 | 실제 실행 화면을 데스크톱·태블릿·모바일 뷰포트로 확인합니다. 선택 모드에서는 화면 요소를 클릭해 소스 위치로 이동하며, 라벨이나 그리드 헤더 같은 텍스트를 클릭하면 그 문자열이 있는 자리로 이동하고, 더블클릭하면 미리보기 중앙에 수정 창이 열려 글자를 고친 뒤 Enter 또는 확인으로 소스에 반영할 수 있습니다. |
편집 즉시 반영 — 실행 모드는 편집기에 열린 소스를 저장하기 전에도 그대로 그립니다. 타이핑, 속성 뷰의 값 변경, 미리보기 안의 텍스트 수정이 잠시 뒤 화면에 반영되며, 새 화면은 보이지 않는 곳에서 그려진 뒤 바꿔치기되므로 깜박이지 않습니다. 저장은 평소처럼 Ctrl+S로 하고, 공통 화면이나 서버 쪽을 고쳤을 때는 새로고침(↻)으로 전체를 다시 불러옵니다.
실행 모드와 로그인 — 실행 모드는 로컬 서버가 미리보기 인증 모드로 기동되어 있어야 로그인 없이 화면을 그립니다.
편집기 태스크 MOCA: 서버 기동이나 F5 디버그로 띄운 서버는 이 모드로 시작되며, 직접 기동할 때는 환경변수 MOCA_PREVIEW=1을 줍니다.
이 모드는 같은 PC 에서 온 미리보기 요청에만 적용되고, 샘플 애플리케이션 런처로 띄운 서버는 로그인이 필요한 제품 모드로 동작합니다.
세 방향 선택 동기화 — 소스 커서, 미리보기에서 선택한 칸·컴포넌트, MOCA Outline 항목은 같은 대상을 가리킵니다. HTML이 길어져도 현재 작업 위치와 화면 구조를 잃지 않게 해줍니다.
SI 현장의 표준 개발환경인 이클립스(전자정부표준프레임워크 포함)를 위한 플러그인입니다. VS Code 확장과 같은 컴포넌트 규격(카탈로그)을 읽으므로, 어느 편집기에서 작성하든 제안 내용이 서로 어긋나지 않습니다.
dropins 폴더에 복사합니다.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 Outline | Window → Show View → Other → MOCA. HTML 태그 전체가 아니라 Layout·Frame·Grid·Form 등 화면 골격만 트리로 표시하고, 항목을 고르면 소스의 그 태그로 이동합니다. |
| MOCA 디자인뷰 | 같은 메뉴에서 엽니다. data-m-layout 골격을 도식으로 그리며 — 칸 클릭 = 소스 이동, 소스 커서 = 칸 선택 표시, 칸 경계 드래그 = 소스의 비율 토큰 수정. 편집하면 도식이 즉시 따라옵니다. |
$p 스코프와 Layout 골격, 칸별 다음 작업 안내가 함께 들어 있습니다.
mgrid + Ctrl+Space — 그리드 골격 한 벌이 미리보기와 함께 제안됩니다.
규격 자동 반영 — 플러그인은 프로젝트의 vendor/moca/docs/moca-catalog.json을 실행 중에 읽습니다.
엔진 규격이 갱신되면 재설치 없이 자동완성에 반영되며, 프로젝트에서 규격 파일을 찾지 못하면 플러그인에 내장된 사본으로 동작합니다.
MOCA 화면은 Layout 안에 Frame과 컴포넌트를 배치하고, 각 Frame에 독립된 화면 스코프를 부여하는 구조입니다.
| 구성요소 | 역할 |
|---|---|
| Layout | 상하·좌우·중첩 비율을 선언하고 반응형 화면 골격을 만듭니다. |
| Frame | 화면 HTML을 불러오고 독립된 스코프와 생명주기를 생성합니다. |
| Scope | $p로 표현되는 화면별 함수·상태·컴포넌트 접근 범위입니다. |
| Component | data-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 참조 |
| 화면 스크립트 | 조회·저장·업무 조건과 동적 변화 | 조회 파라미터, 결과 렌더링, 팝업 결과 반영 |
| 컴포넌트 | 반복 상태·렌더링·검증·표준 상호작용 | 행상태, 필터, 버튼 상태, 날짜 범위, 위젯 배치 |
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() { /* 화면이 가려질 때 */ };
| 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() 같은 공개 메서드를 사용합니다.$p에 두고 공개 API로 컴포넌트에 접근합니다.moca.$t 또는 프로젝트 통신 어댑터를 사용해 JSON 데이터를 연결합니다.| 단계 | 완료 기준 | 주로 쓰는 도구 |
|---|---|---|
| 화면 유형 | 데이터 한 행에 1:N 상세가 있는지 판단하여 배치편집·목록상세를 구분 | 표준 패턴 표 |
| 골격 | 모든 콘텐츠가 Layout 칸 안에 있고 fit·auto·비율이 목적과 일치 | 새 화면 만들기·골격 미리보기 |
| 컴포넌트 | 직접 만든 UI 없이 기존 컴포넌트로 요구사항을 충족 | API 검색·자동완성 |
| 화면 코드 | 전역 함수·전역 ID 접근 없이 $p 기반으로 작성 | 스크립트 자동완성·Outline |
| 데이터 | 조회·저장 결과와 실패상태를 공통 통신 흐름으로 처리 | moca.$t |
| 상태·검증 | 필수값, R/U/C, C/U/D, 취소 복구가 컴포넌트와 연결 | Form·Grid·ButtonGroup |
| 품질 | 화면 폭·테마·키보드·보안 문자열 처리 확인 | 실행 미리보기·체크리스트 |
업무 화면의 골격은 Layout 컴포넌트로 작성합니다. 선언은 방향 문자 + 칸별 크기 토큰 하나로 끝납니다 —
v는 세로(위·아래) 분할, h는 가로(좌·우) 분할이고, 토큰을 :로 나열한
개수가 곧 칸 수입니다. 2분할뿐 아니라 h4:3:3처럼 3칸 이상도 같은 방식으로 선언합니다.
| 토큰 | 의미 | 대표 용도 |
|---|---|---|
숫자 | 칸끼리의 상대 비율입니다. 합이 10일 필요가 없어 2:8과 1:4는 같은 결과입니다(합을 10으로 쓰면 퍼센트처럼 읽혀 관례로 즐겨 쓸 뿐입니다). 0을 주면 그 칸이 접힙니다. | h3:7 좌측 목록·우측 상세 |
숫자px | 고정 크기 — 가로 분할이면 폭, 세로 분할이면 높이가 고정됩니다. | h240px:auto 고정 사이드바 |
fit | 내용 크기만큼만 차지합니다(여백이 남지 않음). | vfit:auto 상단 검색영역 |
auto | 고정 칸(px·fit)을 뺀 남은 공간 전부를 채웁니다. | v200px:auto 가변 본문 |
2:1), 고정+나머지는 px·fit 칸과 auto의
짝으로 선언합니다. auto를 비율 숫자와 섞으면 의도가 읽히지 않습니다.v1로 선언합니다(칸이 하나면 비율값은 의미가 없습니다).vfit:auto:fit은 검색영역·본문·버튼줄 3칸 골격입니다.조회 조건이나 사용자 조작에 따라 분할을 바꿔야 하면 setRatio()를 사용합니다.
같은 문법의 토큰을 넘기며, 방향 문자를 붙이면 방향까지 바뀝니다. 한쪽을 0으로 주면
그 칸이 접혀 사이드 영역 토글에 쓸 수 있습니다.
$p.get('lay_body').setRatio('7:3'); // 비율만 변경
$p.get('lay_body').setRatio('v3:7'); // 방향까지 변경
$p.get('lay_body').setRatio('h0:10'); // 왼쪽 칸 접기
data-m-layout-part를 가진 칸이어야 하며,
Form·Grid·Frame 등의 콘텐츠는 반드시 그 칸 안에 둡니다.목록·상세 화면의 상세 칸에 data-m-mobileview="pop"을 지정하면 좁은 화면에서 목록을 우선 표시하고,
행 선택 시 상세를 전체화면 오버레이로 전환할 수 있습니다.
| 화면 유형 | 루트·본문 Layout | 설명 |
|---|---|---|
| 검색 + 목록 | vfit:auto | 검색은 내용 높이, Grid는 남은 높이를 모두 사용합니다. |
| 좌 목록 + 우 상세 | vfit:auto 안에 h4:6 | 상단 검색 아래에 좌우 목록·상세를 배치합니다. |
| 상 목록 + 하 상세 | vfit:4:6 | 검색 아래에서 목록과 상세를 세로로 나눕니다. |
| Grid + Chart | h5:5 | 동일 데이터를 목록과 시각화로 비교합니다. |
| 고정 사이드 + 본문 | h240px:auto | 사이드 메뉴 폭을 고정하고 본문이 나머지를 채웁니다. |
| 단일 콘텐츠 | v1 | Grid·달력 등 하나의 컴포넌트가 화면 전체를 채웁니다. |
fit을 사용합니다.auto 또는 비율 토큰을 사용합니다.data-m-mobileview="pop"을 지정합니다.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') |
id는 현재 화면 안에서 컴포넌트를 찾는 식별자입니다. 타입 접두사를 사용하면 소스와 자동완성을 읽기 쉽습니다.data-m-ref는 Input·Selectbox·Calendar 등의 값을 Form 행 데이터 필드와 연결합니다.data-m-required="true"는 Form·Grid의 validate()와 연결됩니다.data-m-readonly는 선언 초기값이며, 런타임 변경은 각 컴포넌트의 setReadOnly()를 사용합니다.$p.fn_* 형태로 선언합니다.컴포넌트의 표준 스타일 class는 타입에 맞춰 MOCA가 자동으로 부여하므로 화면에서 적지 않습니다.
화면이 class에 적는 것은 정렬·여백 같은 프로젝트 전용 class뿐입니다.
표시나 동작을 바꾸는 값은 class가 아니라 속성으로 지정합니다. 속성은 값이 정해져 있어 잘못 쓰면 콘솔이 알려주지만,
class는 틀려도 아무 알림 없이 모양만 달라집니다.
| 타입 | MOCA가 부여하는 표준 class |
|---|---|
input | moca_input |
textarea | moca_textarea |
selectbox | moca_selectbox |
combobox | moca_combobox |
inputCalendar·inputMultiCalendar | moca_ica |
tab | moca_tab |
grid | moca_grid와 남은 높이를 채우는 fauto입니다. 화면이 지정한 class와 무관하게 항상 부여하며, 높이 채우기를 끄려면 data-m-fill="false"를 지정합니다. |
form | data-m-variant 값에 따라 moca_table_form(상세) 또는 moca_table_search(검색) |
하나의 화면에 함께 배치되는 입력 컴포넌트는 공통 도판으로 묶고, 구조·업무·시각화 컴포넌트는 대표 동작이 보이는 도판에 연결했습니다.
| 컴포넌트 | 도판 | 확인할 장면 |
|---|---|---|
| Layout | D9-1 | Layout 골격 미리보기 |
| Frame | D3-5, U2-2 | Layout 칸의 자식 화면과 실행 셸 |
| MDI | U2-2 | 여러 업무 화면 탭 |
| Tab | D9-3 | 화면 내부 게시판 탭 전환 |
| Form | D10-1 | 제목·검증 버튼·입력 행 |
| Input | D10-2 | 문자·전화번호·숫자·금액 입력 |
| Textarea | D10-3 | 여러 줄 PATH 입력 |
| Selectbox | D10-4 | 정해진 후보 목록 펼침 |
| Combobox | D10-5 | 검색 가능한 후보 목록 펼침 |
| Radio | D10-6 | 단일 선택 그룹 |
| CheckboxGroup | D10-7 | 복수 선택 그룹 |
| Toggle | D10-8 | ON·OFF 전환 |
| Slider | D10-9 | 현재값과 범위 눈금 |
| InputCalendar·InputMultiCalendar | D10-10 | 날짜·기간 입력과 달력 팝업 |
| InputPop | D10-11 | 검색 입력과 돋보기 버튼 |
| Grid | D11-1 | 셀 타입·툴바·행 편집 |
| ButtonGroup | D11-2 | Form 상태에 따른 신규·수정·삭제 버튼 |
| FileUpload | D11-3 | 파일 선택과 드래그앤드롭 |
| Calendar | D12-1 | 화면에 펼쳐진 날짜 선택 달력 |
| ScheduleCalendar | D12-2 | 월간·기간 일정 표시 |
| Treeview | D12-3 | 일반 조직 계층과 선택 상세 |
| VirtualTree | D12-4 | 10,010개 노드의 가상 렌더링 |
| Widget | D12-5 | 대시보드 조회·편집 상태 |
| Echart | D12-6 | 막대·라인·누적 차트 |
| Pdfviewer 등 뷰어 8종 | D13 | 형식별 담당 뷰어와 장착 방법 |
화면 구조 컴포넌트는 콘텐츠를 직접 입력받기보다 화면의 공간과 이동 단위를 정의합니다. Layout과 Frame은 모든 업무 화면의 기반이며, Tab과 MDI는 여러 화면을 전환하는 컨테이너입니다.
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>
data-m-layout-part를 가져야 합니다.
Grid·Form·Frame을 Layout과 형제로 두거나 칸 표시 없이 바로 넣으면 높이와 반응형 계산이 깨집니다.루트 Layout 오른쪽 아래의 [레이아웃 구조 보기] 버튼을 누르면 현재 화면의 중첩 방향과 비율 토큰이 각 영역 위에 표시됩니다. 화면 골격을 확인한 뒤 같은 버튼을 다시 누르면 원래 업무 화면으로 돌아옵니다.
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가 실행됩니다. 따라서 부모 초기화 시 자식의 스코프와 컴포넌트를 바로 가져올 수 있습니다.
tab은 하나의 업무 화면 안에서 여러 패널을 전환합니다. 선언 탭과 동적 탭을 함께 사용할 수 있습니다.
| 속성·이벤트 | 설명 |
|---|---|
data-m-target | 탭 버튼이 활성화할 패널 ID이며 탭 식별자로도 사용됩니다. |
data-m-src | 패널이 선택될 때 Frame 방식으로 불러올 화면 경로입니다. |
data-m-closable | true이면 탭에 닫기 버튼을 표시합니다. |
data-m-disabled | true이면 탭 전환을 막습니다. |
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)');
mdi는 애플리케이션 전체의 업무 화면 탭을 관리하는 셸 전용 컴포넌트입니다.
일반 업무 화면 안에서는 직접 만들기보다 이미 구성된 MDI의 공개 메서드를 사용합니다.
| 메서드 | 설명 |
|---|---|
openTab(url, param) | 업무 화면을 열고, 이미 같은 화면이 열려 있으면 해당 탭을 활성화합니다. |
closeTab(tabId) | 지정한 업무 탭을 닫습니다. |
getActiveTab() | 현재 활성 탭의 정보를 반환합니다. |
입력 컴포넌트는 값의 종류와 선택 방식에 맞게 고릅니다. Form의 data-m-ref 매핑을 사용하면
한 행의 데이터를 필드에 일괄 설정하고 수정값을 Grid와 자동으로 동기화할 수 있습니다.
| 주요 속성 | 설명 |
|---|---|
data-m-label, data-m-sublabel | 폼 제목과 보조 제목을 표시합니다. |
data-m-addition | 타이틀바 좌우에 추가할 버튼·라벨을 JSON 배열로 정의합니다. |
data-m-readonly | 내부 입력 컴포넌트를 일괄 읽기 전용으로 시작합니다. |
data-m-status | R(조회), U(수정), C(신규) 상태를 나타냅니다. |
data-m-refgrid | 연결할 Grid ID 또는 표현식입니다. 행 선택→폼 채움, 폼 변경→선택행 반영을 자동 처리합니다. |
data-m-variant | 폼 변형을 지정합니다. form은 상세 입력용, search는 조회조건용 모양입니다. |
data-m-toolbarfold | true이면 폼 접기·펼치기 버튼을 표시합니다. |
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>
| 속성 | 설명 |
|---|---|
data-m-value | 초기 입력값입니다. |
data-m-inputtype | password를 지정하면 입력 문자를 가립니다. |
data-m-required | Form·Grid 검증 시 필수 입력으로 판정합니다. |
data-m-readonly, data-m-innerdisabled | 읽기 전용 또는 비활성 상태를 지정합니다. |
data-m-keymask | 숫자·금액·실수·전화번호·대문자·소문자 등 입력 가능한 문자를 제어합니다. |
data-m-displayfunction | 원본값을 바꾸지 않고 콤마·전화번호·백분율 등 표시만 가공합니다. |
data-m-displayfunctionapply | realtime이면 입력 중에도 표시함수를 적용합니다. |
data-m-maxlength, data-m-placeholder | 최대 길이와 안내 문구를 지정합니다. |
data-m-ref | Form의 행 데이터와 연결할 필드명입니다. |
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>
| 속성 | 설명 |
|---|---|
data-m-value | 초기 본문입니다. |
data-m-readonly, data-m-innerdisabled | 읽기 전용·비활성 상태입니다. |
data-m-placeholder, data-m-maxlength, data-m-rows | 안내 문구, 길이와 표시 행 수를 지정합니다. |
data-m-ref | Form 데이터 필드와 연결합니다. |
data-m-rendertype | textarea 또는 div 방식 등 렌더 유형을 지정합니다. |
data-m-inneronblur | 포커스를 잃을 때 호출할 함수입니다. |
getValue(), setValue(), setReadOnly()로 값을 관리합니다.
| 속성 | 설명 |
|---|---|
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>
후보가 많아 사용자가 글자를 입력해 좁혀야 할 때 사용합니다. 기본 목록 키와 부모 연동 규칙은 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()를 제공합니다.
draw()에는 chooseOption을 전달하지 않습니다.
‘선택’ 항목이 필요하면 데이터 목록에 명시적으로 포함합니다.
| 속성 | 설명 |
|---|---|
data-m-itemset | 화면에 펼쳐서 표시할 라디오 항목 배열입니다. |
data-m-disabled | 전체 항목을 비활성화합니다. |
data-m-inneronclick | 항목 선택 시 호출할 함수입니다. |
getValue(), getLabel(), setValue(), setReadOnly(),
redraw()를 제공합니다.
| 속성 | 설명 |
|---|---|
data-m-checktype | checkbox는 단일, checkboxGroup은 다중 선택입니다. |
data-m-label | 단일 체크박스의 라벨입니다. |
data-m-itemset | 그룹 항목 배열입니다. 각 항목에 label·value·checked·onclick·disabled를 지정할 수 있습니다. |
data-m-direction | vertical이면 항목을 세로로 배치합니다. |
data-m-disabled | 전체 선택을 비활성화합니다. |
getValue()는 단일형이면 boolean, 그룹형이면 선택된 값의 배열을 반환합니다.
setValue(), setReadOnly(), redraw()도 제공합니다.
| 속성 | 설명 |
|---|---|
data-m-label | 토글 옆에 표시할 라벨입니다. |
data-m-onoff | 초기 상태입니다. on 또는 off를 사용합니다. |
data-m-truevalue, data-m-falsevalue | ON·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>
| 속성 | 설명 |
|---|---|
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()를 제공합니다.
| 속성 | 설명 |
|---|---|
data-m-type | inputCalendar는 단일 날짜, 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>
| 속성·이벤트 | 설명 |
|---|---|
data-m-value | 초기 표시값입니다. |
data-m-placeholder, data-m-maxlength | 안내 문구와 최대 길이입니다. |
data-m-ref | Form 데이터 필드와 연결합니다. |
data-m-readonly | 직접입력과 팝업 호출을 잠급니다. |
data-m-onclick | 돋보기나 Enter 입력 시 fn(comp) 형태로 호출됩니다. |
openPop(option), getValue(), setValue(), setReadOnly()를 제공합니다.
게시글·공지·메일 본문처럼 글꼴·표·이미지가 들어가는 본문은 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로 고정해도 같은 일이 생깁니다.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가 에디터 안쪽까지 맞추므로 화면이 색을 정하지 않습니다. 좁은 화면에서는 툴바가 짧은 구성으로 바뀌고, 폼이 세로로 쌓이면서 에디터 행이 남는 높이를 계속 채웁니다.
Grid, ButtonGroup, FileUpload, FloatingButton은 조회·편집·저장 중심의 업무 화면을 구성합니다. 이 가운데 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>
| 속성 | 설명 |
|---|---|
data-m-label, data-m-sublabel | 그리드 제목과 보조 제목입니다. |
data-m-defaultcellheight | 기본 행 높이 기준입니다. |
data-m-rowselectedcolor | 선택행 색상을 화면별로 지정할 때 사용합니다. |
data-m-rownum | 순번 컬럼을 자동 생성합니다. |
data-m-rowstatus | C/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"}'>
"detail":"true" — 내장 상세뷰를 엽니다. 선택 행의 모든 컬럼이 「라벨 — 값」으로
펼쳐지며 기본 3단(버튼 순서 3·2·1단, 모바일은 1단 고정)입니다.
입력·콤보·검색콤보·라디오·체크박스 셀타입은 상세뷰에서 실제 컴포넌트로 렌더되어 편집할 수 있고,
수정한 값은 setCellData() 경로로 그리드 행에 반영되어 행상태(U)와 저장 대상에 포함됩니다.
읽기 전용(data-m-readonly)이나 표시함수(data-m-displayfunction)가 있는 컬럼,
그 밖의 셀타입은 값만 표시됩니다."detail":"dblclick" — 내장 상세뷰 대신 버튼이 화면의
data-m-ondblclick 함수를 호출합니다. 목록·상세 패턴(D13-3)처럼 화면이 자체 상세
UI(폼·팝업)를 가진 경우, 더블클릭과 같은 진입을 툴바 버튼으로도 제공할 때 씁니다.| 위치 | 속성 | 설명 |
|---|---|---|
col | data-m-columnkey | 폭을 적용할 데이터 셀 ID와 col을 연결합니다. |
col | data-m-hide | 기기와 무관하게 해당 컬럼을 숨깁니다. |
col | data-m-mobilehide | 모바일에서만 컬럼을 숨깁니다. |
th | data-m-sortable | 정렬 버튼을 표시합니다. |
th | data-m-filterable | 값 목록 필터 버튼을 표시합니다. |
th | data-m-required | 필수 컬럼 표식을 표시합니다. |
th | data-m-celltype="checkbox" | 헤더 전체선택 체크박스를 렌더링합니다. |
| 속성 | 설명 |
|---|---|
id | 행 데이터의 필드명과 연결되는 컬럼 식별자입니다. |
data-m-celltype | input, checkbox, button, radio, selectbox, combobox, tree 등 셀 편집·표시 유형입니다. |
data-m-readonly | 셀 편집 가능 여부입니다. |
data-m-required | validate()에서 검사할 필수 셀입니다. |
data-m-keymask | Input과 동일한 숫자·금액·전화·대소문자 입력제어를 적용합니다. |
data-m-displayfunction | 원본 셀값은 유지하고 화면 표시만 가공합니다. |
data-m-displayformat | Selectbox·코드 셀의 [value]·[label] 표시형식입니다. |
data-m-maxlength | 편집 셀의 최대 입력 길이입니다. |
data-m-align | left, center, right 정렬입니다. |
data-m-itemset | Selectbox·Combobox 셀의 목록입니다. |
data-m-cdfield, data-m-nmfield | Grid 목록 항목의 코드·라벨 키입니다. 기본값은 code·codeNm입니다. |
data-m-parentcol, data-m-parentkey | 같은 행 안의 부모 컬럼과 연결하여 단계형 Selectbox를 구성합니다. |
data-m-onselectchanged | Selectbox·Combobox 셀의 값 변경 이벤트입니다. |
data-m-truevalue, data-m-falsevalue | 체크박스 셀의 체크·해제 저장값입니다. |
data-m-btnlabel | 버튼 셀에 표시할 라벨입니다. |
data-m-popupurl, data-m-popupdata | 팝업 셀에서 호출할 URL과 전달 데이터입니다. |
data-m-callfunction | 셀 동작 시 호출할 화면 함수입니다. |
data-m-calc | sum, count, avg, min, max 집계 연산입니다. |
data-m-colmerge, data-m-colmergealign | 연속 같은 값의 세로 병합과 병합 셀의 세로 정렬을 지정합니다. |
| 이벤트 | 호출 시점 |
|---|---|
data-m-onrowselected | 행 선택 후 Grid, 실제 행 인덱스, 셀 정보와 인스턴스를 전달합니다. |
data-m-onbeforeclick | 클릭에 따른 데이터 반영 전 호출합니다. false 또는 Promise로 후속 처리를 제어할 수 있습니다. |
data-m-onafterclick | 클릭에 따른 데이터 반영 후 호출합니다. |
data-m-ondblclick | 행 더블클릭 시 행·컬럼 정보를 전달합니다. |
data-m-onselectchanged | Selectbox·Combobox 셀값 변경 시 이전·새 값과 라벨을 전달합니다. |
data-m-onscrollend | 무한스크롤에서 마지막 위치에 도달했을 때 호출합니다. |
data-m-onpageclick | 번호 페이징의 페이지 선택 시 호출합니다. |
| 분류 | 메서드 | 설명 |
|---|---|---|
| 렌더 | 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>
| 속성 | 설명 |
|---|---|
data-m-form | 연결할 Form ID입니다. |
data-m-buttons | 라벨|후속함수 형식의 버튼 목록입니다. 수정·취소처럼 공통처리만 필요한 버튼은 함수명을 생략할 수 있습니다. |
data-m-title | R/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>
| 속성·이벤트 | 설명 |
|---|---|
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() | 초기화하거나 현재 첨부목록을 반환합니다. |
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-draggable | false로 지정하면 길게 눌러 이동하는 기능을 끕니다. 드래그로 옮긴 위치는 화면이 유지되는 동안만 보존됩니다. |
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>
날짜·일정·계층·대시보드·차트는 복잡한 렌더링을 컴포넌트가 담당하도록 데이터와 표시 옵션을 분리합니다.
| 속성 | 설명 |
|---|---|
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() | 다시 렌더링하거나 선택을 잠급니다. |
| 속성·이벤트 | 설명 |
|---|---|
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:'광복절' }
}
});
전체 노드를 한 번에 렌더링해도 부담이 없는 메뉴·조직·분류 데이터에 사용합니다.
| 메서드 | 설명 |
|---|---|
setData(data) | 노드 배열을 설정하고 렌더링합니다. |
getData() | 현재 노드 데이터를 반환합니다. |
setOnSelect(fn) | 노드 선택 콜백을 등록합니다. |
selectById(id) | 특정 노드를 선택합니다. |
| 속성 | 설명 |
|---|---|
data-m-rowheight | 스크롤 위치 계산에 사용하는 고정 행 높이입니다. CSS 행 높이와 일치해야 합니다. |
data-m-indent | 깊이 한 단계의 들여쓰기 폭입니다. |
data-m-guideline | 깊이 연결선 표시 여부입니다. |
data-m-defaultexpand | all, none 또는 숫자 깊이로 최초 펼침 범위를 지정합니다. |
data-m-onselect | 노드 선택 시 fn(node,comp)로 호출됩니다. |
setData(), getData(), getSelectedNode(), selectById(),
scrollToId(), expand/collapse/toggle(), expandAll/collapseAll(),
getVisibleCount(), getTotalCount(), getRenderedCount(),
refresh(), destroy()를 제공합니다.
getRenderedCount()는
현재 보이는 영역과 여유분만 반환해야 정상입니다.
| 속성 | 설명 |
|---|---|
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() |
| 속성·메서드 | 설명 |
|---|---|
data-m-theme | 적용할 ECharts 테마명입니다. |
setValue(option), setData(option) | 차트 option 전체를 설정하고 필요할 때 인스턴스를 생성합니다. |
getValue(), getData() | 현재 option을 반환합니다. |
clear() | 차트를 비웁니다. |
getChart(callback), onReady(callback) | 준비된 ECharts 인스턴스를 콜백으로 전달합니다. |
getChartObj() | 이미 생성된 인스턴스를 즉시 반환합니다. |
resize() | 즉시 크기 조정이 필요한 경우 수동으로 다시 계산합니다. |
destroy() | 동적으로 제거하기 전에 관찰자와 차트 인스턴스를 해제합니다. |
$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] }]
});
뷰어 컴포넌트는 업무 파일을 내려받지 않고 화면 안에서 바로 보여줍니다. 다른 컴포넌트와 같이
div에 타입을 선언하면 장착이 끝나며, 형식별로 필요한 렌더링 라이브러리는 엔진이
해당 뷰어를 처음 사용할 때 자동으로 로드하므로 화면에 <script src>를 추가하지 않습니다.
| 타입 | 담당 형식 | 특징 |
|---|---|---|
pdfviewer | 쪽 이동·확대·인쇄·다운로드, 본문 텍스트 선택 | |
imageviewer | PNG·JPG·GIF·SVG·WebP·BMP | 확대·회전·반전·슬라이드쇼, 단일·갤러리 모드 |
textviewer | TXT·LOG·CSV·JSON·XML·HTML | 대용량도 보이는 구간만 그려 빠름. 찾기, 인코딩 자동 판별(EUC-KR 포함), XML·HTML 접기 트리 |
excelviewer | XLSX·XLS | 시트를 뷰어 전용 경량 그리드로 렌더 — 시트 탭·정렬·필터 제공 |
docviewer | DOCX | 쪽·표·머리말/꼬리말을 원본 레이아웃대로 |
pptviewer | PPTX | 텍스트·표·기본 도형 — 내용 확인용(애니메이션·SmartArt 재현 안 됨) |
hwpviewer | HWPX·HWP | HWPX는 직접 렌더(텍스트 선택 가능), 구형 HWP는 내용 확인용. 형식은 파일 내용으로 자동 판별 |
zipviewer | ZIP | 압축을 풀지 않고 트리로 탐색, 항목별 미리보기는 그 형식의 담당 뷰어로 연결 |
가장 기본은 화면 레이아웃 칸에 직접 배치하는 것입니다. 뷰어는 부모가 준 높이를 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' });
| 구분 | 내용 |
|---|---|
| 문서 지정 | 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() |
| 뷰어 | 대표 속성·메서드 |
|---|---|
pdfviewer | data-m-page(시작 쪽), goPage()·fitWidth()·print() |
textviewer | data-m-mode(auto·text·xml), data-m-encoding(자동·UTF-8·EUC-KR), find()·goLine() |
excelviewer | data-m-sheet(시작 시트), data-m-maxrows(대용량 상한), getRows()·setSheet() |
docviewer | data-m-breakpages(쪽 나눔), goPage()·fitWidth() |
pptviewer | data-m-notice(재현 한계 안내 표시), goSlide() |
imageviewer | data-m-mode(단일·갤러리), add()·rotate()·play() |
zipviewer | getFileList()·preview()·downloadEntry() |
속성·이벤트·메서드의 전체 규격은 MOCA API 문서의 각 뷰어 항목에서 확인합니다.
pdfviewer로 여는 구성이 가장 정확합니다.
PPTX·구형 HWP 뷰어는 내용 확인용이라는 한계를 화면에서 안내합니다.표준 화면 패턴은 화면마다 조회·선택·편집 상태를 새로 구현하지 않기 위한 조합 규칙입니다. 먼저 사용자가 처리할 데이터 단위와 편집 위치를 결정한 뒤 가장 가까운 패턴을 선택합니다.
| 패턴 | 구성 | 선택 기준 | 핵심 상태 |
|---|---|---|---|
| 조회·목록 | 검색 Form + Grid | 조건으로 목록을 탐색하고 읽는 화면 | 검색조건, 선택행, 페이지 |
| 배치편집 | 편집 Grid + Grid 도구영역 | 행 데이터만으로 등록·수정·삭제가 끝나는 화면 | C/U/D 행상태, 변경분 |
| 목록·상세 | Grid + Form + ButtonGroup | 선택행의 상세정보나 하위 데이터가 있는 화면 | 읽기·편집, 선택행, 원본값 |
| 팝업 검색 | 검색 Form + 조회 Grid + 선택·닫기 | 원래 화면에 한 건 또는 여러 건의 결과를 반환 | 전달조건, 반환값, 취소 |
| 대시보드 | Widget + KPI·Echart·목록 | 여러 현황을 한 화면에서 요약 | 배치, 표시여부, 새로고침 |
검색조건은 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에서 현재 조건으로 조회합니다.한 행이 하나의 처리 단위이고 별도 상세 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()를 사용합니다. 신규행은 목록에서 제거되고,
기존행은 삭제 상태로 관리되어 저장 대상에 포함됩니다.
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의 취소 흐름을 사용합니다. |
| 저장·삭제 | 처리 완료 후 읽기 | 목록을 갱신하고 처리한 행을 다시 선택합니다. |
팝업은 독립된 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은 호출되지 않습니다.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);
};
화면 코드는 전역 DOM 탐색보다 현재 화면 스코프의 공개 API를 사용합니다. 컴포넌트 접근은 $p,
공통 표현과 검증은 moca.$g, 날짜는 moca.$g.date, 서버 통신은 moca.$t가 담당합니다.
| API 영역 | 역할 |
|---|---|
$p | 현재 화면의 컴포넌트, 파라미터, 부모화면, 팝업·창, 화면 생명주기 |
moca.$g | 메시지, 값 변환, 포맷, 보안 문자열 처리, 공통 화면 유틸리티 |
moca.$g.date | 오늘·현재시각, 날짜 계산·비교·포맷, 달력 데이터 |
moca.$t | JSON 조회·저장·업로드와 진행 상태, Promise 기반 비동기 처리 |
| 컴포넌트 인스턴스 | $p.get('id')로 얻는 각 컴포넌트의 값·목록·상태·렌더링 API |
$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);
};
moca.$g — 메시지·값·표시 유틸리티| 분류 | 대표 API | 적용 예 |
|---|---|---|
| 사용자 메시지 | alert, error, confirm | 완료·실패 안내와 삭제 확인 |
| 값 판정 | isEmpty, isNumeric, nul, getNumber | 입력값 검사와 안전한 기본값 |
| 표시 변환 | comma, phoneWithDashFormatter, percentFormatter | data-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('삭제 처리 중 오류가 발생했습니다.');
}
});
};
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)');
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가 읽기 쉽습니다.
| 계약 항목 | 화면에서 정할 내용 |
|---|---|
| 요청 | 필드명, 자료형, 필수값, 날짜 형식, 페이징 번호를 명확히 합니다. |
| 성공 응답 | 목록 배열, 단건 객체, 총건수, 업무 메시지의 위치를 고정합니다. |
| 빈 결과 | 목록은 빈 배열, 단건은 빈 객체 또는 null 중 하나로 일관되게 처리합니다. |
| 검증 오류 | 사용자가 수정할 수 있는 항목과 메시지를 구분하여 표시합니다. |
| 인증·권한 오류 | 공통 흐름에 맡기고 화면이 임의로 성공 상태를 만들지 않습니다. |
| 재시도 | 중복 저장 가능성이 있는 요청은 자동 재시도하지 않습니다. |
프로젝트 공통값은 화면마다 반복하지 않고 MOCA 설정에 둡니다. 개별 화면 속성은 해당 화면만 달라야 할 때 사용하며, 테마와 접근성은 기능 구현이 끝난 뒤가 아니라 컴포넌트 선택과 화면 구조 단계에서 함께 결정합니다.
| 설정 | 용도 | 개별 화면 재정의 |
|---|---|---|
mocaHome, vendorHome | MOCA 엔진과 외부 라이브러리의 기준경로 | 하지 않음 |
componentSize | Input·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)를 사용합니다.
data-m-mobileview="pop"을 적용합니다.data-m-mobilehide="true"로 숨깁니다.data-m-mobileheight로 지정합니다.| 검사 항목 | 구현 기준 |
|---|---|
| 키보드 이동 | Tab 순서가 화면의 읽기 순서와 일치하고, 주요 기능을 마우스 없이 실행할 수 있어야 합니다. |
| 포커스 이동 | 팝업이 열리면 팝업 안으로, 닫히면 열었던 요소로 포커스가 돌아와야 합니다. |
| 이름과 설명 | 아이콘만 있는 버튼에는 기능을 알 수 있는 이름을 제공하고 입력에는 연결된 라벨을 둡니다. |
| 오류 안내 | 오류가 난 항목을 문자로 설명하고 확인 후 해당 입력으로 포커스를 이동합니다. |
| 상태 표현 | 선택·필수·오류·비활성 상태를 색상 하나에만 의존하지 않습니다. |
| 명도대비 | 본문, 보조문자, 경계선, 포커스 윤곽이 각 테마에서 식별되는지 확인합니다. |
| 확대·축소 | 브라우저 확대 시 문자가 잘리거나 주요 버튼이 화면 밖으로 사라지지 않아야 합니다. |
MOCA는 화면 렌더링과 공통 통신에서 반복되는 보안 처리를 제공합니다. 서버는 인증·권한·토큰 검증과 업로드 정책을 반드시 별도로 적용해야 하며, 화면에서 버튼을 숨기는 것만으로 권한을 보장할 수 없습니다.
| 영역 | MOCA 화면의 책임 | 서버 연동 계약 |
|---|---|---|
| 출력 | 외부 값을 문맥에 맞게 텍스트·속성·제한된 HTML로 처리 | 저장된 값도 신뢰하지 않고 응답 형식과 자료형을 보장 |
| 요청 | 공통 통신을 사용하고 CSRF 토큰 헤더를 전달 | 상태 변경 요청마다 토큰의 유효성과 사용자 세션을 검증 |
| 인증 | 만료 응답을 공통 흐름으로 처리하고 로그인 화면으로 이동 | 보호 자원 접근 전 인증 상태를 판정 |
| 권한 | 권한에 따라 버튼·메뉴를 표시하여 잘못된 조작을 줄임 | 모든 조회·변경 요청에서 최종 권한을 다시 판정 |
| 파일 | 허용 확장자·크기 안내와 선택 단계 검증 | 파일 내용·크기·이름·저장경로를 최종 검증 |
textContent를 사용합니다.moca.$g.sanitizeHtml(), 속성값은 moca.$g.escapeAttr()을 사용합니다.// 일반 텍스트
element.textContent = row.TITLE;
// 제한된 표시 마크업
element.innerHTML = moca.$g.sanitizeHtml(row.CONTENT);
| 구간 | 요구사항 |
|---|---|
| 서버 | 사용자 세션과 연결된 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 })
});
증상부터 코드를 넓게 바꾸기보다 로드 → 스코프 → 선언 → 데이터 → 상태 → 반응형 순서로 범위를 좁힙니다.
같은 ID가 여러 화면에 있을 수 있으므로 오류가 발생한 Frame과 그 화면의 $p를 먼저 확인합니다.
$p.onpageload까지 실행되었는지 확인합니다.$p.get(id)가 기대한 컴포넌트를 반환하는지 확인합니다.data-m-type, 구조 태그와 연결 ID를 확인합니다.| 증상 | 먼저 확인할 내용 | 관련 절 |
|---|---|---|
| 입력 컴포넌트가 기본 브라우저 모양 | 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 |
| 단계 | 완료 기준 |
|---|---|
| 골격 | Layout의 모든 직계 자식이 칸으로 선언되고 목록·상세·도구영역의 책임이 분리되었습니다. |
| 컴포넌트 | 주요 속성, 이벤트 함수, 컴포넌트 간 연결 ID가 정확합니다. |
| 생명주기 | 초기 조회는 onpageload, 재활성화와 정리는 해당 훅에 배치되었습니다. |
| 데이터 | 요청·응답 필드, 날짜 형식, 빈 결과, 페이징 총건수의 계약이 정해졌습니다. |
| 편집 | 필수값 검증, 신규·수정·삭제 상태, 취소 복구, 중복 저장 방지가 동작합니다. |
| 보안 | 출력 무해화, CSRF, 인증·권한, 업로드 제한의 화면·서버 책임이 확인되었습니다. |
| 사용성 | 좁은 화면, 테마, 키보드, 포커스, 빈 데이터와 오류 상황을 확인했습니다. |
$p에 두고 공개 API로 접근했는가?data-m-* 속성을 자동완성 또는 API 문서에서 확인했는가?