Skip to content

feat: Vue 3 프론트엔드 기반 — Vite·Tailwind·Gradle 통합·SPA fallback·공통 인프라#120

Merged
heygw44 merged 2 commits into
mainfrom
infra/113
Jun 2, 2026
Merged

feat: Vue 3 프론트엔드 기반 — Vite·Tailwind·Gradle 통합·SPA fallback·공통 인프라#120
heygw44 merged 2 commits into
mainfrom
infra/113

Conversation

@heygw44

@heygw44 heygw44 commented Jun 2, 2026

Copy link
Copy Markdown
Owner

목적

M14 바닐라 데모 프론트를 폐기하고 Vue 3 + Vite + Pinia + Tailwind v4로 재구축하는 M15의 기반(blocker). frontend/에 프로젝트를 세우고, Gradle이 빌드 산출물을 src/main/resources/static/으로 출력해 같은 오리진(8080)에서 서빙한다. History(clean URL) 라우팅을 위한 Spring SPA fallback과 공통 인프라(API 클라이언트·auth 스토어·레이아웃)를 구축한다. 백엔드 REST API 계약(/api/v1/**)은 그대로 재사용.

주요 변경

프론트엔드 (frontend/)

  • Vite + Vue 3(JS) 스캐폴딩: vite.config(outDir→static, emptyOutDir, /api 프록시, @ alias), jsconfig, index.html, 레코드판 favicon.svg
  • Tailwind v4 CSS-first @theme 디자인 토큰(바이닐 블랙/크림/골드/러스트) + Pretendard
  • 공통 인프라(M14 로직 이식): api/client.js(axios — Bearer 자동·Idempotency-Key·401 refresh 1회 인플라이트 직렬화·ProblemDetail→ApiError), Pinia stores/auth.js(JWT 디코드·localStorage 키 유지)·stores/ui.js
  • 기능 골격: TheHeader/TheFooter/SearchBar/ToastHost + base 컴포넌트 + HomeView(앨범 목록)·NotFoundView + History 라우터

백엔드

  • com.groove.web.SpaRoutes(SPA 라우트 단일 소스) + SpaForwardConfig(명시적 화이트리스트 → forward:/index.html, /api·/actuator·/error 미포함)
  • SecurityConfig: SpaRoutes.PATTERNS GET permitAll 추가 (API 정책 불변), 정적 패턴에 favicon.svg
  • build.gradle.kts: node-gradle download=true(node 자동 다운로드 → CI 무변경) + frontendBuild(증분 캐싱) + processResources.dependsOn + clean 정리 + -PskipFrontend 가드
  • .gitignore: 빌드 산출물(static/node_modules 제외, M14 정적파일 제거

검증 (DoD)

  • ./gradlew check 그린 — 전체 테스트 + jacoco 커버리지 게이트 통과
  • npm run buildstatic/index.html+assets/ 출력(/assets/*·/favicon.svg 참조), emptyOutDir로 M14 잔재 제거
  • ./gradlew clean frontendBuild → node 자동 다운로드 + Vite 빌드 통합
  • ✅ 회귀 테스트 추가: /cart·/adminforward:/index.html(history fallback), /api/v1/admin/** 비인증 401 유지, 없는 /api/**는 SPA로 forward 안 됨(API/SPA 격리)
  • ./gradlew clean check -PskipFrontend → placeholder index.html로 통합 테스트 통과(node/npm 미실행)

런타임(브라우저) 확인은 ./gradlew bootRun(MySQL·local 프로파일) 또는 npm run dev(5173 프록시) 기동이 필요 — MockMvc full-context 테스트로 등가 검증됨.

코드 리뷰 반영 (extra-high recall)

  • -PskipFrontend 값 없이도 스킵(빈 문자열 가드) + 스킵 시 placeholder로 통합 테스트 404 방지
  • axios 응답 빈 본문 null 정규화(M14 fetch 래퍼 동작 보존)
  • 401 재시도 시 Idempotency-Key 재발급 방지(키 1회 고정)
  • crypto.randomUUID secure-context 폴백(lib/uuid)
  • BaseInput type=number 숫자 emit, formatWon 공용 추출(lib/format)
  • node 버전 단일 소스(.node-version) + SpaRoutes 동기화 의무 주석 강화

Closes #113

Summary by CodeRabbit

Release Notes

  • New Features

    • Vue 3 기반 모던 SPA 프론트엔드 출시
    • 상품 검색 기능 추가
    • 인증 플로우 (로그인/회원가입/로그아웃) 구현
    • 장바구니, 관리자 패널 UI 추가
    • Tailwind CSS 기반 반응형 디자인 적용
    • 토스트 알림 시스템 구현
  • Chores

    • Gradle 빌드에 Vite 프론트엔드 통합
    • 기존 정적 자산 교체

M14 바닐라 데모 프론트를 폐기하고 Vue 3 + Vite + Pinia + Tailwind v4 스택으로
재구축하는 M15의 기반(blocker)을 구축한다.

프론트엔드 (frontend/)
- Vite + Vue 3(JS) 스캐폴딩: vite.config(outDir→static, emptyOutDir, /api 프록시,
  @ alias), jsconfig, index.html, 레코드판 favicon
- Tailwind v4 CSS-first @theme 디자인 토큰(바이닐 블랙/크림/골드/러스트) + Pretendard
- 공통 인프라: axios client(Bearer 자동·Idempotency-Key·401 refresh 1회 인플라이트
  직렬화·ProblemDetail→ApiError), Pinia auth/ui 스토어(JWT 디코드·localStorage)
- 기능 골격: TheHeader/TheFooter/SearchBar/ToastHost·base 컴포넌트·HomeView·NotFound
  + History 라우터

백엔드
- SpaRoutes(SPA 라우트 단일 소스) + SpaForwardConfig(화이트리스트 forward:/index.html)
- SecurityConfig: SPA 라우트 GET permitAll 추가(API 정책 불변), favicon.svg 공개
- build.gradle.kts: node-gradle download=true(CI 무변경) + frontendBuild(증분 캐싱)
  + processResources 의존 + clean 정리 + -PskipFrontend 가드
- .gitignore: 빌드 산출물(static/)·node_modules 제외, M14 정적파일 제거

코드 리뷰 반영
- -PskipFrontend 값 없이도 스킵(빈 문자열 가드), 스킵 시 placeholder index.html 로
  통합 테스트 404 방지
- axios 응답 빈 본문 null 정규화(M14 fetch 래퍼 동작 보존)
- 401 재시도 시 Idempotency-Key 재발급 방지(키 1회 고정)
- crypto.randomUUID secure-context 폴백(lib/uuid)
- BaseInput type=number 숫자 emit, formatWon 공용 추출(lib/format)
- node 버전 단일 소스(.node-version)

Closes #113
@heygw44 heygw44 added this to the M15 - Vue Frontend milestone Jun 2, 2026
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@heygw44, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 43 minutes and 21 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 95528a2d-e1fa-4349-aa31-f0797416d042

📥 Commits

Reviewing files that changed from the base of the PR and between bde4154 and 15fb1ea.

📒 Files selected for processing (6)
  • frontend/src/assets/main.css
  • frontend/src/components/SearchBar.vue
  • frontend/src/components/ToastHost.vue
  • frontend/src/components/base/BaseInput.vue
  • frontend/src/views/HomeView.vue
  • src/test/java/com/groove/auth/security/SecurityConfigIntegrationTest.java

Walkthrough

Vue 3 및 Vite 기반 SPA를 Gradle과 통합하고, API 클라이언트·Pinia 상태 관리·Tailwind 스타일링을 구현하며 Spring SPA 라우팅을 설정합니다. 기존 바닐라 JS 프론트를 완전히 제거하고 통합 테스트를 업데이트합니다.

Changes

Vue 3 + Vite SPA 기반으로 마이그레이션

Layer / File(s) Summary
Gradle과 Node 빌드 통합
build.gradle.kts, frontend/.node-version, frontend/.gitignore
Node-Gradle 플러그인 추가, frontendBuild NpmTask 등록, processResources에서 정적 산출물 포함, -PskipFrontend 가드 추가, frontend/.node-version에서 22.12.0 읽기, clean 작업에서 src/main/resources/static 삭제.
Vite·Vue 프로젝트 스캐폴딩
frontend/index.html, frontend/package.json, frontend/vite.config.js, frontend/jsconfig.json, frontend/src/main.js
Vue 3 프로젝트 초기화, package.json에 Vite·Vue·Tailwind·Pinia·Axios 의존성 정의, vite.config.js에 build outDir(../src/main/resources/static), /api 프록시(5173→8080), @ 별칭 설정, index.html에서 #app 마운트 및 main.js 로드.
API 클라이언트 및 인증 흐름
frontend/src/api/client.js, frontend/src/api/auth.js, frontend/src/api/albums.js, frontend/src/lib/problem-detail.js, frontend/src/lib/uuid.js
Axios client baseURL /api/v1, Bearer 자동 첨부, 401 갱신 재시도(in-flight 공유), Idempotency-Key 생성, ProblemDetail → ApiError 변환, loginFlow/signupFlow/logoutFlow 함수, 앨범 공개 API 래퍼, UUID v4 생성기.
Pinia 상태 관리 및 유틸
frontend/src/stores/auth.js, frontend/src/stores/ui.js, frontend/src/lib/format.js
localStorage 기반 useAuthStore (토큰 저장, JWT 디코드, 사용자·권한 계산), useUiStore (토스트 알림, 검색어), 원화 포매팅 함수.
기본 UI 컴포넌트 및 레이아웃
frontend/src/App.vue, frontend/src/components/base/BaseButton.vue, frontend/src/components/base/BaseInput.vue, frontend/src/components/base/BaseSpinner.vue, frontend/src/components/TheHeader.vue, frontend/src/components/TheFooter.vue, frontend/src/components/SearchBar.vue, frontend/src/components/ToastHost.vue
루트 App 레이아웃 (TheHeader·RouterView·TheFooter·ToastHost), BaseButton (variant·loading), BaseInput (v-model·number 처리), BaseSpinner (size prop), 헤더 (로고·검색·네비게이션·로그아웃), 푸터, 검색 폼, 토스트 호스트.
라우팅 및 페이지 뷰
frontend/src/router/index.js, frontend/src/views/HomeView.vue, frontend/src/views/NotFoundView.vue
Vue Router clean history 모드, / → HomeView (앨범 목록 로드), /:pathMatch(.*)* → NotFoundView, 스크롤 상단 초기화.
Tailwind v4 디자인 시스템
frontend/src/assets/main.css
@theme 색상 토큰 (비닐/크림/골드/러스트), Pretendard 가변 폰트 로드, 전역 기본 스타일.
Spring SPA 라우팅 설정
src/main/java/com/groove/web/SpaRoutes.java, src/main/java/com/groove/web/SpaForwardConfig.java, src/main/java/com/groove/auth/security/SecurityConfig.java
SpaRoutes PATTERNS (/login, /signup, /cart, /checkout, /mypage, /me/**, /albums/** 등), WebMvcConfigurer로 해당 경로를 forward:/index.html, SecurityConfig에서 SPA 라우트 GET permitAll 추가, /favicon.svg 정적 공개.
통합 테스트 업데이트
src/test/java/com/groove/auth/security/SecurityConfigIntegrationTest.java
기존 /js/**, /css/** 검증 제거, /, /index.html 200 검증 추가, /cart, /adminindex.html forward 확인, /api/v1/admin/** 비인증 401, 존재하지 않는 /api/v1/** forward 없음 검증.
레거시 정리
src/main/resources/static/js/router.js, src/main/resources/static/js/store.js, src/main/resources/static/js/app.js, src/main/resources/static/js/api.js, src/main/resources/static/index.html, src/main/resources/static/css/app.css
바닐라 JS SPA 구현 전체 삭제 (해시 라우터, store, API 래퍼), 정적 HTML 및 CSS 삭제.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • heygw44/groove#111: SecurityConfig에서 SPA/정적 경로에 대한 permitAll() GET 인증 설정을 변경하여 같은 보안 설정 축의 관련 PR입니다.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.62% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목은 Vue 3 프론트엔드, Vite, Tailwind, Gradle 통합, SPA fallback, 공통 인프라 등 주요 변경사항의 핵심을 명확히 요약합니다.
Linked Issues check ✅ Passed PR은 #113의 모든 코딩 요구사항을 충족합니다: frontend/ Vite 스캐폴딩, Tailwind v4 설정, Gradle 통합, SPA fallback, API 클라이언트, Pinia 스토어, 공통 레이아웃/컴포넌트 구현됨.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #113 범위 내입니다: frontend/ 프로젝트 생성, 빌드 통합, SPA 설정, 기존 바닐라 파일 제거, 공통 인프라 구축이 요구사항과 일치합니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch infra/113

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 and usage tips.

@heygw44 heygw44 added type:infra 인프라·셋업·DevOps domain:common 도메인: common labels Jun 2, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (3)
src/main/java/com/groove/auth/security/SecurityConfig.java (1)

124-125: ⚡ Quick win

SecurityConfig: SpaRoutes.PATTERNS GET permitAll은 현재 코드에서 bare GET 컨트롤러와 충돌하지 않음

  • SecurityConfigrequestMatchers(HttpMethod.GET, SpaRoutes.PATTERNS).permitAll() 대상(/login,/signup,/me/**,/albums/**,/orders/**,/coupons/**,/admin 등)은 현재 코드에서 해당 bare 경로의 GET 핸들러 매핑이 발견되지 않았고, /login,/signupPOST만 존재합니다.
  • 다만 “모든 컨트롤러는 /api/v1 prefix” 불변식이 강제되진 않으므로, 해당 bare 경로에 GET 컨트롤러가 추가되는 회귀 방지는 테스트/검증으로 가드하는 편이 안전합니다.
🤖 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/main/java/com/groove/auth/security/SecurityConfig.java` around lines 124
- 125, The current SecurityConfig uses requestMatchers(HttpMethod.GET,
SpaRoutes.PATTERNS).permitAll() which unintentionally permits bare GET paths
(e.g., /login, /signup, /me/**, /albums/**, /orders/**, /coupons/**, /admin)
that currently have no GET handlers but could be added later; tighten this by
changing SecurityConfig to only permit the explicit SPA shell/static asset paths
(i.e., replace SpaRoutes.PATTERNS with a narrower constant or dedicated SpaShell
patterns) or alternatively add a regression test that scans
RequestMappingHandlerMapping for any GET mappings matching SpaRoutes.PATTERNS
and fails the build if such bare GET controllers exist (reference SecurityConfig
and SpaRoutes.PATTERNS when implementing the change).
frontend/src/assets/main.css (1)

24-28: ⚡ Quick win

Stylelint value-keyword-case 회피: 폰트명 인용 처리.

Pretendard(따옴표 없는 토큰)가 value-keyword-case로 잘못 플래그됩니다. 소문자화는 폰트명을 깨뜨리므로 잘못된 수정이고, 폰트명을 따옴표로 감싸면 키워드로 인식되지 않아 린트 에러가 사라집니다.

♻️ 제안 수정
   --font-sans:
-    'Pretendard Variable', Pretendard, ui-sans-serif, system-ui, -apple-system,
+    'Pretendard Variable', 'Pretendard', ui-sans-serif, system-ui, -apple-system,
     'Apple SD Gothic Neo', 'Noto Sans KR', sans-serif;
   --font-display:
-    'Pretendard Variable', Pretendard, ui-sans-serif, system-ui, sans-serif;
+    'Pretendard Variable', 'Pretendard', ui-sans-serif, system-ui, sans-serif;

참고: line 8의 @theme "unknown at-rule" 경고는 stylelint가 SCSS 규칙으로 동작해 Tailwind v4 디렉티브를 모르는 데서 오는 오탐입니다. 코드가 아니라 stylelint 설정(Tailwind 인지 구성 또는 at-rule-no-unknown ignore)에서 처리하세요.

🤖 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 `@frontend/src/assets/main.css` around lines 24 - 28, The CSS custom properties
--font-sans and --font-display include unquoted font family tokens (e.g.,
Pretendard) that trigger stylelint's value-keyword-case; wrap any unquoted font
names (such as Pretendard) in quotes inside the --font-sans and --font-display
values so they are treated as strings (e.g., 'Pretendard') rather than keywords,
leaving existing quoted names intact; do not change the order or fallback
stacks.
frontend/src/components/ToastHost.vue (1)

17-26: ⚡ Quick win

에러 토스트의 스크린리더 알림과 키보드 접근성 개선 권장.

모든 토스트에 role="status"(polite)가 적용되어 있어 error 타입도 즉시 안내되지 않습니다. 또한 @click 닫기가 <div>에 있어 키보드로는 닫을 수 없습니다(자동 닫힘이 있어 차단 수준은 아님). 타입별 role(error → alert)을 분기하고, 닫기를 버튼으로 노출하는 것을 권장합니다.

🤖 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 `@frontend/src/components/ToastHost.vue` around lines 17 - 26, The toast markup
currently renders each item with a non-interactive <div> using role="status" and
`@click` for dismissal; update the rendering for items in ToastHost.vue so that
the ARIA role is chosen per toast type (use role="alert" when t.type ===
'error', otherwise role="status") and replace the click-to-dismiss on the
container with a dedicated, keyboard-focusable close control (a button that
calls ui.dismiss(t.id)); keep the existing visual classes (styleByType[t.type]
|| styleByType.info) and ensure the close button is accessible (aria-label or
visually-hidden text) while leaving automatic dismissal behavior unchanged.
🤖 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 `@frontend/src/components/base/BaseInput.vue`:
- Around line 28-29: Replace the Tailwind focus utility used in the BaseInput
component: in BaseInput.vue update the input's class string to use
focus:outline-hidden instead of focus:outline-none (the class block that
currently includes "focus:outline-none focus:ring-2 focus:ring-gold-400" should
be changed to "focus:outline-hidden focus:ring-2 focus:ring-gold-400"); keep the
existing conditional border classes and ring styles intact so the component's
visual focus ring remains while preserving forced-colors/high-contrast
accessibility.
- Around line 11-17: In onInput, when props.type === 'number' guard against
valueAsNumber returning NaN (e.g. for "-", ".", "1e") before emitting; read
const num = e.target.valueAsNumber and if Number.isNaN(num)
emit('update:modelValue', '') (or emit the raw string if you prefer to preserve
intermediate input) else emit the numeric value; this ensures update:modelValue
never receives NaN from HTMLInputElement.valueAsNumber.

In `@frontend/src/views/HomeView.vue`:
- Around line 16-17: catch 블록에서 ApiError의 detail 또는 title이 둘 다 비어있을 경우
error.value가 빈 문자열이 되어 잘못된 UI가 보입니다; 에러 처리 로직(현재의 catch(e) 블록, 참조: error.value 및
ApiError 검사)을 변경해 e가 ApiError인 경우 e.detail || e.title || '앨범을 불러오지 못했습니다.'와 같이
최종 폴백 메시지를 포함하도록 설정하고, ApiError가 아닐 때도 동일한 기본 메시지로 폴백되게 하여 항상 사용자에게 의미 있는 에러 문구가
표시되도록 수정하세요.

---

Nitpick comments:
In `@frontend/src/assets/main.css`:
- Around line 24-28: The CSS custom properties --font-sans and --font-display
include unquoted font family tokens (e.g., Pretendard) that trigger stylelint's
value-keyword-case; wrap any unquoted font names (such as Pretendard) in quotes
inside the --font-sans and --font-display values so they are treated as strings
(e.g., 'Pretendard') rather than keywords, leaving existing quoted names intact;
do not change the order or fallback stacks.

In `@frontend/src/components/ToastHost.vue`:
- Around line 17-26: The toast markup currently renders each item with a
non-interactive <div> using role="status" and `@click` for dismissal; update the
rendering for items in ToastHost.vue so that the ARIA role is chosen per toast
type (use role="alert" when t.type === 'error', otherwise role="status") and
replace the click-to-dismiss on the container with a dedicated,
keyboard-focusable close control (a button that calls ui.dismiss(t.id)); keep
the existing visual classes (styleByType[t.type] || styleByType.info) and ensure
the close button is accessible (aria-label or visually-hidden text) while
leaving automatic dismissal behavior unchanged.

In `@src/main/java/com/groove/auth/security/SecurityConfig.java`:
- Around line 124-125: The current SecurityConfig uses
requestMatchers(HttpMethod.GET, SpaRoutes.PATTERNS).permitAll() which
unintentionally permits bare GET paths (e.g., /login, /signup, /me/**,
/albums/**, /orders/**, /coupons/**, /admin) that currently have no GET handlers
but could be added later; tighten this by changing SecurityConfig to only permit
the explicit SPA shell/static asset paths (i.e., replace SpaRoutes.PATTERNS with
a narrower constant or dedicated SpaShell patterns) or alternatively add a
regression test that scans RequestMappingHandlerMapping for any GET mappings
matching SpaRoutes.PATTERNS and fails the build if such bare GET controllers
exist (reference SecurityConfig and SpaRoutes.PATTERNS when implementing the
change).
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6436184a-7ca7-486f-b0f5-bcd13b5a0f55

📥 Commits

Reviewing files that changed from the base of the PR and between bf27cae and bde4154.

⛔ Files ignored due to path filters (3)
  • .gitignore is excluded by !.gitignore
  • frontend/package-lock.json is excluded by !**/package-lock.json
  • frontend/public/favicon.svg is excluded by !**/*.svg
📒 Files selected for processing (38)
  • build.gradle.kts
  • frontend/.gitignore
  • frontend/.node-version
  • frontend/index.html
  • frontend/jsconfig.json
  • frontend/package.json
  • frontend/src/App.vue
  • frontend/src/api/albums.js
  • frontend/src/api/auth.js
  • frontend/src/api/client.js
  • frontend/src/assets/main.css
  • frontend/src/components/SearchBar.vue
  • frontend/src/components/TheFooter.vue
  • frontend/src/components/TheHeader.vue
  • frontend/src/components/ToastHost.vue
  • frontend/src/components/base/BaseButton.vue
  • frontend/src/components/base/BaseInput.vue
  • frontend/src/components/base/BaseSpinner.vue
  • frontend/src/lib/format.js
  • frontend/src/lib/problem-detail.js
  • frontend/src/lib/uuid.js
  • frontend/src/main.js
  • frontend/src/router/index.js
  • frontend/src/stores/auth.js
  • frontend/src/stores/ui.js
  • frontend/src/views/HomeView.vue
  • frontend/src/views/NotFoundView.vue
  • frontend/vite.config.js
  • src/main/java/com/groove/auth/security/SecurityConfig.java
  • src/main/java/com/groove/web/SpaForwardConfig.java
  • src/main/java/com/groove/web/SpaRoutes.java
  • src/main/resources/static/css/app.css
  • src/main/resources/static/index.html
  • src/main/resources/static/js/api.js
  • src/main/resources/static/js/app.js
  • src/main/resources/static/js/router.js
  • src/main/resources/static/js/store.js
  • src/test/java/com/groove/auth/security/SecurityConfigIntegrationTest.java
💤 Files with no reviewable changes (6)
  • src/main/resources/static/css/app.css
  • src/main/resources/static/js/api.js
  • src/main/resources/static/js/router.js
  • src/main/resources/static/js/store.js
  • src/main/resources/static/js/app.js
  • src/main/resources/static/index.html

Comment thread frontend/src/components/base/BaseInput.vue
Comment thread frontend/src/components/base/BaseInput.vue Outdated
Comment thread frontend/src/views/HomeView.vue Outdated
- BaseInput type=number: valueAsNumber 가 NaN("-", ".", "1e")일 때 '' 보정(NaN emit 차단)
- BaseInput·SearchBar: focus:outline-none → focus:outline-hidden (Tailwind v4, forced-colors 접근성)
- HomeView: ApiError 의 detail·title 이 모두 비어도 기본 문구로 폴백
- main.css: 폰트명 Pretendard 인용(stylelint value-keyword-case 회피)
- ToastHost: error 토스트 role=alert(즉시 안내), 키보드 접근 가능한 닫기 버튼 추가
- SecurityConfigIntegrationTest: SpaRoutes.PATTERNS 와 충돌하는 GET 컨트롤러 매핑이 생기면
  실패하는 회귀 가드 추가(forward+permitAll 공유 상수가 실데이터 GET 을 덮는 것 방지)
@heygw44 heygw44 merged commit e37bad2 into main Jun 2, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain:common 도메인: common type:infra 인프라·셋업·DevOps

Projects

None yet

1 participant