설정 안내 정리
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
- 닉네임은 공개 작성자 이름에 직접 반영되는 정보라 악용 가능성을 줄이기 위해 2주 제한을 두는 편이 맞다고 판단했다. 초기 가입 시점의 닉네임도 같은 규칙에 포함되도록 가입 시각을 기본 기준선으로 삼는다.
|
||||
- 다만 이 제한은 테스트와 운영 상황에 따라 조절할 수 있어야 하므로, 기간 자체는 코드 고정보다 환경변수로 바꾸는 편이 맞다고 정리했다. `0`으로 꺼서 QA하거나, `1일` 같은 짧은 값으로 운영 실험을 할 수 있어야 한다.
|
||||
- 프로필 이미지는 자주 다루지 않는 항목이고 변경 직후 결과를 바로 확인할 수 있으므로, 별도 저장 버튼보다 자동 저장이 더 자연스럽다고 정리했다. 대신 닉네임/비밀번호/로그아웃처럼 명시적 행위가 필요한 액션은 작은 아이콘 버튼으로 분리한다.
|
||||
- 닉네임 제한은 설정 본문에 계속 설명을 남기기보다, 버튼이 나타나는 조건과 모달 내부 안내로만 전달하는 편이 더 깔끔하다고 정리했다.
|
||||
|
||||
## 2026-04-07 v1.1.17
|
||||
- 가이드 모달은 같은 기능의 이동 수단을 중복으로 두기보다, 화살표와 점 네비게이션만 유지하는 편이 더 깔끔하다고 정리했다.
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
|
||||
## `/profile`
|
||||
- 화면 파일: `frontend/src/views/ProfileView.vue`
|
||||
- 역할: `settingsThemePanel` 계열 톤의 요약 카드 중심 설정 화면, 아바타 원형 버튼 클릭 기반 프로필 이미지 선택/삭제 즉시 저장, 닉네임 현재 상태와 변경 제한 안내 및 아이콘 버튼 기반 닉네임 변경 모달, 비밀번호 변경 아이콘 버튼, 이메일 읽기 전용 표시, 로그아웃 아이콘 버튼 처리
|
||||
- 역할: `settingsThemePanel` 계열 톤의 요약 카드 중심 설정 화면, 아바타 원형 버튼 클릭 기반 프로필 이미지 선택/삭제 즉시 저장, 닉네임 변경 가능 시점에만 노출되는 아이콘 버튼 기반 닉네임 변경 모달, 비밀번호 변경 아이콘 버튼, 이메일 읽기 전용 표시, 로그아웃 아이콘 버튼 처리
|
||||
- 연동 API: `GET /api/auth/me`, `POST /api/auth/profile`, `POST /api/auth/password`
|
||||
|
||||
## 공통 레이아웃
|
||||
|
||||
@@ -56,6 +56,7 @@
|
||||
- `A/ㅁ`: 관리자 계정일 때 관리자 화면으로 이동
|
||||
- 설정의 가이드 모달은 좌우 화살표, 점 네비게이션, 좌측 단계 목록으로만 이동하고, 설명 영역은 최소 4줄 높이를 유지해 페이지별 높이 차이를 줄인다.
|
||||
- 설정(`/profile`) 화면은 상시 입력 폼보다 `현재 상태 요약 카드 + 필요 시 모달 편집` 흐름을 기본으로 한다. 닉네임과 비밀번호는 작은 액션 버튼으로만 모달을 열어 변경하고, 이메일은 현재 로그인 계정 정보로 읽기 전용 표시를 유지한다. 프로필 이미지는 아바타 원형 버튼 자체를 눌러 변경하며, 선택/삭제 시 즉시 자동 저장한다.
|
||||
- 닉네임 카드 본문에는 제한 설명을 상시 노출하지 않고, 변경 가능한 시점에만 아이콘 버튼을 보여준다. 제한 안내는 닉네임 변경 모달과 가이드 문구에서만 전달한다.
|
||||
- 닉네임 변경 제한 기간은 기본 14일이지만, 서버 환경변수 `NICKNAME_CHANGE_INTERVAL_MS` 또는 `NICKNAME_CHANGE_INTERVAL_DAYS`로 조절할 수 있다. `0`이면 제한을 끈다. 인증 응답에는 `nicknameUpdatedAt`, `nicknameChangeAvailableAt`, `nicknameChangeIntervalMs`, `nicknameChangeIntervalLabel`를 함께 포함하고, 프로필 저장 API는 제한 기간 안의 닉네임 변경 요청에 `nickname_change_locked` 오류를 반환한다.
|
||||
- 왼쪽 공통 검색창은 현재 화면 범위만 검색한다.
|
||||
- 홈: 전체 공개 티어표
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
- 닉네임 변경 모달에서 제한 안내 문구와 실제 저장 차단 시점이 일치하는지, 제한 중에는 버튼이 비활성화되고 다음 가능 시각이 자연스럽게 보이는지 확인한다.
|
||||
- `NICKNAME_CHANGE_INTERVAL_DAYS=1`, `NICKNAME_CHANGE_INTERVAL_MS=0` 같은 운영/테스트 값에서 설정 화면 문구와 백엔드 차단 동작이 함께 바뀌는지 확인한다.
|
||||
- 설정 화면의 아이콘 버튼(`닉네임 변경`, `비밀번호 변경`, `로그아웃`)이 좁은 화면에서도 겹치지 않고, `title/aria-label` 기준 접근성도 자연스러운지 확인한다.
|
||||
- 닉네임 변경 제한 중일 때 설정 카드에서 아이콘이 완전히 사라지는 흐름이 사용성 측면에서 충분히 명확한지 실제 계정으로 확인한다.
|
||||
- 오래전에 가입한 기존 계정은 `nickname_updated_at` 백필 후에도 바로 변경 가능하고, 최근 가입/최근 변경 계정은 정확히 14일 제한이 걸리는지 서버 기준으로 확인한다.
|
||||
- 비밀번호 변경이 요약 카드의 작은 액션으로만 열리더라도 접근성이 떨어지지 않는지, 모달 `Esc` 닫기와 포커스 이동이 자연스러운지 확인한다.
|
||||
- `v1.1.17` 이후 설정의 가이드 모달에서 페이지를 넘길 때 썸네일 영역 위치가 이전보다 안정적으로 유지되는지 확인한다.
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
- 닉네임 변경 제한 기간은 고정 14일 상수가 아니라 환경변수로 바꿨다. `NICKNAME_CHANGE_INTERVAL_MS` 또는 `NICKNAME_CHANGE_INTERVAL_DAYS`로 조절할 수 있고, `0`이면 제한을 끌 수 있다. 프런트 문구도 응답의 `nicknameChangeIntervalLabel`을 따라가도록 맞췄다.
|
||||
- 프로필 이미지 요약 카드는 제거하고, 아바타 선택/삭제 시 즉시 저장되는 자동 저장 흐름으로 바꿨다. 비밀번호 변경과 로그아웃 액션은 좁은 화면에서도 문구가 뭉개지지 않도록 아이콘 버튼(`key.svg`, `logout.svg`)으로 바꿨다.
|
||||
- 닉네임은 `open_in_new.svg` 아이콘 버튼으로 모달을 여는 구조로 정리했고, 이메일은 현재 백엔드 기능 범위를 유지해 읽기 전용 상태임을 카드 안에서 더 명확히 표시했다.
|
||||
- 닉네임 카드 본문에서는 변경 제한 설명을 제거하고, 실제 변경 가능한 시점에만 아이콘 버튼이 나타나도록 바꿨다. 제한 안내는 닉네임 변경 모달 안에서만 `한 번 변경하면 X가 지나야 다시 바꿀 수 있다`는 문구로 보여준다.
|
||||
- 설정 가이드 마지막 단계에도 닉네임 변경 버튼은 제한 기간이 지나야 다시 나타난다는 안내를 추가했다.
|
||||
- 확인: `node --check backend/src/db.js`, `node --check backend/src/routes/auth.js`, `npm run build`
|
||||
|
||||
## 2026-04-07 v1.1.17
|
||||
|
||||
@@ -157,7 +157,7 @@ const guideSteps = [
|
||||
title: '단축키로 빠른 조작',
|
||||
summary: '사이드 패널과 전체 화면을 키보드로 빠르게 전환합니다.',
|
||||
description:
|
||||
'[ 키는 왼쪽 사이드를 열고 닫고, ] 키는 오른쪽 사이드를 열고 닫습니다. F/ㄹ은 전체 화면, S/ㄴ은 검색 포커스(편집 화면에서는 아이템 검색), G/ㅎ은 그리드 보기, L/ㅣ는 리스트 보기입니다. 각종 모달은 Esc 키로 닫을 수 있고, 입력칸에 글을 쓰는 중에는 단축키가 동작하지 않도록 처리되어 있습니다.',
|
||||
'[ 키는 왼쪽 사이드를 열고 닫고, ] 키는 오른쪽 사이드를 열고 닫습니다. F/ㄹ은 전체 화면, S/ㄴ은 검색 포커스(편집 화면에서는 아이템 검색), G/ㅎ은 그리드 보기, L/ㅣ는 리스트 보기입니다. 설정 화면의 닉네임 변경 버튼은 변경 가능 기간이 지난 뒤에만 다시 나타납니다. 각종 모달은 Esc 키로 닫을 수 있고, 입력칸에 글을 쓰는 중에는 단축키가 동작하지 않도록 처리되어 있습니다.',
|
||||
},
|
||||
]
|
||||
const currentGuideStep = computed(() => guideSteps[guideStepIndex.value] || guideSteps[0])
|
||||
|
||||
@@ -72,11 +72,6 @@ const canChangeNicknameNow = computed(() => {
|
||||
if (!nicknameUpdatedAt.value) return true
|
||||
return Date.now() >= nicknameChangeAvailableAt.value
|
||||
})
|
||||
const nicknameCooldownText = computed(() => {
|
||||
if (nicknameChangeIntervalMs.value <= 0) return '닉네임 변경 제한이 없습니다.'
|
||||
if (!nicknameUpdatedAt.value || canChangeNicknameNow.value) return `닉네임은 ${nicknameChangeIntervalLabel.value}에 한 번만 변경할 수 있어요.`
|
||||
return `다음 변경 가능 시점: ${formatDateTime(nicknameChangeAvailableAt.value)}`
|
||||
})
|
||||
onMounted(async () => {
|
||||
if (!auth.hydrated) await auth.refresh()
|
||||
if (!auth.user) {
|
||||
@@ -360,9 +355,9 @@ async function logout() {
|
||||
<div class="settingsSummaryItem__valueRow">
|
||||
<div class="settingsSummaryItem__value">{{ nickname || '미설정' }}</div>
|
||||
<button
|
||||
v-if="canChangeNicknameNow"
|
||||
class="settingsIconAction"
|
||||
type="button"
|
||||
:disabled="!canChangeNicknameNow"
|
||||
aria-label="닉네임 변경"
|
||||
title="닉네임 변경"
|
||||
@click="openNicknameModal"
|
||||
@@ -370,7 +365,6 @@ async function logout() {
|
||||
<SvgIcon :src="openInNewIcon" :size="18" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="settingsSummaryItem__meta">{{ nicknameCooldownText }}</div>
|
||||
</div>
|
||||
|
||||
<div class="settingsSummaryItem">
|
||||
@@ -379,7 +373,7 @@ async function logout() {
|
||||
<div class="settingsSummaryItem__value">{{ authEmail }}</div>
|
||||
<span class="settingsSummaryItem__status">읽기 전용</span>
|
||||
</div>
|
||||
<div class="settingsSummaryItem__meta">현재 로그인에 사용하는 계정 이메일입니다. 지금은 설정 화면에서 직접 변경하지 않습니다.</div>
|
||||
<div class="settingsSummaryItem__meta">현재 로그인에 사용하는 계정 이메일입니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -430,7 +424,7 @@ async function logout() {
|
||||
<div id="nicknameModalTitle" class="settingsModalCard__title">닉네임 변경</div>
|
||||
<div class="settingsModalCard__desc">
|
||||
닉네임은 공개 티어표의 작성자 이름으로 보이며,
|
||||
{{ nicknameChangeIntervalMs > 0 ? `악용 방지를 위해 ${nicknameChangeIntervalLabel}에 한 번만 변경할 수 있어요.` : '현재는 변경 주기 제한이 없습니다.' }}
|
||||
{{ nicknameChangeIntervalMs > 0 ? `한 번 변경하면 ${nicknameChangeIntervalLabel}이 지나야 다시 바꿀 수 있어요.` : '현재는 변경 주기 제한이 없습니다.' }}
|
||||
</div>
|
||||
<label class="field">
|
||||
<span class="field__label">새 닉네임</span>
|
||||
@@ -741,6 +735,7 @@ async function logout() {
|
||||
margin-top: 4px;
|
||||
color: var(--theme-text-muted);
|
||||
line-height: 1.6;
|
||||
word-break: keep-all;
|
||||
}
|
||||
|
||||
.field {
|
||||
|
||||
Reference in New Issue
Block a user