Skip to content

[refactor] 캘린더 공통 로직 분리 및 일정 출처 구분 #235

Open

Description

@laura-jung

Feature Issue 📌

  • 기존 : 캘린더 연동·일정 동기화 로직이 구글 전용으로 작성되어 있음
    • externalEventId가 있으면 무조건 구글 일정으로 판단
    • 동기화·연동 해제 쿼리, 투두 상태 컬럼·응답 필드, 오류 코드가 모두 구글 기준
    • 이 상태로 애플 캘린더([feat] 애플 캘린더 연동 및 일정 투두 저장 #233)를 추가하면 구글 동기화·연동 해제가 애플 투두까지 삭제하는 문제 발생
  • 변경 : 애플 캘린더 추가 전에 구글·애플이 공통으로 쓰는 로직과 공급자별 로직을 분리하고, 투두에 일정 출처(CalendarSource: GOOGLE/APPLE)를 저장해 구분
    • 이번 작업에서는 애플 기능을 추가하지 않고, 오류 코드 문자열 외의 구글 동작은 그대로 유지

기획과 논의 내용

패키지 구조

  • 공통 로직은 calendar/ 바로 아래, 공급자 전용 로직은 calendar/google/, calendar/apple/ 하위 패키지로 분리
    • 기존 컨벤션(domain/{기능}/{레이어})에 없는 구조이지만, 공급자별 연결·인증·클라이언트 코드가 많아 경계를 명확히 하기 위해 도입
  • 공통 : 공급자 인터페이스(CalendarEventProvider), 공통 일정 형식, 날짜 계산, 투두 동기화, 동기화·조회 서비스
  • 구글 전용 : OAuth·state 검증, 토큰 갱신, 토큰 폐기 대기열, 구글 연결 정보, 구글 클라이언트

일정 출처 구분

  • todos.calendar_source 컬럼 추가, 모든 캘린더 투두 쿼리를 출처 조건으로 조회
  • 투두 상태 컬럼을 출처 공통으로 이름 변경
    • deleted_from_google → deleted_from_calendar
    • disconnected_from_google → disconnected_from_calendar
  • 응답에 공통 필드 추가 : isCalendarEvent, calendarSource, isDeletedFromCalendar, isDisconnectedFromCalendar
    • 기존 구글 필드(isGoogleEvent 등)는 공통 값으로 계산해 그대로 유지

오류 코드

  • CalendarErrorCode 하나에서 구글 전용 항목은 GOOGLE_ 접두어로 변경 (errorCode 문자열도 GOOGLE_CALENDAR_xxx로 변경)
  • 공통 항목(CALENDAR_400, CALENDAR_404, CALENDAR_500)은 유지

구글 연동 API URL 변경 (애플 /calendar/apple과 형식 통일, 기존 경로는 유지하지 않음)

  • GET /api/v1/users/calendar/authorize → GET /api/v1/users/calendar/google/authorize
  • POST /api/v1/users/calendar → POST /api/v1/users/calendar/google
  • DELETE /api/v1/users/calendar → DELETE /api/v1/users/calendar/google
  • 프론트 콜백 경로(/oauth/calendar/callback)와 구글 콘솔 리디렉션 설정은 변경 없음
  • URL·errorCode 변경으로 서버와 웹을 같은 시점에 배포해야 함

일정 조회·동기화 API

  • GET /api/v1/users/calendar/events : 연동된 모든 캘린더 일정을 합쳐 조회하도록 확장 (현재는 구글만)
    • 일정마다 출처(calendarSource) 필드 추가
  • POST /api/v1/users/calendar/events/sync : 연동된 모든 캘린더를 동기화하도록 확장 (현재는 구글만)
  • 둘 다 연동된 캘린더가 없을 때만 404 CALENDAR_404

⚠️ 배포 시 운영 DB 작업 필요 (ddl-auto: update는 컬럼 이름 변경·데이터 보정을 하지 않음)

ALTER TABLE todos RENAME COLUMN deleted_from_google TO deleted_from_calendar;
ALTER TABLE todos RENAME COLUMN disconnected_from_google TO disconnected_from_calendar;
ALTER TABLE todos ADD COLUMN calendar_source VARCHAR(20) NULL;
UPDATE todos SET calendar_source = 'GOOGLE' WHERE external_event_id IS NOT NULL;
  • 반드시 새 버전 배포 전에 실행 : 새 버전이 먼저 뜨면 ddl-auto가 빈 deleted_from_calendar 컬럼을 새로 만들어 기존 값이 이어지지 않음
  • 이름 변경 후에는 구버전 서버가 컬럼을 찾지 못하므로 구버전 중지 → SQL 실행 → 새 버전 배포 순서로 진행 (짧은 중단 발생)
  • 정확한 컬럼 타입과 실행 시점은 PR에서 확정

Todo ✔️

  • 리팩토링 전 일정 투두 동기화 로직(CalendarTodoSynchronizer)의 현재 동작을 테스트로 고정
  • 관련 API 명세서 수정 (구글 URL·errorCode 변경, 일정 조회·동기화 통합, 투두 응답 공통 필드) — 리팩토링 완료 후 작성
  • CalendarSource enum 추가, Todo에 출처 컬럼 추가 및 상태 컬럼 이름 변경
  • 공통 일정 형식·공급자 인터페이스 추가, 구글 구현체로 기존 조회 로직 이전
  • 투두 동기화·연동 해제 로직을 출처 기반 공통 로직으로 분리
  • 구글 전용 코드(OAuth, 토큰, 연결 정보, 클라이언트)를 calendar/google/로 이동, 회원 탈퇴(AuthService)의 구글 연결 참조 수정
  • 구글 연동·해제·인증 URL API 경로에 /google 추가
  • 일정 조회·동기화 API를 연동된 모든 캘린더 대상으로 확장
  • 구글 전용 오류 코드에 GOOGLE_ 접두어 적용
  • 홈·오늘·투두 상세 응답에 공통 필드 추가, 수정·삭제 제한을 공통 판단으로 변경
  • 고정한 테스트와 로컬 구글 계정으로 구글 동작 유지 확인, 배포 SQL·순서 정리
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions