본문으로

이 누리집은 대한민국 공식 전자정부 누리집입니다.

회원가입
메뉴검색
전체 메뉴 닫기

레이어 팝업 샘플

화면을 열면 바로 뜨는 안내 팝업입니다. 지금 이 화면에도 3개가 떠 있습니다 — WEB-INF/jsp/common/layerPopup.jsp 조각을 <jsp:include> 한 결과입니다.

🚨 될 수 있으면 쓰지 마세요 레이어 팝업은 사용자가 요청하지 않았는데 화면을 가리고 뜨는 UI 입니다. 웹에서 가장 평이 나쁜 패턴이고, 접근성과 모바일에서 특히 불리합니다 (포커스가 튀고, 좁은 화면에서는 본문을 통째로 덮습니다).
전 국민이 쓰는 공공 포털이므로, 관리자가 등록해 전체 사용자에게 알리는 공지(메인 팝업존)에만 쓰는 것을 원칙으로 합니다.
먼저 이 대안들을 검토하세요.
  • 화면 안 안내문 — 자리만 차지하고 아무것도 가리지 않습니다. 대부분 이걸로 충분합니다.
  • 사용자가 버튼을 눌러 여는 모달 (모달 팝업 샘플) — 사용자가 원해서 연 것이라 문제가 없습니다.
  • 게시판 공지 상단 고정
그래도 필요하면 — 개수를 최소로 하고(운영 SDC 포털은 5개까지 띄우는데 그 자체가 나쁜 예입니다), '오늘 하루 그만보기' 를 반드시 남겨 두세요.
💡 한 줄 요약 — 화면 JSP 에 include 한 줄, 컨트롤러에서 모델에 목록 한 줄.
목록이 비어 있으면 아무것도 그리지 않습니다 (CSS/JS 도 로드하지 않습니다). 여러 개 동시 노출 · 계단식 배치 · 드래그 · ESC 닫기 · 화면 밖으로 안 나가기 · 반응형 · 웹접근성은 이미 되어 있습니다.

1. 지금 화면에서 확인해 보기

떠 있는 팝업을 닫았다면 아래 버튼으로 다시 여세요. '오늘 하루 그만보기' 를 눌렀다면 쿠키를 지워야 다시 뜹니다 — 그 버튼이 실제로 어떻게 동작하는지 확인하는 용도입니다.

제목줄을 잡고 드래그해 보세요. 겹친 팝업은 클릭하면 맨 앞으로 나옵니다. ESC 는 맨 앞 팝업 하나만 닫습니다. 창 크기를 780px 아래로 줄이면 세로로만 쌓이는 카드 뭉치로 바뀝니다.

2. 붙이는 법 — 두 곳만 고치면 됩니다

이 화면이 실제로 하고 있는 일 그대로입니다.

① 화면 JSP (위치는 본문 최상위가 안전합니다 — 아래 주의사항 참고) <jsp:include page="/WEB-INF/jsp/common/layerPopup.jsp"/> ② 컨트롤러 List<Map<String, Object>> pops = new ArrayList<Map<String, Object>>(); Map<String, Object> p = new HashMap<String, Object>(); p.put("mainPupId", "N001"); // 필수 — '오늘 하루 그만보기' 쿠키 이름에 쓰인다 p.put("title", "서비스 점검 안내"); p.put("imgYn", "N"); // 'Y' = 이미지형, 그 외 = HTML형 p.put("htmlCnts", "<p>내용</p>"); p.put("pupWidthSize", "480"); // 가로 px (없으면 500) p.put("pupHeightSize", "320"); // 세로 px 상한 (HTML형만) pops.add(p); model.addAttribute("layerPopupData", pops);
⚠ VO 말고 List<Map<String,Object>> 를 쓰세요.
조각은 mainPupId / title / imgYn / atchFileId / htmlCnts / linkUrl / pupWidthSize / pupHeightSize / pupDesc 를 EL 로 읽습니다. VO 에 이 getter 가 하나라도 없으면 PropertyNotFoundException 으로 화면이 통째로 500 이 됩니다 (빈 값으로 넘어가지 않습니다). Map 은 없는 키가 null 이라 안전하고, 쓰지 않는 필드를 안 채워도 됩니다.

3. 항목 필드

필드필수설명
mainPupId팝업 식별자. '오늘 하루 그만보기' 쿠키 이름에 쓰인다
※ 이름이 main~ 인 것은 메인 팝업 테이블에서 온 이름입니다. 공통으로 옮기면서도 그대로 뒀습니다 — 바꾸면 DAO·SQL 까지 번집니다
imgYn'Y' = 이미지형, 그 외 = HTML형
title제목. 드래그 손잡이이자 접근성 이름이라 되도록 넣으세요.
없으면 제목줄을 안 그리고 드래그도 안 됩니다
htmlCntsHTML형본문 HTML. 이스케이프하지 않고 그대로 출력합니다(관리자 입력 전제)
atchFileId이미지형첨부파일 ID
linkUrl이미지 클릭 시 새 창으로 이동. 비었거나 http:// 만 있으면 링크를 안 겁니다
pupWidthSize가로 px. 없으면 500, 최소 360 은 CSS 가 보장
pupHeightSize세로 px 상한. HTML형에만 적용
※ 가로는 '실제 폭', 세로는 '상한' 입니다 — 내용이 짧은데 세로를 고정하면 본문과 버튼 사이에 큰 빈 공간이 생깁니다
pupDesc이미지 대체텍스트 후보(title 이 없을 때)

4. include 파라미터 3가지

이 화면은 아래처럼 세 가지를 다 넘기고 있습니다.

<jsp:include page="/WEB-INF/jsp/common/layerPopup.jsp"> <jsp:param name="cookiePrefix" value="smpLayerPop_"/> <jsp:param name="todayBtn" value="Y"/> <jsp:param name="imgUrlPrefix" value="/pub2026/images/main/"/> </jsp:include>
파라미터기본값설명
cookiePrefix layerPop_ 🚨 화면마다 다르게 주세요. 쿠키는 접두사 + 팝업ID 이고 path=/사이트 전역입니다. 화면마다 팝업 ID 체계가 다르므로(메인은 팝업 채번, 다른 화면은 게시글 ID 등) 번호가 겹치는 순간 한 화면에서 끈 팝업이 다른 화면에서도 꺼집니다.
※ 메인은 기본값을 그대로 씁니다 — 바꾸면 이미 '그만보기' 를 누른 사용자의 쿠키가 초기화됩니다
todayBtn Y N 이면 '오늘 하루 그만보기' 버튼을 안 그립니다. 약관 변경 고지처럼 매번 보여야 하는 안내에만 쓰세요. 버튼만 빠지고 '닫기' 는 그대로라, 그 팝업은 새로고침하면 다시 뜹니다(그게 목적입니다).
⚠ 남용 금지 — 끌 수 없는 팝업은 사용자에게 가장 나쁜 형태입니다.
imgUrlPrefix /common/getImageFile.do?fd= 이미지형 팝업의 파일 서비스 경로. 뒤에 첨부파일ID + &fs=0 이 붙습니다.
SDC(TN_SBCS_FILE_DTL) 자료면 기본값으로는 이미지가 404 입니다 → /common/getSdcImageFile.do?fd= 를 넘기세요.
※ 한 화면의 팝업이 두 DB 에 섞여 있으면 이 방식으로는 안 됩니다. 그때는 컨트롤러가 완성된 URL 을 항목에 담는 구조로 바꿔야 합니다(메인 배너 팝업존의 PopupZone.imgUrl 이 그 예)
※ 이 샘플은 DB 첨부파일이 없어 퍼블 정적 이미지 폴더를 가리켜 두었습니다. 실제 화면에서는 건드릴 일이 거의 없습니다

5. 이미 되어 있는 것 — 따로 안 해도 됩니다

  • 여러 개 동시 노출 — 계단식으로 겹쳐 배치. 클릭하면 그 팝업이 맨 앞으로
  • 계단 간격 자동 — 앞 팝업의 제목줄 높이를 실측해 그만큼 내립니다(제목이 두 줄이어도 X 버튼이 안 가립니다). 동시에 맨 앞 팝업 몫을 먼저 떼는 예산이 있어, 개수가 많아도 맨 앞 본문이 사라지지 않습니다
  • 드래그 이동 — 제목줄을 잡고 이동. 터치 기기도 됩니다(jQuery UI 는 마우스만 듣습니다). jQuery UI draggable 이 없는 빌드에서는 조용히 넘어갑니다
  • ESC 로 닫기 — 맨 앞 팝업부터 하나씩. 모달이 열려 있으면 모달에 양보합니다
  • 화면 밖으로 안 나감 — 팝업마다 자기 위치 기준으로 높이 상한을 잡아 하단 버튼이 항상 눌립니다. 창 크기를 바꾸면 다시 계산합니다
  • 헤더를 안 가림#wrap-header 높이를 실측해 그 아래에서 시작합니다. 헤더가 없는 레이아웃이면 기본값(top:200px)을 씁니다
  • 반응형 — 780px 이하에서는 가로 계단을 없애고 세로로만 쌓습니다(카드 뭉치)
  • 웹접근성role="dialog" + aria-modal="false" + 제목 연결, X 버튼 이름 부여

6. 붙일 때 흔히 막히는 곳

증상원인 / 조치
아무것도 안 뜬다모델이 비었거나 이름이 다름 — layerPopupData (메인은 mainPopupData)
화면이 500 으로 죽는다VO 에 위 getter 가 없음 → List<Map> 으로 바꾸거나 getter 추가
이미지가 깨진다imgUrlPrefix 가 SDC 인데 MDIS 기본값을 쓰고 있음, 또는 파일 실물 없음
다른 화면에서 껐는데 여기도 꺼짐cookiePrefix 를 안 갈랐음
계속 안 뜬다이전에 '오늘 하루 그만보기' 를 누름. 브라우저 쿠키에서 접두사+ID 삭제
팝업이 화면이 아니라 어떤 박스 안에 갇힌다include 를 transform/filter/perspective 가 걸린 요소 에 넣었음. 그 요소가 position:fixed 의 새 기준이 됩니다 → 본문 최상위로 옮기세요
같은 팝업이 두 벌 뜬다레이아웃과 화면이 둘 다 include 함. 조각에 가드가 있어 보통은 막히지만, include 를 한 곳으로 정리하세요
드래그가 안 된다title 이 비어 손잡이(제목줄)가 없음. 또는 780px 이하 좁은 화면(의도된 동작)
무엇이든 물어보세요