CFcoForward Popup
Project Collaboration Guide

coForward Popup

다양한 형태의 모달과 팝업을 생성하는 UI 컴포넌트입니다.

Popup은 제목, 내용, 버튼, 이벤트 등을 자유롭게 구성하여 다양한 사용자 인터페이스를 만들 수 있습니다.

확인, 취소, 추가 버튼과 드래그, 다시 보지 않기 기능 등 다양한 옵션을 제공합니다.

🪟

다양한 팝업 유형

일반 팝업과 콘텐츠 뷰어 등 다양한 형태를 지원합니다.

🖱️

드래그 이동

드래그 가능한 팝업을 생성할 수 있습니다.

🔘

버튼 구성

확인, 취소, 추가 버튼을 자유롭게 구성할 수 있습니다.

⚙️

콜백 이벤트

버튼별 이벤트와 자동 닫기 여부를 설정할 수 있습니다.

🚫

다시 보지 않기

일정 기간 동안 팝업을 숨기는 기능을 제공합니다.

📦

데이터 전달

팝업과 호출 화면 간 데이터를 전달할 수 있습니다.

coForward Popup 소개

coForward Popup은 HTML <dialog>를 기반으로 팝업을 생성하고, 확인·취소·추가 버튼 콜백과 다시 보지 않기 처리를 제공하는 사내 공통 JavaScript 컴포넌트입니다.

이 문서에서 다루는 기능

기능 설명
기본 팝업 표시 제목, 본문, 확인 버튼이 있는 팝업을 표시합니다.
취소·추가·확인 버튼 버튼 캡션과 클릭 콜백을 지정합니다.
자동 닫기 제어 버튼 클릭 후 팝업을 닫을지 여부를 설정합니다.
컨테이너 내부 표시 document.body가 아니라 특정 요소 안에 팝업을 추가합니다.
다시 보지 않기 지정한 일수 동안 같은 제목의 팝업을 차단합니다.
닫힘 후 콜백 팝업이 닫힌 뒤 후속 함수를 실행합니다.
드래그 이동 헤더를 잡고 팝업 위치를 이동합니다.

필수 준비물

  • Popup 클래스 파일
  • 팝업 전용 CSS
  • <script>를 실행할 수 있는 브라우저
📌 단일 HTML 기준
이 파일은 Popup.js의 클래스 코드를 문서 하단 <script>에 직접 포함하므로 별도 import와 localData 파일이 필요하지 않습니다.

적용 준비

HTML 작성

기본 모달 팝업은 별도 컨테이너 없이 document.body에 추가됩니다.

<button id="openPopup" type="button">팝업 열기</button>

<script>
// Popup 클래스와 실행 코드를 이 HTML 안에 직접 작성합니다.
</script>

특정 영역 안에 팝업을 표시하려면 컨테이너를 준비합니다.

<button id="openInnerPopup" type="button">영역 안 팝업 열기</button>
<div id="popupContainer"></div>

<script>
// Popup 클래스와 실행 코드를 이 HTML 안에 직접 작성합니다.
</script>

클래스 불러오기

이 단일 HTML에서는 Popup.jsPopup 클래스를 문서 하단 <script>에 직접 붙여 넣어 사용합니다.

// HTML 하단 script 안에 Popup 클래스 코드를 직접 포함
const popup = new Popup();
📌 참고
JavaScript 경로는 프로젝트의 실제 정적 리소스 경로에 맞게 변경합니다.

CSS 준비

Popup 스타일은 __popup.scss에 정의되어 있습니다. 해당 파일을 프로젝트의 Sass 빌드에 포함하여 사용합니다.

close()는 팝업에 closing 클래스를 추가하고, 닫기 애니메이션이 종료되면 팝업을 닫고 제거합니다. __popup.scss&.closing은 CSS로 컴파일되면 .popup.closing이 되며, pop-out 애니메이션이 적용됩니다.

.popup.closing {
    animation: popupClose 0.2s ease forwards;
}


기본 생성 및 표시

팝업은 다음 순서로 생성합니다.

const popup = new Popup();

popup.setTitle('알림');
popup.setContent('처리가 완료되었습니다.');
popup.setSubmitCaption('확인');
popup.add();

기본 적용 순서

Popup 클래스 코드 포함
↓
인스턴스 생성
↓
제목·내용·버튼 설정
↓
콜백 설정
↓
add() 호출
⚠️ 중요
인스턴스를 생성한 것만으로는 팝업이 표시되지 않습니다. 설정이 끝난 뒤 add()를 호출합니다.

버튼과 콜백

버튼 캡션

popup.setCancelCaption('취소');
popup.setExtraCaption('도움말');
popup.setSubmitCaption('확인');
설정 생성되는 버튼 class 기본값
cancelCaption btn-cancel 빈 문자열
extraCaption btn-sub 빈 문자열
submitCaption btn-confirm Submit

캡션이 빈 문자열이면 해당 버튼은 생성되지 않습니다.

확인 버튼 콜백

popup.setPayload({ id: 10 });

popup.setOnSubmit((payload) => {
    console.log('확인:', payload.id);
});

payload가 설정되어 있으면 onSubmit에는 payload가 전달됩니다. payload가 없으면 생성된 dialog 요소가 전달됩니다.

한 번만 실행되는 확인 콜백

popup.setOnSubmitOnce((payloadOrDialog) => {
    console.log('한 번만 실행:', payloadOrDialog);
});

onSubmit이 있으면 onSubmitOnce보다 onSubmit이 우선 실행됩니다. 한 번만 실행해야 하는 경우 onSubmit은 설정하지 않습니다.

취소 버튼 콜백

popup.setCancelCaption('취소');

popup.setOnCancelEvent((dialog) => {
    console.log('취소:', dialog);
});

취소 콜백에는 생성된 dialog 요소가 전달됩니다.

추가 버튼 콜백

popup.setExtraCaption('자세히');
popup.setPayload({ url: '/help' });

popup.setExtraEvent((payload) => {
    console.log('추가 버튼:', payload.url);
});

payload가 설정되어 있으면 onExtraEvent에는 payload가 전달됩니다. payload가 없으면 생성된 dialog 요소가 전달됩니다.

버튼 클릭 후 닫기 제어

popup.setIsCloseAfterSubmit(false);
popup.setIsCloseAfterCancel(false);
popup.setIsCloseAfterExtraEvent(false);
설정 기본값 설명
isCloseAfterSubmit true 확인 버튼 클릭 후 닫을지 여부
isCloseAfterCancel true 취소 버튼 클릭 후 닫을지 여부
isCloseAfterExtraEvent true 추가 버튼 클릭 후 닫을지 여부

표시 위치와 컨테이너

기본 모달 표시

컨테이너를 설정하지 않으면 팝업은 document.body에 추가되고 showModal()로 표시됩니다.

const popup = new Popup();
popup.setTitle('알림');
popup.setContent('본문입니다.');
popup.add();

컨테이너 내부 표시

const container = document.getElementById('popupContainer');

popup.setContainer(container);
popup.add();

컨테이너가 설정되면 팝업에 in-container 클래스가 추가되고, 컨테이너 안에 append된 뒤 open 속성이 설정됩니다.

type과 class

popup.setType('content-viewer');
popup.setClass('notice-popup wide');
설정 설명
type dialog의 data-type 속성으로 저장됩니다.
class 공백으로 나눈 각 class가 dialog에 추가됩니다.

typeorder 또는 content-viewer이면 헤더 닫기 버튼이 강제로 표시됩니다.

헤더 닫기 버튼

popup.setHeaderCloseButton(false);

headerCloseButtontrue이면 헤더에 닫기 버튼이 표시됩니다. 기본값은 true입니다.

드래그 이동

popup.setDragable(true);

dragabletrue이면 팝업 헤더를 마우스로 끌어 위치를 이동할 수 있습니다.


다시 보지 않기

blockingDays가 1 이상이면 footer에 다시 보지 않기 체크박스가 표시됩니다.

popup.setTitle('점검 안내');
popup.setBlockingDays(7);
popup.setBlockingCaption('7일 동안 다시 보지 않기');

이 단일 HTML 버전은 localData를 사용하지 않으므로 체크 상태를 영구 저장하지 않습니다.

차단 여부 확인

const popupData = {
    title: '점검 안내',
    content: '시스템 점검이 예정되어 있습니다.',
    blockingDays: 7
};

if (!Popup.checkBlocking(popupData)) {
    const popup = new Popup();
    popup.setData(popupData);
    popup.add();
}

이 단일 HTML 버전의 Popup.checkBlocking()은 localData를 사용하지 않기 때문에 항상 false를 반환합니다.

⚠️ 중요
다시 보지 않기 기능은 title을 기준으로 차단 데이터를 찾습니다. 같은 제목을 여러 팝업에서 공유하면 함께 차단될 수 있습니다.

닫기 처리와 이벤트

닫기 후 콜백

popup.setCloseAfterCallBack(() => {
    console.log('팝업이 닫혔습니다.');
});

팝업이 닫히고 DOM에서 제거된 뒤 closeAfterCallBack이 실행됩니다.

닫기 전 이벤트

팝업이 닫힐 때 documentbeforeDialogClose 이벤트가 발생합니다.

document.addEventListener('beforeDialogClose', (event) => {
    console.log(event.detail.className);
    console.log(event.detail.type);
});

detail에는 닫히는 dialog의 classNamedata-type 값이 전달됩니다.

직접 닫기

popup.close(dialogElement);

close()는 dialog 요소를 인자로 받습니다. 일반 사용에서는 헤더 닫기 버튼 또는 footer 버튼의 자동 닫기를 사용하는 방식을 권장합니다.


통합 예제

아래 예제는 안전한 DOM 본문, 확인·취소 버튼, payload, 다시 보지 않기, 닫기 후 콜백을 함께 사용합니다.

HTML

<button id="openDeletePopup" type="button">삭제 팝업 열기</button>

<script type="module" src="/js/delete-popup.js"></script>

JavaScript

// Popup 클래스는 이 HTML 하단 script에 포함되어 있습니다.

const openButton = document.getElementById('openDeletePopup');

if (!openButton) {
    throw new Error('팝업 버튼을 찾을 수 없습니다.');
}

openButton.addEventListener('click', () => {
    const popupData = {
        title: '삭제 확인',
        blockingDays: 1,
        blockingCaption: '오늘 다시 보지 않기'
    };

    if (Popup.checkBlocking(popupData)) {
        return;
    }

    const content = document.createElement('div');
    const message = document.createElement('p');
    message.textContent = '선택한 항목을 삭제하시겠습니까?';
    content.appendChild(message);

    const popup = new Popup();

    popup.setTitle(popupData.title);
    popup.setContent(content);
    popup.setPayload({ id: 10 });
    popup.setCancelCaption('취소');
    popup.setSubmitCaption('삭제');
    popup.setBlockingDays(popupData.blockingDays);
    popup.setBlockingCaption(popupData.blockingCaption);

    popup.setOnSubmit((payload) => {
        console.log('삭제 대상 ID:', payload.id);
    });

    popup.setOnCancelEvent(() => {
        console.log('삭제를 취소했습니다.');
    });

    popup.setCloseAfterCallBack(() => {
        console.log('팝업이 닫혔습니다.');
    });

    popup.add();
});

실행 데모

Popup.js의 기본 생성, 확인, 취소, 닫기 동작만 확인할 수 있는 단일 데모입니다.

팝업 동작 로그가 여기에 표시됩니다.

문제 해결

팝업이 표시되지 않습니다.

다음 항목을 확인합니다.

  1. HTML 하단에 Popup 클래스가 포함되어 있는지 확인합니다.
  2. new Popup() 이후 add()를 호출했는지 확인합니다.
  3. 브라우저가 <dialog>showModal()을 지원하는지 확인합니다.
  4. 브라우저 개발자 도구의 Console 오류를 확인합니다.

닫기 버튼을 눌러도 팝업이 사라지지 않습니다.

__popup.scss가 정상적으로 컴파일되어 로드되었는지와 .popup.closingpop-out 애니메이션이 적용되는지 확인합니다.

확인 버튼을 눌렀는데 콜백 인자가 예상과 다릅니다.

payload가 설정되어 있으면 payload가 전달되고, 없으면 dialog 요소가 전달됩니다.

popup.setPayload({ id: 10 });

다시 보지 않기가 동작하지 않습니다.

다음 항목을 확인합니다.

  • blockingDays가 1 이상인지 확인합니다.
  • title이 비어 있지 않은지 확인합니다.
  • 팝업을 띄우기 전에 Popup.checkBlocking(popupData)를 호출했는지 확인합니다.
  • 이 단일 HTML 버전은 localData를 사용하지 않으므로 브라우저 재접속 후 차단 상태를 유지하지 않습니다.

컨테이너 안에 표시되지 않습니다.

setContainer(container)에 실제 DOM 요소를 전달했는지 확인합니다.

const container = document.getElementById('popupContainer');
popup.setContainer(container);

API 요약

주요 속성

속성 기본값 설명
type 빈 문자열 dialog의 data-type 값입니다.
placement 빈 문자열 위치 구분 코드용 속성입니다. 현재 렌더링 코드에서 직접 사용되지는 않습니다.
class 빈 문자열 dialog에 추가할 CSS class 문자열입니다.
title 빈 문자열 팝업 제목입니다.
content 빈 문자열 팝업 본문입니다. 문자열 또는 HTMLElement를 사용할 수 있습니다.
contentWidth false article width 값입니다. 숫자를 전달하면 px 단위로 적용됩니다.
payload null 확인·추가 콜백에 전달할 데이터입니다.
cancelCaption 빈 문자열 취소 버튼 문구입니다.
extraCaption 빈 문자열 추가 버튼 문구입니다.
submitCaption Submit 확인 버튼 문구입니다.
headerCloseButton true 헤더 닫기 버튼 표시 여부입니다.
isCloseAfterCancel true 취소 버튼 클릭 후 닫기 여부입니다.
isCloseAfterExtraEvent true 추가 버튼 클릭 후 닫기 여부입니다.
isCloseAfterSubmit true 확인 버튼 클릭 후 닫기 여부입니다.
container null 팝업을 추가할 컨테이너입니다.
blockingDays 0 다시 보지 않기 기간입니다.
blockingCaption 다시 보지 않기 다시 보지 않기 체크박스 라벨입니다.
closeAfterCallBack null 닫기 완료 후 실행할 함수입니다.
closedBy none dialog의 closedby 속성 값입니다.
dragable false 헤더 드래그 이동 여부입니다.

주요 메서드

메서드 설명
setData(data) 여러 설정을 객체로 한 번에 적용합니다.
setTitle(title) 제목을 설정합니다.
setContent(content) 본문을 설정합니다.
setPayload(payload) 콜백에 전달할 데이터를 설정합니다.
setCancelCaption(caption) 취소 버튼 문구를 설정합니다.
setExtraCaption(caption) 추가 버튼 문구를 설정합니다.
setSubmitCaption(caption) 확인 버튼 문구를 설정합니다.
setOnCancelEvent(callback) 취소 버튼 콜백을 설정합니다.
setExtraEvent(callback) 추가 버튼 콜백을 설정합니다.
setOnSubmit(callback) 확인 버튼 콜백을 설정합니다.
setOnSubmitOnce(callback) 한 번만 실행되는 확인 버튼 콜백을 설정합니다.
setContainer(container) 팝업을 추가할 컨테이너를 설정합니다.
setBlockingDays(days) 다시 보지 않기 기간을 설정합니다.
setBlockingCaption(caption) 다시 보지 않기 라벨을 설정합니다.
setCloseAfterCallBack(callback) 닫기 완료 후 콜백을 설정합니다.
setDragable(dragable) 드래그 이동 여부를 설정합니다.
add() 팝업을 생성해 화면에 표시합니다.
getCode(isPreview?) 팝업 DOM을 생성해 반환합니다. true이면 dialog 대신 div를 반환합니다.
close(dialog) 지정한 dialog를 닫고 제거합니다.
setBlockingData(data) 다시 보지 않기 데이터를 저장하거나 제거합니다.
Popup.checkBlocking(popupData) 저장된 다시 보지 않기 상태를 확인합니다.

© team coForward