Skip to content

feat: name/nickname 표시 정책 적용 - #74

Merged
evenif99 merged 6 commits into
devfrom
feature/name-nickname-policy
Jun 20, 2026
Merged

evenif99 merged 6 commits into
devfrom
feature/name-nickname-policy

Conversation

@evenif99

@evenif99 evenif99 commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • name 필드 우선 표시 정책 적용 (name이 있으면 name, 없으면 nickname)
  • 개인정보 수정 페이지에 이름(name), 닉네임(nickname), MBTI 수정 폼 구현
  • 마이페이지 메인 하드코딩 제거 → useUserMe() 연결
  • API_SPEC.md GET/PATCH 응답에 name 필드 반영

변경 파일

  • docs/API_SPEC.md — GET/PATCH 응답 스펙에 name 필드 추가
  • src/app/(page)/mypage/edit/page.tsx — 프로필 수정 폼 (name, nickname, MBTI)
  • src/app/(page)/mypage/edit/page.module.scss — 수정 페이지 스타일
  • src/app/(page)/mypage/page.tsx — 하드코딩 제거, useUserMe 동적 표시
  • src/components/home/HomeGreeting.tsx — name ?? nickname 우선순위 적용
  • src/domains/user/constants.ts — MBTI 옵션 상수

Test plan

  • 홈 화면 인사말에 name 우선 표시 확인
  • 마이페이지 메인에서 DB 데이터 기반 이름/MBTI 표시 확인
  • 개인정보 수정 페이지에서 이름, 닉네임, MBTI 수정 동작 확인
  • 닉네임 중복 시 에러 메시지 표시 확인
  • name이 null인 사용자는 nickname으로 fallback 표시 확인

🤖 Generated with Claude Code

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능
    • 사용자 프로필 API에 name(null 허용) 필드 추가
  • 개선 사항
    • 프로필/인사말 표시에서 name 우선, 없으면 nickname 표시
    • 마이페이지에서 MBTI는 데이터가 있을 때만 표시
    • 회원가입 후 프로필 초기 처리를 최적화
  • 문서
    • 사용자 API 명세 업데이트

evenif99 and others added 3 commits June 19, 2026 13:04
- 로그인 시 user_terms_agreements 테이블에 service, privacy 약관 동의 레코드 자동 생성
- saveFirstLoginFields에서 $transaction으로 유저 업데이트와 약관 동의 레코드 생성을 원자적 처리
- 약관 버전 상수 정의 (날짜 기반: 2026-06-18)
- 기존 유저 대상 backfill 스크립트 추가 (scripts/backfill-user-terms-agreements.ts)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- API 라우트 디렉토리 이동 (src/app/api/user/me → src/app/api/users/me)
- domains/user/hooks.ts 내 API 호출 경로 일괄 수정

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add name field priority across the application: display name when
available, fall back to nickname otherwise. Implement profile edit
page with name, nickname, and MBTI fields. Remove hardcoded values
from mypage main.

- GET/PATCH /api/users/me: add name field to response and request
- HomeGreeting: use name ?? nickname for greeting
- MyPage main: replace hardcoded nickname/MBTI with useUserMe data
- Profile edit page: full form with name, nickname, MBTI, avatar
- API_SPEC.md: update GET/PATCH docs with name field

Co-Authored-By: Claude <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
talky-owl Ready Ready Preview, Comment Jun 20, 2026 5:09am
talky-owl-xqdp Ready Ready Preview, Comment Jun 20, 2026 5:09am

@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

API 스펙에 사용자 name 필드와 표시 우선순위 규칙(name 우선, null이면 nickname)을 추가했다. 백엔드 엔드포인트와 클라이언트 타입에 name 필드를 반영하고, 인증 로직에서 name 존재 시 닉네임 생성 루프를 건너뛰는 분기를 추가했다. 마이페이지와 홈 인사말 컴포넌트가 name 우선 displayName을 적용하도록 변경되었다. 동시에 방 참여/초대 엔드포인트에서 감사 및 접근 로그 기록을 제거했다.

Changes

name 필드 추가 및 표시 우선순위 적용

Layer / File(s) Summary
API 스펙: name 필드 및 표시 우선순위 규칙 명세화
docs/API_SPEC.md
GET /api/users/me 응답에 name: string | null 추가, nickname 타입을 string | null로 변경. PATCH 요청 바디에 name(150자), nickname(220자) 제약 명세화, 응답 스키마도 동일하게 업데이트. GET 처리 정책에 name 우선 표시 규칙 추가.
백엔드 엔드포인트 및 사용자 프로필 타입: name 필드 추가
src/app/api/user/me/route.ts, src/domains/user/api.ts
UserMeDtoUserProfile 인터페이스에 name: string | null 필드 추가. GET 핸들러의 Prisma select과 응답 data에 name 포함. PATCH 핸들러도 update select 및 응답 data에 name 포함.
인증 로직: saveFirstLoginFields name 기반 분기 및 createUser 정리
src/lib/auth/index.ts
saveFirstLoginFields 초기에 prisma.user.findUniquename 존재 여부 조회, name 있으면 닉네임 생성 루프 건너뛰고 kakaoId·termsAgreedAt 업데이트 및 userTermsAgreement.createMany(skipDuplicates: true) 수행 후 즉시 반환. events.createUser에서 kakao providerAccountId 조회 후 존재 시에만 saveFirstLoginFields 호출로 정리.
UI 컴포넌트: name 우선 displayName 적용
src/app/(page)/mypage/page.tsx, src/components/home/HomeGreeting.tsx
MyPage에서 useUserMe 훅으로 user?.name ?? user?.nickname 우선순위의 displayName 계산, 프로필 이름 렌더링에 적용. user.mbti 존재 시에만 배지 조건부 렌더링. HomeGreeting도 동일 논리로 인사말 구성.

감사 및 접근 로그 기록 제거

Layer / File(s) Summary
방 초대 엔드포인트: 감사 로그 제거
src/app/api/rooms/[id]/invite/route.ts
POST /api/rooms/:id/invite에서 disputeRoom 업데이트 직후 INVITE_LINK_CREATED 감사 로그(prisma.auditLog.create 및 예외 무시) 제거, 곧바로 inviteUrl 생성 및 응답 반환으로 진행.
방 참여 엔드포인트: 접근 및 감사 로그 제거
src/app/api/rooms/join/[token]/route.ts
GET과 POST 핸들러에서 토큰 유효성, 만료 처리, 충돌 체크, 성공 응답 등 모든 분기에서 roomAccessLog.create()auditLog.create() 호출 제거. 응답 반환 로직은 유지.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25분

Possibly related PRs

  • I5-Project/TALKY-OWL#36: docs/API_SPEC.mdGET/PATCH /api/users/me 사용자 프로필 필드(name 추가, nickname null 허용, 표시 우선순위) 변경이 해당 PR의 User 엔드포인트 API 스펙 작업과 직접 겹침.
  • I5-Project/TALKY-OWL#50: 두 PR 모두 src/lib/auth/index.ts의 Kakao 최초 로그인 처리(saveFirstLoginFields, kakaoId 저장, nickname 생성, termsAgreedAt 설정) 로직을 수정함.
  • I5-Project/TALKY-OWL#72: 두 PR 모두 saveFirstLoginFields의 기존 사용자 분기 처리와 CURRENT_TERMS_VERSIONS 기반 userTermsAgreement 트랜잭션 생성, createUser 이벤트 정리를 직접 수정함.

🐰 이름이 생겼어요, name 필드가 왔어요
nickname보다 name이 먼저 인사해요
첫 로그인 때도 이름 있으면 쏙 건너뛰고
약관 이력 척척 만들어 트랜잭션 완료~
마이페이지도 홈도 이제 진짜 내 이름! 🦉

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning Summary, 변경 파일, Test plan을 포함하고 있으나 저장소의 필수 PR 템플릿의 대부분 섹션(작업 내용, 담당 영역, Issue, 범위 확인, 보안 확인 등)이 누락되어 있습니다. PR 템플릿의 모든 필수 섹션을 작성하세요: 작업 내용, 담당 영역(profile-mypage 체크), 관련 Issue, 작업 범위 확인, 보안/개인정보 확인, DB/API 변경 여부 등.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항인 'name/nickname 표시 정책 적용'을 명확하게 요약하고 있으며, 전체 변경사항과 잘 일치합니다.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/name-nickname-policy

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

- src/app/api/user/me/route.ts: dev 버전 유지 (프로필 이미지 업로드 포함)
- src/app/api/users/me/route.ts: dev 버전 유지
- src/app/(page)/mypage/edit/page.tsx: dev 버전 유지 (profileEditStore 사용)
- src/app/(page)/mypage/edit/page.module.scss: dev 버전 유지
- src/domains/user/hooks.ts: dev 버전 유지 (api 모듈 import 구조)
- src/domains/user/constants.ts: dev 버전 유지 (없음 옵션 포함)
- src/lib/auth/index.ts: 양쪽 변경사항 병합 (user.name 체크 + skipDuplicates)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 24 hours (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/lsgs-projects-34d31fd6?upgradeToPro=build-rate-limit

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/API_SPEC.md`:
- Around line 336-337: The API specification document defines "name" and
"nickname" fields in the GET response contract (lines 336-337 and 358), but the
implementation in the route handler (src/app/api/users/me/route.ts at lines
8-41) does not retrieve or return these fields. Update the route handler to
query and include the "name" and "nickname" fields in the response object so
that the actual implementation matches the API specification contract.
- Around line 375-376: The PATCH request/response specification in the
API_SPEC.md file defines name as a 1-50 character optional field and nickname as
a 2-20 character optional field, but the PATCH handler in the user/me route does
not match these constraints. Update the PATCH handler in
src/app/api/user/me/route.ts to add validation for the name field (1-50
characters) and fix the nickname validation to enforce a 2-20 character range
instead of the current 2-100 character range to align the implementation with
the documented API specification.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: e3b59962-16a7-411d-b40c-d46fef9597df

📥 Commits

Reviewing files that changed from the base of the PR and between a6b441e and 1643b52.

📒 Files selected for processing (4)
  • docs/API_SPEC.md
  • src/app/(page)/mypage/page.tsx
  • src/components/home/HomeGreeting.tsx
  • src/lib/auth/index.ts

Comment thread docs/API_SPEC.md
Comment on lines +336 to +337
"name": "string | null",
"nickname": "string | null",

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

GET 응답 명세와 실제 구현 DTO가 불일치합니다.

Line 336-337, Line 358에서 name을 응답 계약에 추가했지만, 제공된 구현 스니펫(src/app/api/users/me/route.ts:8-41)은 name을 조회/반환하지 않습니다. 현재 상태면 name 우선 표시 정책이 서버 응답에서 성립하지 않습니다.

예시 수정안 (서버 구현 동기화)
 interface UserMeDto {
   id: string
+  name: string | null
   nickname: string | null
   mbti: string | null
 }

 const user = await prisma.user.findUnique({
   where: { id: userId },
-  select: { id: true, nickname: true, mbti: true },
+  select: { id: true, name: true, nickname: true, mbti: true },
 })

 return NextResponse.json<ApiResponse<UserMeDto>>({
   success: true,
-  data: { id: user.id, nickname: user.nickname, mbti: user.mbti },
+  data: { id: user.id, name: user.name, nickname: user.nickname, mbti: user.mbti },
 })

Also applies to: 358-358

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/API_SPEC.md` around lines 336 - 337, The API specification document
defines "name" and "nickname" fields in the GET response contract (lines 336-337
and 358), but the implementation in the route handler
(src/app/api/users/me/route.ts at lines 8-41) does not retrieve or return these
fields. Update the route handler to query and include the "name" and "nickname"
fields in the response object so that the actual implementation matches the API
specification contract.

Comment thread docs/API_SPEC.md
Comment on lines +375 to +376
"name": "string (optional, 1~50자)",
"nickname": "string (optional, 2~20자)",

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.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

PATCH 요청/응답 명세가 현재 서버 검증 로직과 맞지 않습니다.

Line 375-376, Line 390-391 기준으로 name(1~50)nickname(2~20) 계약을 명시했지만, 제공된 PATCH 스니펫(src/app/api/user/me/route.ts:103-141)은 name을 처리하지 않고 nickname을 2~100자로 검증합니다. 명세-구현 간 계약 불일치로 클라이언트/서버 통합 오류가 발생할 수 있습니다.

Also applies to: 390-391

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/API_SPEC.md` around lines 375 - 376, The PATCH request/response
specification in the API_SPEC.md file defines name as a 1-50 character optional
field and nickname as a 2-20 character optional field, but the PATCH handler in
the user/me route does not match these constraints. Update the PATCH handler in
src/app/api/user/me/route.ts to add validation for the name field (1-50
characters) and fix the nickname validation to enforce a 2-20 character range
instead of the current 2-100 character range to align the implementation with
the documented API specification.

- UserMeDto, UserProfile 타입에 name 필드 추가
- GET/PATCH /api/user/me select 및 응답에 name 포함
- Prisma schema에 모델이 없는 prisma.auditLog, prisma.roomAccessLog 호출 제거

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown

Deployment failed with the following error:

Resource is limited - try again in 1 day (more than 100, code: "api-deployments-free-per-day").

Learn More: https://vercel.com/lsgs-projects-34d31fd6?upgradeToPro=build-rate-limit

@coderabbitai coderabbitai Bot 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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/app/api/user/me/route.ts (2)

138-138: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

nickname 최대 길이 검증이 API 스펙과 불일치합니다.

API 스펙에서 nickname은 2~20자로 명세화되었으나, 현재 코드는 최대 100자까지 허용하고 있습니다. 이는 API 계약 위반이며 데이터 제약 조건과 맞지 않습니다.

🔧 최대 길이 수정 제안
-      if (!trimmed || trimmed.length < 2 || trimmed.length > 100) {
-        fieldErrors.push({ field: 'nickname', code: 'INVALID_NICKNAME', message: '닉네임은 2~100자로 입력해주세요.' })
+      if (!trimmed || trimmed.length < 2 || trimmed.length > 20) {
+        fieldErrors.push({ field: 'nickname', code: 'INVALID_NICKNAME', message: '닉네임은 2~20자로 입력해주세요.' })
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/api/user/me/route.ts` at line 138, The nickname maximum length
validation in the route handler is using 100 characters as the upper limit, but
according to the API specification, nickname should be limited to a maximum of
20 characters. Update the length check condition in the validation statement
where trimmed.length is compared against 100, changing it to 20 to align with
the documented API specification of 2-20 character range for nickname.

125-155: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

PATCH 핸들러에서 name 필드 처리가 누락되었습니다.

API 스펙에서 PATCH /api/users/me 요청 바디에 name 필드(1~50자)를 명세화했지만, 현재 PATCH 핸들러는 formData에서 name 필드를 전혀 처리하지 않습니다. email, nickname, mbti, profileImage는 처리하지만 name이 빠져있어 사용자가 프로필 수정 폼에서 이름을 업데이트할 수 없습니다.

name 필드 처리 로직을 추가해야 합니다.

🔧 name 필드 처리 추가 제안

nickname 처리 블록 이후에 name 처리 로직을 추가하세요:

     }
   }
 
+  const nameValue = formData.get('name')
+  if (nameValue !== null) {
+    const trimmed = String(nameValue).trim()
+    if (!trimmed || trimmed.length < 1 || trimmed.length > 50) {
+      fieldErrors.push({ field: 'name', code: 'INVALID_NAME', message: '이름은 1~50자로 입력해주세요.' })
+    } else {
+      data.name = trimmed
+    }
+  }
+
   const mbtiValue = formData.get('mbti')
   if (mbtiValue !== null) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/app/api/user/me/route.ts` around lines 125 - 155, The PATCH handler in
the user/me/route.ts is missing validation and processing for the name field,
which is required by the API specification with a length constraint of 1-50
characters. Add name field handling logic after the nickname processing block by
retrieving the 'name' value from formData, validating that it exists and meets
the 1-50 character length requirement, then either pushing a field error with
code 'INVALID_NAME' to fieldErrors if validation fails, or assigning the trimmed
name to data.name if validation succeeds. Follow the same pattern used for
nickname and email field processing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/app/api/user/me/route.ts`:
- Line 138: The nickname maximum length validation in the route handler is using
100 characters as the upper limit, but according to the API specification,
nickname should be limited to a maximum of 20 characters. Update the length
check condition in the validation statement where trimmed.length is compared
against 100, changing it to 20 to align with the documented API specification of
2-20 character range for nickname.
- Around line 125-155: The PATCH handler in the user/me/route.ts is missing
validation and processing for the name field, which is required by the API
specification with a length constraint of 1-50 characters. Add name field
handling logic after the nickname processing block by retrieving the 'name'
value from formData, validating that it exists and meets the 1-50 character
length requirement, then either pushing a field error with code 'INVALID_NAME'
to fieldErrors if validation fails, or assigning the trimmed name to data.name
if validation succeeds. Follow the same pattern used for nickname and email
field processing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI (base), Organization UI (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: a8807f35-b496-4b8b-9bbf-6feb0ddad983

📥 Commits

Reviewing files that changed from the base of the PR and between 1643b52 and 4866978.

📒 Files selected for processing (4)
  • src/app/api/rooms/[id]/invite/route.ts
  • src/app/api/rooms/join/[token]/route.ts
  • src/app/api/user/me/route.ts
  • src/domains/user/api.ts
💤 Files with no reviewable changes (2)
  • src/app/api/rooms/[id]/invite/route.ts
  • src/app/api/rooms/join/[token]/route.ts

@evenif99
evenif99 merged commit 31f4782 into dev Jun 20, 2026
3 checks passed
@evenif99
evenif99 deleted the feature/name-nickname-policy branch June 20, 2026 05:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant