캘린더 ToDo 만들기: SwiftUI와 EventKit으로 캘린더 이벤트를 완료 리스트로 전환

발행: (2026년 5월 22일 AM 07:57 GMT+9)
6 분 소요
원문: Dev.to

출처: Dev.to

가끔은 내 캘린더를 되돌아보면서 내가 계획한 것뿐 아니라 실제로 했던 일도 알고 싶을 때가 있다.

  • 공부 세션을 끝냈나요?
  • 실제로 헬스장에 갔나요?
  • 이번 주에 어떤 예정된 작업을 완료했나요?
  • 일일 일정에 어떤 리듬이 있나요?

캘린더 앱은 미래 계획을 관리하는 데는 뛰어나지만, 그 계획이 실제로 완료됐는지는 잘 보여주지 못한다.

그래서 나는 Calendar ToDo 라는 iOS 앱을 만들기 시작했다 – 캘린더 이벤트를 ‘완료’로 표시하고 캘린더를 개인 실행 로그로 바꿔주는 앱이다.

App Store: Calendar ToDo

Calendar ToDo


Calendar ToDo란?

Calendar ToDo는 기존 캘린더 이벤트에 완료 기록을 추가해 주는 iOS 앱이다.

Calendar ToDo – 디자인

핵심 아이디어는 아주 단순하다.

캘린더에는 이미 계획이 들어 있다. Calendar ToDo는 그 계획을 완료 목록으로 바꾸는 일을 도와준다.

기능

  • 오늘의 캘린더 이벤트 표시
  • 이벤트를 완료로 표시
  • 오늘의 완료율 표시
  • 완료된 이벤트 타임라인 보관
  • 히트맵으로 실행 리듬 시각화
  • 이벤트 종료 시 알림 전송
  • 알림에서 바로 이벤트를 완료로 표시 가능
  • iCloud / CloudKit과 완료 기록 동기화

디자인 결정: Calendar ToDo는 원본 캘린더 이벤트를 편집하지 않는다. EventKit을 사용해 캘린더 데이터를 읽어온 뒤, 완료 기록은 앱 내부에 별도로 저장한다.


왜 캘린더 제목을 직접 편집하지 않을까?

완료된 이벤트를 관리하는 가장 간단한 방법은 제목 앞에 체크 표시를 붙이는 것이다. 예:

✅ Study SwiftUI
✅ Workout
✅ Write blog post

개인용 소규모 캘린더에서는 통하지만, 다음과 같은 단점이 있다.

문제Calendar ToDo제목 편집
원본 캘린더 무결성캘린더를 읽기 전용으로 유지원본 캘린더를 수정
계획과 결과의 분리완료 기록을 별도 저장계획과 결과가 뒤섞임
공유 캘린더공유 데이터에 손대지 않음공유 캘린더에서 위험
반복 이벤트각 발생을 개별 추적반복 이벤트에서 오류 발생

업무용 캘린더, 공유 캘린더, 반복 이벤트가 있는 경우 제목을 직접 바꾸는 것은 안전하지 않다. Calendar ToDo는 캘린더 위에 레이어처럼 작동한다: 캘린더는 계획된 이벤트의 원천이며, 앱은 실행 결과만 저장한다.


기본 아키텍처

앱은 SwiftUI, EventKit, Core Data, CloudKit으로 구성된다.

단순화된 데이터 흐름은 다음과 같다:

SwiftUI

EventKit

캘린더 이벤트 읽기

Core Data / CloudKit

완료 기록 저장

알림 / 위젯 / 리포트
  • EventKit – 캘린더 이벤트를 읽는다.
  • Core Data + CloudKit – 앱 자체의 완료 기록을 저장·동기화한다.

핵심 분리

  • 캘린더 이벤트 – EventKit에서 가져온(읽기 전용) 데이터
  • 완료 기록 – Calendar ToDo가 별도로 저장

이렇게 하면 사용자의 캘린더가 안전하게 보호된다.


EventKit으로 이벤트 읽기

EventKit을 이용해 오늘의 이벤트를 가져오는 코드는 대략 다음과 같다:

let eventStore = EKEventStore()

let calendars = eventStore.calendars(for: .event)

let predicate = eventStore.predicateForEvents(
    withStart: startOfDay,
    end: endOfDay,
    calendars: calendars
)

let events = eventStore.events(matching: predicate)

가져온 EKEvent 객체들은 SwiftUI에 표시되지만, 앱은 절대 직접 수정하지 않는다. 이 규칙은 캘린더에 업무 이벤트, 공유 이벤트, 반복 이벤트, 혹은 다른 앱이 만든 이벤트가 포함될 수 있기 때문에 중요하다.


완료 기록을 별도로 저장하기

EKEvent에 완료 상태를 다시 쓰는 대신, 앱은 자체적인 완료 기록을 만든다:

struct CompletionRecord {
    let occurrenceKey: String
    let status: CompletionStatus
    let completedAt: Date
}

enum CompletionStatus {
    case done
    case skipped
    case partial
}

실제 구현에는 더 많은 필드가 있지만 핵심 아이디어는 동일하다: 캘린더 이벤트를 바꾸지 말고 결과를 별도로 저장한다. 이렇게 하면 프라이버시가 보호되고 기존 캘린더와 함께 사용할 때도 안전하다.


어려운 부분: 이벤트와 기록 매칭하기

처음엔 event.eventIdentifier만으로도 완료 기록을 `EKEvent

0 조회
Back to Blog

관련 글

더 보기 »

NeuroCalT+ 암산

!Cover image for NeuroCalT+ Mental Mathhttps://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads...

러스트 언어 성능 [PDF]

Goal Rust is defined as a safe, low‑level, system programming language directly competing with C++. How much does it pay for safety in terms of performance? Ca...