본문 바로가기
프로젝트

문화재청 행사일정 API로 달력 만들기 시리즈 (2)

by 이페코장인 2024. 2. 25.

지난 글에서 문화행사 일정을 MySQL에 저장하는데까지 진행하였다. 이제 이 데이터를 이용해서 ics파일을 만들고자 한다.

 

iCal4j 를 Spring에 세팅하기

 

자바에서 쉽고 간단하게 ics파일을 다루는 iCal4j 라는 라이브러리가 있기에, 이를 사용하면 ics파일 쓰기/읽기/저장하기를 할 수 있다.

 

iCal4j 공식 레퍼런스 사이트

Getting Started - iCal4j

 

Getting Started - iCal4j

Getting Started These instructions are designed to help you get a basic setup, to be able to start coding with iCal4j. Download iCal4j libraries are currently published directly to Maven Central. Use the following table to identify current coordinates for

www.ical4j.org

 

 

iCal4j를 사용하기 위해 스프링 프로젝트 빌드에 추가를 해야 한다. 나는 Maven을 사용하였기에, pom.xml파일에 다음과 같은 dependency코드를 추가하였다. Gradle을 사용한다면 필요한 코드도 같이 적어 두었다. (2024년 1월 5일 버전)

 

// Maven용 코드

<dependency>
    <groupId>org.mnode.ical4j</groupId>
    <artifactId>ical4j</artifactId>
    <version>4.0.0-rc3</version>
</dependency>


// Gradle용 코드

implementation group: 'org.mnode.ical4j', name: 'ical4j', version: '4.0.0-rc3'

 

 

iCalendar (ics) 파일 생성하기

 

이제 iCal4j에서 제공하는 함수와 객체들을 활용할 수 있게 되었다. 이번에도 ics파일 생성용 뷰 페이지를 만들어서 컨트롤러를 이어주고 다음과 같은 코드로 행사일정을 저장한다. 나는 uid (이벤트 id), startDate(시작일), endDate(종료일), eventName(제목), location(장소), description(내용) 의 정보들을 입력했는데, 다른 정보들도 다룰 수 있는 객체들이 라이브러리에 존재하니 iCal4j 공식 사이트의 문서를 읽어보면 좋다.

 

	@GetMapping("/calendar/saveFile")
	public String saveFile(HttpSession session) {
		
		// 달력 만들기
	    Calendar icsCalendar = new Calendar();
	    icsCalendar.add(new ProdId("-//Ben Fortuna//iCal4j 1.0//EN"));
	      
        // DB에서 저장된 행사 일정 가져오기
	    List<EventCalendar> eventList = service.findAll();
        
        // 이벤트 만들기
	    for (EventCalendar eventCal : eventList) {
		    	  
		    // 이벤트에 필수로 할당해줘야 하는 고유 id
		    UidGenerator ug = new RandomUidGenerator();
		    Uid uid = ug.generateUid();
		    
		    // 날짜정보 필터링
	    	if (eventCal.getSDate().length() == 8 && eventCal.getEDate().length() == 8) {
	    		
//	    		01234567
//		    	20230422 이런 형태로 된 날짜정보를 자바 LocalDate객체로 변환해주고, 시작/종료일 넣어주기
	    		log.debug("sdate : " + eventCal.getSDate() + "edate : " + eventCal.getEDate());
	    		int sYear = Integer.parseInt(eventCal.getSDate().substring(0, 4));
	    		int sMonth = Integer.parseInt(eventCal.getSDate().substring(4, 6));
	    		int sDay = Integer.parseInt(eventCal.getSDate().substring(6));
	    		LocalDate startDate = LocalDate.of(sYear, sMonth, sDay);
		    		  
			    int eYear = Integer.parseInt(eventCal.getEDate().substring(0, 4));
			    int eMonth = Integer.parseInt(eventCal.getEDate().substring(4, 6));
			    int eDay = Integer.parseInt(eventCal.getEDate().substring(6));
			    LocalDate endDate = LocalDate.of(eYear, eMonth, eDay);
		    		  
			    // 이벤트 제목
			    String eventName = eventCal.getSubTitle();
			    VEvent newEvent = new VEvent(startDate, endDate, eventName);
			    newEvent.add(uid);
			   
			    // 이벤트 장소
			    Location location = new Location(eventCal.getSido() + eventCal.getGugun());
			    newEvent.add(location);
			  
			    // 이벤트 내용
			    Description description = new Description(eventCal.getSubContent() + "\n" + eventCal.getSubDate());
			    newEvent.add(description);
			  
			    // 이벤트 저장
			    icsCalendar.add(newEvent);
	    	    }
	      }
	      
	      // 파일 저장 경로
		  String rootPath = session.getServletContext().getRealPath("resources");
		  String savePath = rootPath + "/upload/board"; // 파일 저장 경로
		  log.debug("savePath : " + savePath);
			
	      // 파일 생성하기
	      String filePath = savePath + "/EventCalendar.ics";
	      FileOutputStream out = null;
	      try {
		   out = new FileOutputStream(filePath);
		   CalendarOutputter outputter = new CalendarOutputter();
		   outputter.output(icsCalendar, out);
	      } catch (FileNotFoundException e) {
		   e.printStackTrace();
	      } catch (ValidationException e) {
		   e.printStackTrace();
	      } catch (IOException e) {
		   e.printStackTrace();
	      } finally {
			 if (out != null) {
			      try {
			           out.close();
			      } catch (IOException e) {
			           e.printStackTrace();
			      }
	                 }
	      }
		
		return "calendar/view";
	}

 

 

프로젝트를 실행하면 수천 개의 행사일정이 저장되느라 시간이 조금 걸리고, ics파일이라는 것이 저장 경로에 생성이 된다.

 

이 파일을 메모장에서 열어보면, 다음과 같이 일정 데이터가 제대로 저장된 것을 확인할 수 있다.

 

 

 

구글, 네이버, Outlook, 스마트폰 달력앱 등에서 ics파일 사용하기

 

생성된 ics파일은 다양한 달력/일정 앱에서 사용을 지원해 준다. 대표적으로 구글 캘린더나 네이버 캘린더에서 달력 가져오기 설정을 눌러 보면, ics파일을 업로드해서 일정을 생성할 수 있는 기능이 있다. 나는 구글 캘린더 웹버전으로 파일을 읽어 보았다.

 

  

 

ics파일에 저장된 데이터가 워낙 많다보니 구글에서 파일을 읽는 데 시간이 다소 걸린다. 일정 가져오기가 끝났다는 메세지가 나오면, 다음과 같이 구글 캘린더 앱에서 데이터가 예쁘게 들어가 있다.

 

 

시리즈 3