Skip to content

[FEAT] 로그인 가드에서 사용자 시간대(IANA) 감지 후 서버 동기화 - #201

Merged
kimminna merged 2 commits into
developfrom
feat/web/199-sync-timezone-on-auth-guard
Jul 14, 2026
Merged

[FEAT] 로그인 가드에서 사용자 시간대(IANA) 감지 후 서버 동기화#201
kimminna merged 2 commits into
developfrom
feat/web/199-sync-timezone-on-auth-guard

Conversation

@kimminna

@kimminna kimminna commented Jul 14, 2026

Copy link
Copy Markdown
Member

ISSUE 🔗

close #199



What is this PR? 🔍

로그인 시 브라우저의 IANA 시간대를 감지해 서버에 동기화하는 로직을 추가했습니다. 최초 구현은 로그인 가드(AuthGuardProvider)에서 accessToken 존재 여부를 기준으로 동기화했는데, 새로고침·재발급마다 불필요하게 재호출되는 문제가 있어 실제 로그인이 일어나는 OAuth 콜백 시점으로 옮겼습니다.

배경

  • 기존 구조: 서버는 사용자의 시간대 정보 없이 홈 화면의 '오늘' 판정 등 날짜 계산을 수행하고 있었습니다.
  • 발생 문제: 최초 구현은 AuthGuardProvider에서 accessToken 변화를 기준으로 삼았습니다. accessTokenlocalStorage에 저장돼 있어 새로고침마다 컴포넌트가 리마운트되고, dedup에 쓰던 useRef가 매번 초기화되어 같은 토큰 값이어도 새로고침할 때마다 PATCH가 재전송됐습니다. 401 재발급(reissue) 때도 토큰 문자열이 바뀌어 다시 트리거됐습니다.
  • 해결 방향: 시간대 동기화 호출을 실제 로그인이 성공하는 시점(OAuth 콜백)으로 옮겨, 새로고침이나 토큰 재발급으로는 재호출되지 않고 로그인할 때 한 번만 호출되도록 변경했습니다.

시간대 동기화 위치 이동 (AuthGuardProvider → OauthCallbackContainer)

  • 변경 요약: useUpdateTimezone mutation 호출을 AuthGuardProvider에서 제거하고, OauthCallbackContainer의 토큰 교환 성공(onSuccess) 콜백 안으로 옮겼습니다.

  • 이유: AuthGuardProvider는 인증된 모든 화면(온보딩, (main) 레이아웃 하위 전체)을 감싸는 가드라서 새로고침마다 다시 마운트됩니다. 그 안에서 dedup에 쓰던 useRef는 컴포넌트 생명주기에 묶여 있어 페이지 새로고침 시 리셋되는 것을 막을 수 없었습니다. 반면 OauthCallbackContainer는 실제 OAuth 로그인이 성공했을 때만 렌더링되는 화면이라 "로그인 시점에 한 번"이라는 의도를 컴포넌트 위치만으로 보장할 수 있습니다.

  • 구현 방식: OauthCallbackContainer의 토큰 교환 onSuccess에서 setAccessToken 직후 시간대를 동기화합니다.

    onSuccess: ({ data }) => {
      setAccessToken(data.accessToken);
      setOnboardingCompleted(data.user.onboardingCompleted);
    
      const zoneId = Intl.DateTimeFormat().resolvedOptions().timeZone;
      updateTimezone({ data: { zoneId } });
    
      router.replace(data.isNewUser ? ROUTES.ONBOARDING : ROUTES.HOME);
    }

    AuthGuardProvider는 다시 인증 가드(비로그인 시 /login 리다이렉트) 역할만 담당하도록 되돌렸습니다.

  • 경계 · 제약: 401 인터셉터의 accessToken 재발급(axios.ts)에서는 더 이상 시간대를 재동기화하지 않습니다 — 재발급은 로그인이 아니라 세션 유지이므로 이번 범위에서는 제외했습니다. 로그인 상태를 유지한 채 기기 시간대를 변경한 사용자는 재로그인 전까지 서버에 반영되지 않는데, 이 트레이드오프는 의도된 단순화이며 필요하면 후속 작업으로 남깁니다.



To Reviewers

이전 리뷰에서 새로고침·재발급마다 값이 같아도 재호출되는 점을 지적해주셔서, 실제 로그인 시점(OAuth 콜백)에만 호출하도록 변경했습니다. 다만 로그인 상태를 유지한 채 시간대를 바꾼 사용자는 재로그인하기 전까지는 서버에 반영되지 않는데, 이 트레이드오프가 괜찮은지 확인 부탁드립니다.



Screenshot 📷



Test Checklist ✔

  • pnpm check-types 통과
  • pnpm lint 통과
  • 실제 로그인 플로우에서 Network 탭으로 PATCH 요청이 로그인 시점에만 전송되는지 확인 — 미실행: 브라우저 수동 확인 필요

- accessToken 확보 시 Intl.DateTimeFormat으로 IANA 시간대를 감지해 useUpdateTimezone PATCH를 호출하도록 추가했습니다
- syncedTokenRef로 같은 토큰에 대해 중복 PATCH가 발생하지 않도록 했습니다
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
timo Ready Ready Preview, Comment Jul 14, 2026 4:57pm

Request Review

@github-actions github-actions Bot added the ⏰ Timo-web Timo 웹 서비스 label Jul 14, 2026
@github-actions github-actions Bot added ✨ Feature 새로운 기능(기능성) 구현 ♦️ 민아 민아상 labels Jul 14, 2026
@coderabbitai

coderabbitai Bot commented Jul 14, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kimminna, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 12 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: a76bc9c4-59d8-42d9-b6e2-ddb3f1c72e3d

📥 Commits

Reviewing files that changed from the base of the PR and between a5349df and 8806763.

📒 Files selected for processing (1)
  • apps/timo-web/app/[locale]/oauth/callback/_containers/OauthCallbackContainer.tsx

Walkthrough

AuthGuardProvideraccessToken 확보 또는 변경 시 클라이언트의 IANA 시간대를 감지하고, 동일 토큰에 대한 중복 요청을 방지하면서 updateTimezone을 호출하도록 변경되었습니다.

Changes

인증 시간대 동기화

Layer / File(s) Summary
토큰 기반 시간대 동기화
apps/timo-web/providers/auth/AuthGuardProvider.tsx
useRef로 마지막 동기화 토큰을 추적하고, 인증 토큰이 변경되면 Intl.DateTimeFormat().resolvedOptions().timeZone을 조회해 updateTimezone({ zoneId })를 호출합니다. useEffect 문서, useRef 문서

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: ehye1

Sequence Diagram(s)

sequenceDiagram
  participant AuthGuardProvider
  participant Intl.DateTimeFormat
  participant useUpdateTimezone
  AuthGuardProvider->>Intl.DateTimeFormat: resolvedOptions().timeZone 조회
  Intl.DateTimeFormat-->>AuthGuardProvider: IANA timezone 반환
  AuthGuardProvider->>useUpdateTimezone: updateTimezone({ zoneId }) 호출
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed IANA 감지, useUpdateTimezone 연동, 토큰당 1회 호출이 구현되어 이슈 요구사항을 충족합니다.
Out of Scope Changes check ✅ Passed 변경 범위가 AuthGuardProvider의 시간대 동기화에만 맞춰져 있어 별도 범위 이탈은 보이지 않습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed 로그인 가드에서 IANA 시간대를 감지해 서버와 동기화한다는 핵심 변경을 정확히 요약했습니다.
Description check ✅ Passed 시간대 동기화와 로그인 시점 처리 의도를 설명해 변경 사항과 충분히 관련 있습니다.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web/199-sync-timezone-on-auth-guard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown

Timo Performance Report

Bundle Size — timo-web
라우트 크기 First Load JS
/[locale]/home 209.56 kB 🔴 415.42 kB
/[locale]/today 192.90 kB 🔴 398.76 kB
/[locale]/focus 159.08 kB 🔴 364.93 kB
/[locale]/settings 166.24 kB 🔴 372.09 kB
/[locale]/statistics 232.88 kB 🔴 438.74 kB
/[locale]/[...rest] 0 B 🟡 205.86 kB
/[locale]/login 212.94 kB 🔴 418.79 kB
/[locale]/oauth/callback 119.65 kB 🟡 325.50 kB
/[locale]/onboarding 232.84 kB 🔴 438.70 kB
/[locale] 118.96 kB 🟡 324.82 kB
/[locale]/policy 125.07 kB 🟡 330.92 kB

공유 번들: 205.86 kB
🟢 < 200kB  |  🟡 < 350kB  |  🔴 ≥ 350kB (First Load JS · gzip)

Lighthouse — timo-web
URL Perf A11y LCP CLS TBT
/en/home 🔴 68 🟢 95 🔴 15.5s 🟢 0.000 🟡 292ms
/en/today 🔴 60 🟢 95 🔴 15.5s 🟢 0.000 🟡 574ms
/en/focus 🔴 57 🟢 95 🔴 15.2s 🟢 0.000 🔴 700ms
/en/statistics 🔴 61 🟢 95 🔴 15.2s 🟢 0.000 🟡 528ms

Perf ≥ 70 / A11y ≥ 85 목표
LCP 🟢 < 2.5s 🟡 < 4s 🔴 ≥ 4s  |  CLS 🟢 < 0.1 🟡 < 0.25 🔴 ≥ 0.25  |  TBT 🟢 < 200ms 🟡 < 600ms 🔴 ≥ 600ms

Image Optimization — timo-web
파일 크기 포맷 상태
images/google-calendar.png 36.20 kB PNG ⚠️ 🟢
images/google-logo.png 26.79 kB PNG ⚠️ 🟢

총 2개 · 63.00 kB  |  🟢 < 200KB  |  🟡 < 500KB  |  🔴 ≥ 500KB
⚠️ 2개 파일 WebP/AVIF 변환 권장

측정 커밋: 36f48f1

- 타임존 동기화 로직을 로그인 가드(AuthGuardProvider)에서 OAuth 콜백(OauthCallbackContainer)으로 옮겼습니다
- accessToken이 localStorage에 남아있는 상태로 새로고침될 때마다 컴포넌트가 리마운트되어 동기화 API가 매번 재호출되던 문제를 해결했습니다
- 이제 실제 로그인이 성공하는 시점에만 서버로 타임존이 동기화됩니다

@jjangminii jjangminii left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

타임존을 언제 보내야하나 고민했었는데 확실히 아직은 로그인시에만 보내는게 맞다고 생각이 드네요..
고생하셨습니다~ 여행가서 테스트해보고싶어요

@kimminna
kimminna merged commit e46922b into develop Jul 14, 2026
11 checks passed
@kimminna
kimminna deleted the feat/web/199-sync-timezone-on-auth-guard branch July 14, 2026 18:55
@kimminna kimminna mentioned this pull request Jul 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feature 새로운 기능(기능성) 구현 ⏰ Timo-web Timo 웹 서비스 ♦️ 민아 민아상

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 로그인 가드에서 사용자 시간대(IANA) 감지 후 서버 동기화

2 participants