OPEN SOURCE/FullCalendar

์Šคํ”„๋ง๋ถ€ํŠธ(SpringBoot)๋กœ ํ’€์บ˜๋ฆฐ๋”(FullCalendar) ๊ตฌํ˜„ํ•˜๊ธฐ - 1

Junesker 2025. 5. 12. 15:25
๋ฐ˜์‘ํ˜•

์Šคํ”„๋ง๋ถ€ํŠธ๋กœ ํ’€ ์บ˜๋ฆฐ๋” ๊ตฌํ˜„ํ•˜๊ธฐ

 

ํ’€์บ˜๋ฆฐ๋” ๊ธฐ๋ณธ์ ์ธ ์—ฌ๋Ÿฌ ์†์„ฑ์— ๋Œ€ํ•ด์„œ ์ด์ „ ๊ฒŒ์‹œ๊ธ€์„ ํ†ตํ•ด ์•Œ์•„๋ดค๋‹ค๋ฉด, ์Šคํ”„๋ง ๋ถ€ํŠธ๋ฅผ ํ™œ์šฉํ•ด ํ’€์บ˜๋ฆฐ๋”๋ฅผ ๊ตฌํ˜„ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ํ’€์บ˜๋ฆฐ๋”๋Š” ์ผ์ • ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ๋•Œ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ, ๋งŽ์€ ๊ธฐ์—…๋“ค์ด ํ’€์บ˜๋ฆฐ๋” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๊ฐ€์ ธ๋‹ค ์ผ์ • ๊ด€๋ฆฌ ๊ธฐ๋Šฅ์œผ๋กœ ํ™œ์šฉํ•˜๊ณ  ์žˆ๋Š” ๋งŒํผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ณ  ์‚ฌ์šฉํ•ด๋ณด๋Š”๋ฐ ์˜๋ฏธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

 

 

 

ํ’€์บ˜๋ฆฐ๋” ์„ค์ •ํ•˜๊ธฐ


์บ˜๋ฆฐ๋” ํ™”๋ฉด ๋งŒ๋“ค๊ธฐ

 

์บ˜๋ฆฐ๋” ํ™”๋ฉด์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” JSPํŽ˜์ด์ง€๋ฅผ ์ด์šฉํ•ด ์บ˜๋ฆฐ๋”๊ฐ€ ๋ณด์—ฌ์งˆ ํŽ˜์ด์ง€๋ฅผ ๊ด€๋ จ ์Šคํฌ๋ฆฝํŠธ, ์Šคํƒ€์ผ์„ ์ ์šฉํ•ด ๋งŒ๋“ค์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ์œ„ํ•ด์„œ๋Š” ์Šคํฌ๋ฆฝํŠธ, ์Šคํƒ€์ผ ์ •๋ณด๋ฅผ CDN ๋˜๋Š” ์ œ๊ณต ํŒŒ์ผ์„ ํ†ตํ•ด ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์บ˜๋ฆฐ๋” ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธ์ ์ธ ์„ค์ •์ด ํ•„์š”ํ•œ๋ฐ ๊ฐ ์„ค์ •์— ๋”ฐ๋ผ 3๊ฐ€์ง€ ๋ฐฉ์‹์œผ๋กœ ์บ˜๋ฆฐ๋” ํ™”๋ฉด์„ ๊ตฌ์„ฑํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

  1. ํ’€์บ˜๋ฆฐ๋” ๊ธฐ๋ณธ ์„ค์ •์„ ์ด์šฉํ•œ ๋ฐฉ์‹
  2. ์ปค์Šคํ…€ ์ผ์ •์œผ๋กœ events ์†์„ฑ ์ด์šฉํ•œ ๋ฐฉ์‹
  3. ์ปค์Šคํ…€ ์ผ์ •์œผ๋กœ events ์†์„ฑ์— URL ์ด์šฉํ•œ ๋ฐฉ์‹

 

COMMON ์„ค์ •

์œ„ 3๊ฐ€์ง€ ๋ฐฉ์‹ ๋ชจ๋‘ ์•„๋ž˜ COMMON ์„ค์ •์€ ๋™์ผํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋งŒ, ์Šคํฌ๋ฆฝํŠธ ๋‚ด์— ์ž‘์„ฑํ•ด์•ผ ํ•  ์†์„ฑ ๋‚ด์šฉ๋“ค์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

 

ํ’€์บ˜๋ฆฐ๋” GLOBAL CDN ์„ค์ •

<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js"></script>

 

 

ํ’€์บ˜๋ฆฐ๋”๊ฐ€ ๋‚˜ํƒ€๋‚  ์˜์—ญ ์„ค์ •

<div id="calendar"></div>

 

 

1.  JSP ํŽ˜์ด์ง€ ๊ตฌ์„ฑํ•˜๊ธฐ (ํ’€์บ˜๋ฆฐ๋” ๊ธฐ๋ณธ ์„ค์ •)

 

์ „์ฒด ์†Œ์Šค

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js"></script>
</head>
<body>
	<div id="calendar"></div>
</body>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
	let calendarEl = document.getElementById('calendar');
	
	let headerToolbar = {
		left: 'prevYear,prev,next,nextYear today',
		center: 'title',
		right: 'dayGridMonth,dayGridWeek,timeGridDay'
	}
	
	let calendar = new FullCalendar.Calendar(calendarEl, {
		initialView: 'dayGridMonth',
		headerToolbar: headerToolbar
	});
	calendar.render();
});
</script>
</html>

 

 

์ ์šฉ ํ™”๋ฉด

 

๊ธฐ๋ณธ์ ์ธ ํ’€์บ˜๋ฆฐ๋” ์„ค์ •์œผ๋กœ ์ ์šฉํ•œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. ํ—ค๋” ํˆด๋ฐ”๋กœ๋Š” ์˜ค๋ฅธ์ชฝ์— '์›”', '์ฃผ', '์ผ' ๋‹จ์œ„๋กœ ์ผ์ •์„ ๋ณผ ์ˆ˜ ์žˆ๊ณ  ํˆด๋ฐ” ์™ผ์ชฝ์—๋Š” ํ˜„์žฌ ์›”์„ ์ด์ „, ๋‹ค์Œ์œผ๋กœ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๋ฒ„ํŠผ์ด ๋ณด์—ฌ์ง‘๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ํ˜„์žฌ ๋‚ ์งœ๋ฅผ ์บ˜๋ฆฐ๋”์— ์ƒ‰์ƒ์œผ๋กœ ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค. 

 

 

 

 

 

2.  EVENTS ๊ตฌ์„ฑํ•˜์—ฌ ํ’€์บ˜๋ฆฐ๋”์— ์ผ์ • ์ถ”๊ฐ€ํ•˜๊ธฐ (์ปค์Šคํ…€ ์ผ์ • ์ง์ ‘ ๊ตฌํ˜„)

 

์ „์ฒด์†Œ์Šค

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js"></script>
</head>
<body>
	<div id="calendar"></div>
</body>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
	let calendarEl = document.getElementById('calendar');
	
	let headerToolbar = {
		left: 'prevYear,prev,next,nextYear today',
		center: 'title',
		right: 'dayGridMonth,dayGridWeek,timeGridDay'
	}
	
	let calendar = new FullCalendar.Calendar(calendarEl, {
		initialView: 'dayGridMonth',
		headerToolbar: headerToolbar,
		events : [
			{
				id: "sch01",
				title : "์ผ์ •01",
				start : "2025-05-12",
				end : "2025-05-13",
				backgroundColor: "red",
				textColor : "white",
				allDay : true
			},
			{
				id: "sch02",
				title : "์ผ์ •02",
				start : "2025-05-12T09:00:00",
				end : "2025-05-13T09:00:00",
				backgroundColor: "green",
				textColor : "white",
				allDay : false
			}
		]
	});
	calendar.render();
});
</script>
</html>

 

 

์ ์šฉ ํ™”๋ฉด

 

'events' ์†์„ฑ์— ์ปค์Šคํ…€์œผ๋กœ ์ž‘์„ฑ๋œ ์ผ์ • 2๊ฐ€์ง€๋ฅผ ๋ฐฐ์—ด์˜ ํ˜•ํƒœ๋กœ ๋งŒ๋“ค์–ด์„œ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ์ฒซ๋ฒˆ์งธ '์ผ์ •01' ์ผ์ •์€ allDay์˜ ์†์„ฑ์ด 'true'๋กœ ํ•˜๋ฃจ์ข…์ผ์— ๋Œ€ํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ์ผ์ •์ด๊ณ  ๋‘๋ฒˆ์งธ '์ผ์ •02' ์ผ์ •์€ allDay์˜ ์†์„ฑ์ด 'false'๋กœ ํ•˜๋ฃจ์ข…์ผ์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์‹œ์ž‘์‹œ๊ฐ„๊ณผ ๋ ์‹œ๊ฐ„์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์ผ์ •์œผ๋กœ ๊ตฌ์„ฑ๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ ์ผ์ •์— ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ์†์„ฑ ๊ฐ’์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. 

 

 

 

 

 

3.  ์ผ์ • ๋ชฉ๋ก์„ ์š”์ฒญํ•  URL๋กœ ํ’€์บ˜๋ฆฐ๋”์— ์ผ์ • ์ถ”๊ฐ€ํ•˜๊ธฐ (DB ์—ฐ๋™)

 

์ „์ฒด์†Œ์Šค

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/fullcalendar@6.1.14/index.global.min.js"></script>
</head>
<body>
	<div id="calendar"></div>
</body>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
	let calendarEl = document.getElementById('calendar');
	
	let headerToolbar = {
		left: 'prevYear,prev,next,nextYear today',
		center: 'title',
		right: 'dayGridMonth,dayGridWeek,timeGridDay'
	}
	
	let calendar = new FullCalendar.Calendar(calendarEl, {
		initialView: 'dayGridMonth',
		headerToolbar: headerToolbar,
		events: "/scheduleList.do"
	});
	calendar.render();
});
</script>
</html>

 

 

์ ์šฉ ํ™”๋ฉด

 

์„ธ๋ฒˆ์งธ ๋ฐฉ์‹์ธ ์ผ์ • ๋ชฉ๋ก์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•œ ์š”์ฒญ์„ ์„œ๋ฒ„๋กœ๋ถ€ํ„ฐ ๋ฐ›์•„์™€ 'events' ์†์„ฑ์— ๋ฐฐ์—ด์˜ ํ˜•ํƒœ๋กœ ๊ตฌ์„ฑํ•ด์ค๋‹ˆ๋‹ค. ์š”์ฒญ URL์„ ํ†ตํ•ด์„œ ๋„˜๊ฒจ๋ฐ›์€ ๋ฐ์ดํ„ฐ ์ž์ฒด๊ฐ€ List ํƒ€์ž…์˜ ๋ฐฐ์—ด ๋ฐ์ดํ„ฐ๊ธฐ ๋•Œ๋ฌธ์— events ์†์„ฑ์— ๊ฐ ์ผ์ •์„ ๊ตฌ์„ฑํ•  event๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค๋ฉด ์ผ์ •์„ ๊ตฌ์„ฑํ•˜๋Š”๋ฐ ๋ฌธ์ œ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์„ธ๋ฒˆ์งธ ๋ฐฉ์‹์ด ํ’€์บ˜๋ฆฐ๋”๋ฅผ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ์žˆ์–ด ๊ฐ€์žฅ ๋ณดํŽธ์ ์œผ๋กœ ๋งŽ์ด ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. (๋ฌผ๋ก  events ์†์„ฑ์— ์ž‘์„ฑํ•  ๋‚ด์šฉ์€ ์ž‘์—…์ž๋“ค ๋งˆ๋‹ค ์ฐจ์ด๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•„์ž๋Š” ์†Œ๊ฐœํ•ด๋“œ๋ฆฐ๊ฒƒ์ฒ˜๋Ÿผ URL ๊ธฐ๋ฐ˜์œผ๋กœ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.)

 

 

 

 

 

๊ฐ ๋ฐฉ์‹์— ๋”ฐ๋ผ์„œ event(์ผ์ •)๋ฅผ ๊ตฌ์„ฑํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ๋งˆ์ง€๋ง‰ ๋ฐฉ์‹์œผ๋กœ ์†Œ๊ฐœํ•ด๋“œ๋ฆฐ DB์—ฐ๋™์„ ์ด์šฉํ•œ ์ผ์ • ๊ตฌ์„ฑ์— ๋Œ€ํ•ด์„œ๋Š” [ ์Šคํ”„๋ง๋ถ€ํŠธ(SpringBoot)๋กœ ํ’€์บ˜๋ฆฐ๋”(FullCalendar) ๊ตฌํ˜„ํ•˜๊ธฐ - 2 ] ๊ฒŒ์‹œ๊ธ€์„ ํ†ตํ•ด์„œ ์†Œ๊ฐœํ•ด๋“œ๋ฆฌ๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

์Šคํ”„๋ง๋ถ€ํŠธ(SpringBoot)๋กœ ํ’€์บ˜๋ฆฐ๋”(FullCalendar) ๊ตฌํ˜„ํ•˜๊ธฐ - 2

'์Šคํ”„๋ง๋ถ€ํŠธ(SpringBoot)๋กœ ํ’€์บ˜๋ฆฐ๋”(FullCalendar) ๊ตฌํ˜„ํ•˜๊ธฐ - 1' ๊ฒŒ์‹œ๊ธ€์„ ํ†ตํ•ด์„œ ๊ธฐ๋ณธ์ ์ธ ์บ˜๋ฆฐ๋”๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด์•˜์Šต๋‹ˆ๋‹ค. ํ’€์บ˜๋ฆฐ๋” ๊ตฌํ˜„ํ•˜๊ธฐ ๋‘ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ

junesker.tistory.com

 

 

 

 

 

@Junesker


 

๋ฐ˜์‘ํ˜•