Skip to content

Conversation

@manNomi
Copy link
Contributor

@manNomi manNomi commented Feb 1, 2026

구현 내용

이미지 로드 실패 시 적절한 폴백 이미지를 표시하도록 개선했습니다.

변경 사항

  • useImageFallback 커스텀 훅 추가 - 재사용 가능한 이미지 폴백 로직
  • 🎨 대학 로고 폴백 SVG 추가 (university-logo-placeholder.svg)
  • 🎨 뉴스 썸네일 폴백 SVG 추가 (news-thumbnail-placeholder.svg)
  • 🔧 UniverSityCard - 대학 로고 폴백 처리
  • 🔧 NewsCards - 뉴스 썸네일 폴백 처리

기술적 세부사항

  • Next.js Image 컴포넌트의 onError 이벤트 활용
  • useState로 에러 상태 관리
  • 회색 톤의 심플한 SVG 아이콘으로 일관성 유지

테스트

  • 대학 로고 로드 실패 시 폴백 이미지 확인
  • 뉴스 썸네일 로드 실패 시 폴백 이미지 확인

@vercel
Copy link

vercel bot commented Feb 1, 2026

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

Project Deployment Actions Updated (UTC)
solid-connect-web-admin Error Error Feb 1, 2026 3:31pm
solid-connection-web Error Error Feb 1, 2026 3:31pm

@coderabbitai
Copy link

coderabbitai bot commented Feb 1, 2026

Caution

Review failed

The pull request is closed.

Walkthrough

  1. 관리자 앱 빌드 아티팩트 추가: .output 하위에 Nitro 설정, 서버 엔트리, 번들 JS/CSS, 매니페스트, robots.txt 등이 생성되었습니다.
  2. 관리자 UI 컴포넌트 추가: 로그인 페이지와 성적 관리(학점/어학) UI 및 인라인 편집·상태 업데이트 로직이 번들에 포함되었습니다.
  3. Radix 및 UI 유틸 통합: 프리미티브, 슬롯, 탭, 로빙 포커스, 프레즌스 등 여러 UI 유틸리티 모듈이 추가되었습니다.
  4. 서버·런타임 라이브러리 추가: TanStack Router, seroval, h3, Nitro 서버 엔트리 등 SSR·라우팅·직렬화 관련 모듈이 다수 추가되었습니다.
  5. 클라이언트 개선 및 훅 추가: Axios 인증 인터셉터, 토큰 관리, 이미지 폴백 훅, 토스트(sonner) 등 클라이언트 유틸이 도입되었습니다.

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Suggested reviewers

  • wibaek
  • enunsnv
  • khwww
🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning PR 설명이 템플릿 구조를 따르지 않습니다. 필수 섹션인 '관련 이슈'와 '특이 사항'이 누락되었습니다. PR 템플릿의 필수 섹션들을 모두 작성해주세요. 최소한 이슈 번호, 특이 사항, 리뷰 요구사항을 추가하십시오.
Docstring Coverage ⚠️ Warning Docstring coverage is 1.03% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목이 주요 변경사항과 일치합니다. 이미지 폴백 처리라는 핵심 기능을 명확하게 설명하고 있습니다.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/image-fallback

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Note

Due to the large number of review comments, Critical severity comments were prioritized as inline comments.

🤖 Fix all issues with AI agents
In
`@apps/admin/.output/server/_chunks/_libs/`@radix-ui/react-use-effect-event.mjs:
- Line 1: Add the `.output` build directory to .gitignore, stop tracking the
already-committed build artifacts by removing all tracked files under the
`.output` directory from Git's index (untrack them without deleting local files)
and commit that removal, then clean up this PR so it only contains the actual
source changes (the image fallback feature: functions/components like
useImageFallback and the SVG placeholder code) and not any files under
`.output`; finally, verify the PR diff contains only the source files related to
the image fallback/SVG placeholder and not Nuxt/Nitro build artifacts.

In `@apps/web/src/components/home/NewsCards.tsx`:
- Around line 10-25: The hook useImageFallback is currently called once in
NewsCards so getSrc/handleError are shared across all items causing one image
error to flip all images to fallback; fix by extracting a per-item NewsCard
component that receives a single news item and calls useImageFallback inside it
(use the news.imageUrl, news.title, news.url, news.id there), then update
NewsCards to map newsList => <NewsCard key={news.id} news={news} /> so each card
maintains its own getSrc/handleError state.

In `@apps/web/src/hooks/useImageFallback.ts`:
- Around line 8-19: The hook useImageFallback currently stores a single boolean
hasError so one failing image flips all images; change it to track error state
per image URL (e.g., a Record<string, boolean> or Map) and update getSrc and
handleError to accept the image key/originalSrc so they check/set the per-URL
flag; specifically, replace hasError with something like failedMap, make
handleError take the originalSrc (or an id) and set failedMap[originalSrc] =
true, and make getSrc(originalSrc) return failedMap[originalSrc] ? fallbackSrc :
originalSrc so multiple images can independently fall back while preserving the
existing function names useImageFallback, getSrc, handleError and exposed
hasError can be removed or replaced by a getter that reports failure for a given
URL.
🟠 Major comments (27)
apps/admin/.output/server/_libs/crossws.mjs-1-1 (1)

1-1: ⚠️ Potential issue | 🟠 Major

빌드 산출물이 버전 관리에 포함되고 있습니다.

.output 디렉토리가 .gitignore에 등록되지 않아 컴파일된 JavaScript, CSS, 이미지 등의 빌드 결과물이 리포지토리에 커밋되고 있습니다.

필요한 조치:

  1. .gitignore 파일에 .output 디렉토리 추가하기
  2. 현재 커밋된 apps/admin/.output 디렉토리를 제거하고 히스토리에서 정리하기

이렇게 하면 향후 빌드 산출물이 실수로 커밋되는 것을 방지할 수 있습니다.

apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-layout-effect.mjs-1-6 (1)

1-6: ⚠️ Potential issue | 🟠 Major

.output 디렉토리의 빌드 산출물이 저장소에 커밋되어 있습니다

확인 결과, apps/admin/.output/ 디렉토리의 100개 파일이 버전 관리 대상으로 추적되고 있습니다. 이 파일들은 빌드 단계에서 생성되는 산출물이므로 저장소에 포함되지 않아야 합니다.

문제점:

  1. .gitignore 설정 누락

    • 루트 .gitignore.output 패턴이 없습니다
    • apps/admin/.gitignore 파일도 존재하지 않습니다
    • .output 내 100개 파일이 모두 추적 상태입니다
  2. 불필요한 저장소 비대화

    • 빌드 결과물은 소스로부터 재생성 가능합니다
    • 저장소 크기가 불필요하게 증가합니다
    • PR 목적(이미지 fallback 처리)과 무관한 파일들입니다

해결 방안:

  1. 루트 .gitignore.output/ 패턴 추가

    • 패턴: .output/ 또는 **/.output/
  2. 기존 커밋된 파일 제거

    • git rm -r --cached apps/admin/.output/로 추적 해제
    • 새로운 커밋으로 반영
apps/admin/.output/server/_libs/tiny-invariant.mjs-1-12 (1)

1-12: ⚠️ Potential issue | 🟠 Major

빌드 산출물이 저장소에 커밋되어 있습니다.

검증 결과, 다음과 같은 상황을 확인했습니다:

  1. .output 디렉토리 구성

    • 약 100개의 빌드 아티팩트 파일 포함
    • Nitro 빌드 구성 파일, 번들된 JavaScript/CSS, 서버 청크 등으로 구성
  2. .gitignore 누락

    • 현재 .gitignore.output 패턴이 정의되지 않음
    • 빌드 산출물이 실수로 추적되고 있음
  3. 문제 해결 방안

    • .gitignore.output/ 패턴 추가
    • 이미 커밋된 파일은 git rm --cached -r apps/admin/.output/ 명령으로 제거

이 파일은 PR의 이미지 폴백 처리 기능 추가와는 무관합니다. 의도치 않게 포함되었다면 정리 부탁드립니다.

apps/admin/.output/server/_libs/proxy-from-env.mjs-1-77 (1)

1-77: ⚠️ Potential issue | 🟠 Major

빌드 결과물이 의도치 않게 버전 관리에 포함되어 있습니다.

.output 디렉토리는 Nitro 빌드 시스템에 의해 자동 생성되는 폴더인데, 현재 약 100개 이상의 컴파일된 파일들이 저장소에 커밋되어 있습니다.

  1. 발견된 문제점

    • .gitignore 파일에 .output 패턴이 누락되어 있습니다
    • 100개 이상의 빌드 산출물이 저장소 크기를 불필요하게 증가시키고 있습니다
    • 향후 팀 협업 시 병합 충돌 위험이 커집니다
  2. 필요한 수정 사항

    • .gitignore 파일에 .output/ 패턴을 추가해 주세요
    • 이미 커밋된 빌드 파일들을 제거해 주세요
  3. 확인된 내용

    • nitro.json 파일의 존재로 Nitro 기반 프로젝트임을 확인했습니다
    • 해당 파일은 @__PURE__ 주석이 있는 번들된 코드로, 수작업으로 작성된 것이 아닙니다
apps/admin/.output/server/_libs/get-proto.mjs-1-44 (1)

1-44: ⚠️ Potential issue | 🟠 Major

빌드 출력물이 버전 관리에 포함되어 있습니다 - 제거가 필요합니다.

이 파일들은 apps/admin/.output/ 디렉토리의 Nuxt/Nitro 서버 빌드 결과물입니다. 빌드 아티팩트는 저장소에 커밋되어서는 안 됩니다.

확인된 문제점:

  1. .gitignore.output 패턴이 포함되지 않아 수백 개의 빌드 아티팩트가 버전 관리 대상이 되고 있습니다.
  2. 현재 커밋에 다수의 .output 관련 파일들이 포함되어 있습니다 (nitro.json, 번들된 자산, 서버 청크 등).
  3. PR 목표(이미지 fallback 처리)와 무관한 파일들입니다.

권장 조치:

  1. 이 커밋에서 apps/admin/.output/ 디렉토리 전체를 제거해주세요.
  2. .gitignore 파일에 .output 항목을 추가하여 향후 빌드 결과물이 커밋되는 것을 방지해주세요.
  3. 필요시 git rm -r --cached apps/admin/.output/를 사용하여 추적 해제할 수 있습니다.
apps/admin/.output/server/_libs/use-sync-external-store.mjs-1-1 (1)

1-1: ⚠️ Potential issue | 🟠 Major

빌드 산출물 100개 파일이 저장소에 커밋되어 있습니다.

.output/ 디렉토리는 Nitro SSR 빌드 프로세스의 산출물로, 버전 관리에 포함되지 않아야 합니다. 검증 결과 다음을 확인했습니다:

  1. .gitignore에 누락된 패턴
    .output/ 디렉토리가 .gitignore에 등록되지 않음 → 즉시 추가 필요

  2. 대규모 빌드 산출물 커밋

    • 총 100개 파일이 apps/admin/.output/ 경로에서 커밋됨
    • JavaScript 번들, CSS 자산, 서버 청크, 아이콘 등 포함
    • PR 목표(이미지 폴백 처리)와 무관한 내용
  3. 권장 조치사항

    • .gitignoreapps/admin/.output/ 추가
    • git 히스토리에서 해당 파일들 제거 (BFG, git filter-branch 등)
    • 향후 빌드 산출물이 자동으로 제외되도록 설정

이러한 파일들을 커밋하면 저장소 크기 증가, 불필요한 머지 충돌, 코드 리뷰 복잡성 증가 등의 문제가 발생합니다.

apps/admin/.output/server/_libs/tiny-warning.mjs-1-5 (1)

1-5: ⚠️ Potential issue | 🟠 Major

.output/ 디렉토리는 빌드 결과물이므로 버전 관리에서 제외되어야 합니다.

현재 상황을 확인한 결과:

  1. .output/ 디렉토리가 .gitignore에 포함되지 않음

    • 루트 .gitignore 파일에 .output 패턴이 없습니다.
  2. .output/ 디렉토리는 Nitro 빌드 산출물임이 확인됨

    • 약 100개의 번들 파일 포함 (hashed filename: client-ByMMc4SQ.js 등)
    • nitro.json, 프로덕션 에셋, 매니페스트 파일 등 포함

필수 조치:

  • .gitignore 파일에 .output/ 패턴을 추가해 주세요.
    # Nitro build output
    **/.output/
    .output/
    
  • 현재 커밋에서 apps/admin/.output/ 디렉토리를 제거해 주세요.

빌드 결과물을 저장소에 포함하지 않으면 저장소 크기를 줄이고, 불필요한 머지 충돌을 방지하며, 코드 리뷰 효율성을 높일 수 있습니다.

apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-callback-ref.mjs-1-11 (1)

1-11: ⚠️ Potential issue | 🟠 Major

.output/ 디렉토리를 버전 관리에서 제외해야 합니다.

현재 상황을 정리하면 다음과 같습니다.

  1. 빌드 결과물이 git에서 추적 중입니다.

    • apps/admin/.output/ 디렉토리는 Nuxt.js의 표준 빌드 출력 디렉토리입니다.
    • 현재 약 2.8MB, 100개의 파일이 저장소에 포함되어 있습니다.
  2. .gitignore에서 누락된 규칙을 추가하세요.

    • .output 패턴이 .gitignore에 명시되지 않아, 빌드 결과물이 버전 관리 대상이 되고 있습니다.
    • .gitignore에 다음 규칙을 추가하면 향후 이런 문제를 방지할 수 있습니다: **/.output
  3. 이미 커밋된 파일은 제거해야 합니다.

    • git에서 추적 중인 기존 파일들을 제거하려면 git rm --cached -r apps/admin/.output/ 명령을 실행한 후, .gitignore 업데이트와 함께 커밋하세요.

이를 통해 저장소 크기를 줄이고, 불필요한 머지 충돌을 방지하며, 코드 리뷰를 더 간결하게 유지할 수 있습니다.

apps/admin/.output/server/_libs/cookie-es.mjs-1-58 (1)

1-58: ⚠️ Potential issue | 🟠 Major

.output 디렉토리 전체가 버전 관리에 포함되었습니다. 빌드 아티팩트는 제거하고 .gitignore에 추가해 주세요.

현재 상황을 정리하면 다음과 같습니다:

  1. 빌드 결과물이 커밋된 상태
    약 2.8MB 규모의 .output 디렉토리가 100개 이상의 번들된 라이브러리 파일과 함께 저장소에 포함되어 있습니다.

  2. .gitignore 설정이 누락된 상태
    루트 .gitignore에는 .next, dist, build 같은 다른 빌드 산출물은 제외되어 있지만, .output은 명시되어 있지 않습니다.

  3. 해결 방법

    • apps/admin/.output 디렉토리를 git에서 제거하세요
    • 루트 .gitignore 파일에 **/.output 패턴을 추가하세요

빌드 아티팩트를 버전 관리에 포함시키면 저장소 크기가 불필요하게 증가하고, 개발자들의 로컬 빌드 결과로 인한 충돌이 발생할 수 있습니다.

apps/admin/.output/server/_libs/date-fns.mjs-1-1489 (1)

1-1489: ⚠️ Potential issue | 🟠 Major

.output 디렉토리를 .gitignore에 추가하고 빌드 아티팩트 제거가 필요합니다.

프로젝트 구조를 확인한 결과, 다음과 같은 사항을 발견했습니다:

  1. .output 디렉토리가 버전 관리에 포함되어 있습니다

    • 현재 약 100개의 auto-generated 파일이 git에 추적 중입니다
    • 파일명에 해시가 포함되어 있어 빌드마다 변경됩니다 (예: client-ByMMc4SQ.js)
  2. .gitignore 설정 보완이 필요합니다

    • 현재 .gitignore에는 **/build, **/dist 등이 있습니다
    • Nitro SSR의 표준 출력 디렉토리인 .output 패턴이 누락되었습니다
  3. 권장하는 조치사항

    • 루트 .gitignore**/.output 추가
    • git rm -r --cached apps/admin/.output 명령으로 추적 중지
    • 저장소에서 불필요한 빌드 아티팩트 제거
# .gitignore에 추가할 항목
**/.output
apps/admin/.output/server/_libs/react.mjs-1-510 (1)

1-510: ⚠️ Potential issue | 🟠 Major

빌드 산출물 커밋은 제거해 주세요.

    1. 증상: .output/ 아래 파일은 빌드 산출물이라 PR 목표(이미지 폴백)와 직접 관련이 없습니다.
    1. 조치: 파일을 제거하고 루트 .gitignore.output/가 포함됐는지 확인해 주세요.
🧹 제안 변경(루트 .gitignore)
+.output/
apps/admin/.output/server/_chunks/_libs/@tanstack/store.mjs-1-1 (1)

1-1: ⚠️ Potential issue | 🟠 Major

빌드 산출물이 버전 관리에 포함되어 있습니다.

다음 사항들을 확인해 주세요:

  1. 빌드 결과물 커밋 방지: .output/ 디렉토리는 빌드 과정에서 생성되는 산출물로, 버전 관리 시스템에 포함되지 않아야 합니다.
  2. .gitignore 업데이트: .output/ 경로가 .gitignore에 추가되어 있는지 확인해 주세요.
  3. 리포지토리 정리: 이미 커밋된 빌드 산출물을 제거하는 것을 권장합니다.

빌드 산출물을 버전 관리에 포함하면 다음과 같은 문제가 발생할 수 있습니다:

  • 리포지토리 크기 불필요하게 증가
  • 병합 충돌 가능성 증가
  • 코드 리뷰 시 실제 소스 코드 변경사항 파악 어려움
🔧 .gitignore 업데이트 제안

.gitignore 파일에 다음 항목을 추가해 주세요:

+# Build outputs
+apps/admin/.output/
+*.output/

이미 커밋된 파일들을 제거하려면:

git rm -r --cached apps/admin/.output/
git commit -m "chore: remove build artifacts from version control"

참고: PR 목표에 언급된 실제 기능 구현 코드(useImageFallback 훅, SVG 에셋, 컴포넌트 변경사항)가 리뷰 파일에 포함되어 있지 않습니다. 실제 소스 코드 변경사항을 확인하여 이미지 폴백 처리 로직을 리뷰할 수 있도록 해주시면 좋겠습니다.

#!/bin/bash
# Description: Check if .output/ is already in .gitignore and verify the extent of build artifacts committed

# Check if .output/ is in .gitignore
echo "=== Checking .gitignore for .output/ directory ==="
if [ -f .gitignore ]; then
  rg '\.output' .gitignore || echo "⚠️  .output/ not found in .gitignore"
else
  echo "⚠️  .gitignore file not found"
fi

echo ""
echo "=== Finding all .output/ directories in the repository ==="
fd -t d '.output' --max-depth 5

echo ""
echo "=== Counting files in apps/admin/.output/ ==="
fd -t f . apps/admin/.output/ | head -20
apps/admin/.output/server/_libs/call-bind-apply-helpers.mjs-1-60 (1)

1-60: ⚠️ Potential issue | 🟠 Major

빌드 출력 파일 - 동일한 패턴의 문제입니다.

  1. 상태

    • call-bind-apply-helpers.mjs.output/ 디렉토리 내 빌드 결과물입니다.
    • Function.prototype.call/apply와 Reflect.apply를 위한 지연 로딩 헬퍼입니다.
  2. 전체 요약

    • 이번 리뷰에서 확인된 3개의 파일 모두 빌드 출력물입니다.
    • PR 목적(이미지 폴백 처리)과 관련이 없는 파일들입니다.
  3. 권장 조치

    • .output/ 디렉토리 전체를 .gitignore에 추가하세요.
    • 이 PR에서 빌드 출력 파일들을 제거해 주세요.
    • 실제 이미지 폴백 관련 소스 코드 변경사항만 커밋하세요.
apps/admin/.output/server/_libs/gopd.mjs-1-27 (1)

1-27: ⚠️ Potential issue | 🟠 Major

빌드 출력 파일 - 이전 파일과 동일한 문제가 있습니다.

  1. 상태

    • 이 파일 역시 .output/ 디렉토리 내의 빌드 결과물입니다.
    • Object.getOwnPropertyDescriptor에 대한 지연 로딩 래퍼로, npm 패키지에서 번들링된 코드로 보입니다.
  2. 조치 필요

    • dunder-proto.mjs에서 언급한 것과 같이, 이 파일은 버전 관리에서 제외되어야 합니다.
apps/admin/.output/server/_libs/dunder-proto.mjs-1-36 (1)

1-36: ⚠️ Potential issue | 🟠 Major

빌드 출력 파일이 버전 관리에 포함되고 있습니다 - 즉시 제거 필요

현재 상태를 확인한 결과, 약 100개의 빌드 결과물이 git에 추적되고 있으며 .gitignore에 등록되어 있지 않습니다.

  1. 현재 문제 상황

    • .output/ 디렉토리의 100개 파일이 이미 저장소에 커밋됨
    • .gitignore.output 패턴이 없어 계속 추적될 상태
    • 빌드 산출물(자동 생성 가능한 파일들)이 소스 코드와 함께 관리되고 있음
  2. 권장 조치 사항

    • .gitignore**/.output/ 또는 **/dist 등 빌드 출력 패턴 추가
    • 커밋된 빌드 산출물은 git에서 제거:
      git rm -r --cached apps/admin/.output/
    • 이후 .gitignore 수정 및 커밋
  3. 기대 효과

    • 저장소 크기 최적화
    • 빌드 재현성 향상
    • 불필요한 머지 충돌 방지
apps/admin/.output/server/_libs/has-flag.mjs-1-16 (1)

1-16: ⚠️ Potential issue | 🟠 Major

.output 산출물 커밋을 즉시 제거하고 소스 파일을 추가해야 합니다.

현재 상태를 확인한 결과 다음 문제들이 발견되었습니다:

  1. 빌드 산출물만 존재apps/admin 디렉토리에 .output 폴더만 있고 소스 파일(페이지, 컴포넌트, 설정 파일 등)이 전혀 없습니다.
  2. .output이 .gitignore에 없음 — Nitro/Nuxt 서버 빌드 결과물인 .output이 버전 관리에 포함되어 있습니다. 표준 관행상 이는 무시되어야 합니다.
  3. 소스와 산출물 분리 필요 — 개발자가 apps/admin의 실제 소스 코드(TypeScript, 설정 파일 등)를 커밋한 후 빌드를 재실행하는 것이 권장됩니다.

제안:

  • .gitignore.output 추가
  • 이 커밋에서 apps/admin/.output 제거
  • apps/admin의 실제 소스 코드를 리포지토리에 추가
apps/admin/.output/server/_libs/srvx.mjs-689-697 (1)

689-697: ⚠️ Potential issue | 🟠 Major

  1. serve() 첫 호출이 Promise를 반환하지 않음
    #listeningPromise 설정 후 반환이 없어 await server.serve()undefined가 됩니다. 마지막에 this를 리턴해주세요.
🔁 수정 제안
   serve() {
     if (this.#listeningPromise) return Promise.resolve(this.#listeningPromise).then(() => this);
     this.#listeningPromise = new Promise((resolve) => {
       this.node.server.listen(this.serveOptions, () => {
         printListening(this.options, this.url);
         resolve();
       });
     });
+    return Promise.resolve(this.#listeningPromise).then(() => this);
   }
apps/admin/.output/server/_libs/srvx.mjs-186-198 (1)

186-198: ⚠️ Potential issue | 🟠 Major

  1. waitUntil의 Set 정리가 누락돼 누수 위험
    Set에는 래핑된 Promise를 넣는데 finally에서 원래 Promise를 삭제해 계속 쌓입니다. 래핑된 Promise를 변수로 저장해 삭제해주세요.
🧹 수정 제안
     waitUntil: (promise) => {
       if (typeof promise?.then !== "function") return;
-      promises.add(Promise.resolve(promise).catch(console.error).finally(() => {
-        promises.delete(promise);
-      }));
+      const p = Promise.resolve(promise).catch(console.error).finally(() => {
+        promises.delete(p);
+      });
+      promises.add(p);
     },
apps/admin/.output/server/_libs/srvx.mjs-130-137 (1)

130-137: ⚠️ Potential issue | 🟠 Major

  1. 포트 파싱 NaN 허용으로 런타임 오류 가능
    PORT 환경변수가 숫자가 아니면 parseInt 결과가 NaN인데 현재 범위 검사에서 통과합니다. listen 단계에서 모호한 에러가 나니 finite 체크를 추가해주세요.
🔧 수정 제안
-  const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
-  if (port < 0 || port > 65535) throw new RangeError(`Port must be between 0 and 65535 (got "${port}").`);
+  const port = typeof _port === "number" ? _port : Number.parseInt(_port, 10);
+  if (!Number.isFinite(port) || port < 0 || port > 65535) {
+    throw new RangeError(`Port must be between 0 and 65535 (got "${port}").`);
+  }
apps/admin/.output/server/_chunks/_libs/@radix-ui/react-id.mjs-1-14 (1)

1-14: ⚠️ Potential issue | 🟠 Major

.output 디렉토리를 .gitignore에 추가하세요.

현재 상태를 확인한 결과:

  1. .output 디렉토리는 Nitro/TanStack Start의 SSR 빌드 산출물입니다

    • 번들된 자산(JS, CSS), 서버 청크, 공개 파일 등이 포함되어 있습니다
    • 빌드 시마다 자동으로 생성되는 파일입니다
  2. 현재 .output 파일들이 git에서 삭제 대상(D)으로 표시되어 있습니다

    • 이는 이미 커밋된 상태이며, 정리가 필요한 상황입니다
  3. .gitignore.output 패턴이 누락되어 있습니다

    • 다른 빌드 산출물은 적절히 제외되어 있습니다(**/.next/, **/build, **/dist)
    • .output 디렉토리도 동일한 방식으로 처리해야 합니다

.gitignore에 아래를 추가하여 향후 커밋을 방지하세요:

# Nitro build output
**/.output
apps/admin/.output/server/robots.txt-1-3 (1)

1-3: ⚠️ Potential issue | 🟠 Major

빌드 결과물이 커밋되었습니다.

apps/admin/.output/ 디렉토리는 Nitro/Nuxt의 빌드 출력 경로입니다. 빌드 결과물은 .gitignore에 추가하여 버전 관리에서 제외해야 합니다.

  1. 빌드 재현성 문제: 빌드 결과물은 매 빌드마다 재생성되므로 커밋할 필요가 없습니다.
  2. 저장소 크기 증가: 불필요한 파일로 인해 저장소 용량이 커집니다.
  3. 충돌 가능성: 여러 개발자가 빌드할 때 불필요한 merge conflict가 발생할 수 있습니다.

.gitignore에 다음을 추가해주세요:

apps/admin/.output/
apps/admin/.output/server/_libs/sonner.mjs-107-112 (1)

107-112: ⚠️ Potential issue | 🟠 Major

1) visibilitychange 리스너 해제 대상 불일치 문제

  • document에 등록한 리스너를 window에서 제거하려고 하고 있습니다.
  • 서로 다른 객체이기 때문에 실제로는 리스너가 제거되지 않으며, 컴포넌트 언마운트 후에도 메모리에 남아 있게 됩니다.
  • 반드시 동일한 객체(document)에서 리스너를 제거해 주세요.
🛠️ 제안 수정
-    return () => window.removeEventListener("visibilitychange", callback);
+    return () => document.removeEventListener("visibilitychange", callback);
apps/admin/.output/server/_chunks/_libs/@tanstack/history.mjs-146-148 (1)

146-148: ⚠️ Potential issue | 🟠 Major

1) initialIndex가 0일 때 의도와 다르게 마지막 인덱스로 설정됩니다.

- 현재 코드의 truthy 체크로 인해 0이 거짓으로 평가되고 있습니다.
- 사용자가 명시적으로 0을 지정했을 때도 기본값인 `entries.length - 1`로 대체되는 문제가 발생합니다.
- `opts.initialIndex != null`로 변경하여 0을 유효한 값으로 처리해 주세요.
🛠️ 제안 수정
-  let index = opts.initialIndex ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1) : entries.length - 1;
+  let index = opts.initialIndex != null
+    ? Math.min(Math.max(opts.initialIndex, 0), entries.length - 1)
+    : entries.length - 1;
apps/admin/.output/server/_libs/seroval-plugins.mjs-1-58 (1)

1-58: ⚠️ Potential issue | 🟠 Major

.gitignore에 빌드 결과물 디렉토리를 추가해주세요.

apps/admin/.output/ 디렉토리가 현재 버전 관리에 포함되어 있으며, 이는 Nitro 빌드 아티팩트(총 100개 파일)입니다. 다음을 확인했습니다:

  1. 현재 상태

    • .output 패턴이 .gitignore에 없음
    • 약 100개의 빌드 파일이 추적 중 (nitro.json, client-*.js, assets, favicon.ico 등)
  2. 권장 조치

    • .gitignore 파일에 .output 디렉토리를 추가하세요
    • 예: **/\.output/ 또는 **/.output/ 패턴 추가
  3. 효과

    • 향후 빌드 결과물이 자동으로 무시되어 의도하지 않은 커밋 방지
    • CI/CD 파이프라인에서만 빌드 아티팩트 생성 가능

이미 .next/, dist/, build/ 등의 패턴이 .gitignore에 있으므로, 동일한 맥락에서 .output/도 함께 제외하는 것이 일관성 있습니다.

apps/admin/.output/server/index.mjs-13-24 (1)

13-24: ⚠️ Potential issue | 🟠 Major

  1. lazyService 실패 시 영구 실패로 고착될 수 있습니다.
  • loader()가 한 번 실패하면 promise가 재설정되지 않아 이후 요청도 계속 실패합니다.
  • 실패 시 promise를 초기화해 재시도 가능하게 만드는 편이 안정적입니다.
🔧 제안 수정
 function lazyService(loader) {
   let promise, mod;
   return {
     fetch(req) {
       if (mod) {
         return mod.fetch(req);
       }
       if (!promise) {
-        promise = loader().then((_mod) => mod = _mod.default || _mod);
+        promise = loader()
+          .then((_mod) => (mod = _mod.default || _mod))
+          .catch((err) => {
+            promise = void 0;
+            throw err;
+          });
       }
       return promise.then((mod2) => mod2.fetch(req));
     }
   };
 }
apps/admin/.output/public/assets/index-C5TecN1M.js-1-1 (1)

1-1: ⚠️ Potential issue | 🟠 Major

  1. 파일 링크 베이스 URL이 undefined로 굳는 위험이 보입니다.
  • pn/ynvoid 0인 상태로 템플릿 리터럴에 합쳐지면 undefined... URL이 만들어집니다.
  • 빌드 타임 환경값 주입이 의도라면 기본값을 빈 문자열로 두어 링크가 깨지지 않게 해주세요.
🔧 제안 방향
- const FILE_BASE = import.meta.env.VITE_FILE_BASE;
+ const FILE_BASE = import.meta.env.VITE_FILE_BASE ?? "";
apps/admin/.output/server/_ssr/index.mjs-571-575 (1)

571-575: ⚠️ Potential issue | 🟠 Major

  1. POST/JSON 본문에도 크기 제한이 필요합니다.
  • GET만 MAX_PAYLOAD_SIZE를 검사하고 POST는 무제한으로 request.json()을 읽습니다.
  • Content-Length 기준 차단이나 스트리밍 제한을 추가해 메모리 과사용을 막아주세요.
🔧 제안 수정
         let jsonPayload;
         if (contentType?.includes("application/json")) {
+          const contentLength = Number(request.headers.get("Content-Length") || 0);
+          if (contentLength && contentLength > MAX_PAYLOAD_SIZE) {
+            throw new Error("Payload too large");
+          }
           jsonPayload = await request.json();
         }
🟡 Minor comments (5)
apps/admin/.output/server/_chunks/_libs/follow-redirects.mjs-1-530 (1)

1-530: ⚠️ Potential issue | 🟡 Minor

.output 빌드 산출물을 .gitignore에 추가해 주세요

현재 .gitignore에는 다른 빌드 산출물(**/build, **/dist, **/.next/)은 제외되어 있지만, .output 디렉토리는 누락되어 있습니다. 이 파일이 현재 git에 의해 추적되고 있는데, 이는 의도하지 않은 커밋으로 보입니다.

  1. .gitignore**/.output 패턴 추가
  2. 이미 커밋된 .output 디렉토리는 git rm -r --cached apps/admin/.output 명령으로 제거
apps/admin/.output/server/_libs/ms.mjs-1-2 (1)

1-2: ⚠️ Potential issue | 🟡 Minor

.output 디렉토리를 .gitignore에 추가해 주세요

  1. 현재 상황

    • .output 디렉토리는 Nuxt 빌드 산출물이며, 현재 .gitignore에 포함되어 있지 않습니다.
    • 표준 Next.js/Nuxt 프로젝트에서는 이 디렉토리를 버전 관리에서 제외합니다.
  2. 권장 조치

    • .gitignore 파일에 **/.output/ 패턴을 추가하여 모든 워크스페이스의 빌드 산출물을 무시하도록 설정해 주세요.
apps/admin/.output/public/manifest.json-1-25 (1)

1-25: ⚠️ Potential issue | 🟡 Minor

플레이스홀더 앱 이름이 남아있습니다.

빌드 결과물 이슈 외에, manifest에 기본 템플릿 이름이 그대로 사용되고 있습니다:

  1. short_name: "TanStack App" → 프로젝트에 맞는 이름으로 변경 필요
  2. name: "Create TanStack App Sample" → 실제 앱 이름으로 변경 필요

소스 파일에서 manifest 설정을 수정해주세요. PWA 설치 시 사용자에게 이 이름이 표시됩니다.

apps/admin/.output/server/_ssr/_tanstack-start-manifest_v-Cijt78HO.mjs-1-4 (1)

1-4: ⚠️ Potential issue | 🟡 Minor

📦 빌드 결과물이 커밋되어 삭제 중입니다 - .gitignore 설정 보강 필요

이 PR에서 apps/admin/.output/ 디렉토리가 제거되고 있습니다. 해당 디렉토리는 개발자 로컬 파일 경로 정보를 포함하고 있었습니다:

/Users/manwook-han/Desktop/code/solid-connect/solid-connect-web-nomi/admin-app/src/routes/...

현재 상황:

  1. 삭제 진행 중: PR에서 모든 .output 빌드 아티팩트를 커밋에서 제거하고 있습니다 ✓
  2. 예방 조치 필요: .output/.gitignore에 추가하여 향후 재발을 막아야 합니다

권장 조치:

  • .gitignore**/.output/ 패턴 추가 (기존 빌드 디렉토리 패턴들과 함께)
  • 다른 monorepo 앱도 동일하게 적용되도록 패턴 일반화

이는 Nitro/SSR 빌드 아티팩트가 실수로 재커밋되는 것을 방지합니다.

apps/admin/.output/server/_chunks/_libs/@radix-ui/react-collection.mjs-1-69 (1)

1-69: ⚠️ Potential issue | 🟡 Minor

.output/ 디렉토리는 빌드 산출물이므로 커밋에서 제외되어야 합니다.

현재 상태를 확인한 결과:

  1. .output/ 디렉토리의 파일들이 깃에서 삭제 상태(D)로 표시되어 있음
  2. .gitignore.output/이 등록되지 않음 (보완 필요)

필요한 조치:

  • .gitignore.output/ 추가
  • 깃 추적에서 이미 커밋된 .output/ 파일들 제거 (git rm --cached apps/admin/.output/)
  • 향후 빌드 산출물(minified JS, CSS, 번들 결과물 등)이 리포지토리에 포함되지 않도록 정책 정립
🧹 Nitpick comments (2)
apps/admin/.output/server/_libs/function-bind.mjs (1)

1-88: 빌드 산출물 커밋 여부를 확인해주세요.
apps/admin/.output/** 경로는 빌드 산출물로 보이며, 소스 관리에 포함하면 PR 노이즈와 용량이 크게 늘 수 있어요.

  1. 의도 확인: 배포 전략상 산출물을 커밋하는 것이 맞는지 확인 부탁드려요.
  2. 필요 시 제외: 의도치 않은 경우 .gitignore 처리 또는 CI 아티팩트로 이동을 권장해요.
apps/admin/.output/server/_libs/seroval-plugins.mjs (1)

4-14: 빈 catch 블록이 오류를 무시합니다.

Lines 6-7과 13-14의 빈 catch 블록이 예외를 조용히 무시하고 있습니다. 이로 인해 디버깅이 어려워질 수 있습니다.

  1. 문제 위치:
    • Line 6-7: enqueue 실패 시 무시
    • Line 13-14: close 실패 시 무시

빌드 결과물이라 직접 수정이 어렵겠지만, 소스 코드에서 최소한 로깅을 추가하는 것이 좋습니다.

@@ -0,0 +1 @@

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and its content
echo "=== Checking file existence and content ==="
if [ -f "apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs" ]; then
  echo "File exists."
  echo "File size:" $(stat -f%z "apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs" 2>/dev/null || stat -c%s "apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs" 2>/dev/null)
  echo "Content:"
  cat -n "apps/admin/.output/server/_chunks/_libs/@radix-ui/react-use-effect-event.mjs"
else
  echo "File does not exist"
fi

# Check .gitignore for .output patterns
echo -e "\n=== Checking .gitignore for .output patterns ==="
if [ -f ".gitignore" ]; then
  echo "Lines matching .output:"
  rg -n '\.output' .gitignore || echo "No .output pattern found in .gitignore"
else
  echo ".gitignore file not found"
fi

# Count .output files in the repository
echo -e "\n=== Counting .output files ==="
fd -t f '\.mjs$|\.js$' 'apps/admin/.output' | wc -l || echo "Cannot find .output directory"

# Check apps directory structure
echo -e "\n=== Checking apps/admin directory structure ==="
ls -la apps/admin/ 2>/dev/null | head -20 || echo "Cannot access apps/admin"

Repository: solid-connection/solid-connect-web

Length of output: 524


🏁 Script executed:

# Verify build system type
echo "=== Checking for build config files ==="
fd -t f 'nuxt.config|next.config|vite.config|tsconfig|package.json' apps/admin/ | head -10

# Check if .output is in git tracking
echo -e "\n=== Checking git status for .output files ==="
git ls-files | grep -c '\.output' || echo "Count of .output files in git:"
git ls-files | grep '\.output' | head -5

# Look for relevant PR-related files (image fallback)
echo -e "\n=== Searching for image fallback related files ==="
fd -t f 'useImageFallback|university|news|fallback|placeholder' apps/admin --max-depth 5 2>/dev/null | grep -v '.output' | head -10

# Check for .output in root .gitignore
echo -e "\n=== Checking root .gitignore ==="
if [ -f ".gitignore" ]; then
  cat -n .gitignore | head -30
fi

Repository: solid-connection/solid-connect-web

Length of output: 1022


빌드 결과물이 버전 관리에 포함되어 있습니다.

.output/ 디렉토리의 100개 파일이 Git에 추적되고 있는데, 이들은 모두 Nuxt/Nitro 빌드 시 생성되는 아티팩트입니다. 이 문제를 해결하기 위해 다음 단계들이 필요합니다:

  1. .gitignore.output 패턴 추가

    • 현재 .gitignore에는 .next/, dist, build 같은 빌드 아티팩트 패턴은 있지만 .output은 누락된 상태입니다.
  2. Git에서 추적 중인 .output 파일들 제거

    • 이미 커밋된 100개의 빌드 아티팩트 파일들을 버전 관리에서 제거해야 합니다.
  3. PR 범위 정리

    • 이미지 폴백 기능(useImageFallback, SVG 플레이스홀더)과 관련된 실제 소스 코드만 포함하고 빌드 결과물은 제외해 주세요.

빌드 아티팩트를 커밋하면 저장소 크기가 증가하고, 머지 충돌이 발생할 가능성이 높아지며, 빌드 환경마다 불필요한 차이가 생깁니다.

🤖 Prompt for AI Agents
In `@apps/admin/.output/server/_chunks/_libs/`@radix-ui/react-use-effect-event.mjs
at line 1, Add the `.output` build directory to .gitignore, stop tracking the
already-committed build artifacts by removing all tracked files under the
`.output` directory from Git's index (untrack them without deleting local files)
and commit that removal, then clean up this PR so it only contains the actual
source changes (the image fallback feature: functions/components like
useImageFallback and the SVG placeholder code) and not any files under
`.output`; finally, verify the PR diff contains only the source files related to
the image fallback/SVG placeholder and not Nuxt/Nitro build artifacts.

Comment on lines +10 to +25
const NewsCards = ({ newsList }: NewsCardsProps) => {
const { getSrc, handleError } = useImageFallback("/svgs/placeholders/news-thumbnail-placeholder.svg");

return (
<div className="flex flex-col gap-4">
{newsList.map((news) => (
<a key={news.id} target="_blank" href={news.url} rel="noreferrer">
<div className="flex gap-4">
<Image
className="h-[90px] w-[170px] shrink-0 rounded-xl object-cover"
src={getSrc(news.imageUrl)}
alt={news.title}
width={170}
height={90}
onError={handleError}
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

훅을 컴포넌트 레벨에서 호출하면 모든 이미지가 같은 에러 상태를 공유합니다.

현재 구조에서는:

  1. useImageFallbackNewsCards 레벨에서 한 번만 호출됨
  2. .map()으로 렌더링되는 모든 뉴스 이미지가 동일한 handleErrorgetSrc를 공유
  3. 뉴스 이미지 중 하나라도 로드 실패 시 → hasError = true모든 이미지가 fallback으로 전환
🐛 수정 제안: 개별 NewsCard 컴포넌트 분리
+// 개별 뉴스 카드 컴포넌트
+const NewsCard = ({ news }: { news: News }) => {
+  const { getSrc, handleError } = useImageFallback("/svgs/placeholders/news-thumbnail-placeholder.svg");
+
+  return (
+    <a target="_blank" href={news.url} rel="noreferrer">
+      <div className="flex gap-4">
+        <Image
+          className="h-[90px] w-[170px] shrink-0 rounded-xl object-cover"
+          src={getSrc(news.imageUrl)}
+          alt={news.title}
+          width={170}
+          height={90}
+          onError={handleError}
+        />
+        <div className="mr-5 flex flex-col gap-0.5">
+          <div className="text-serif text-text-brown typo-sb-9">{news.title}</div>
+          <div className="font-serif text-gray-150 typo-regular-6">{news.description}</div>
+        </div>
+      </div>
+    </a>
+  );
+};
+
 const NewsCards = ({ newsList }: NewsCardsProps) => {
-  const { getSrc, handleError } = useImageFallback("/svgs/placeholders/news-thumbnail-placeholder.svg");
-
   return (
     <div className="flex flex-col gap-4">
-      {newsList.map((news) => (
-        <a key={news.id} target="_blank" href={news.url} rel="noreferrer">
-          {/* ... */}
-        </a>
-      ))}
+      {newsList.map((news) => (
+        <NewsCard key={news.id} news={news} />
+      ))}
     </div>
   );
 };
🤖 Prompt for AI Agents
In `@apps/web/src/components/home/NewsCards.tsx` around lines 10 - 25, The hook
useImageFallback is currently called once in NewsCards so getSrc/handleError are
shared across all items causing one image error to flip all images to fallback;
fix by extracting a per-item NewsCard component that receives a single news item
and calls useImageFallback inside it (use the news.imageUrl, news.title,
news.url, news.id there), then update NewsCards to map newsList => <NewsCard
key={news.id} news={news} /> so each card maintains its own getSrc/handleError
state.

Comment on lines +8 to +19
export const useImageFallback = (fallbackSrc: string) => {
const [hasError, setHasError] = useState(false);

const handleError = () => {
setHasError(true);
};

const getSrc = (originalSrc: string) => {
return hasError ? fallbackSrc : originalSrc;
};

return { getSrc, handleError, hasError };
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

훅 설계가 단일 이미지 사용에만 적합합니다.

현재 구현은 하나의 hasError 상태만 관리하므로, 한 컴포넌트에서 여러 이미지를 렌더링할 때 문제가 발생합니다.

NewsCards에서 이 훅을 사용하면 뉴스 목록의 이미지 중 하나라도 로드에 실패하면 모든 뉴스 이미지가 fallback으로 전환됩니다.

해결 방법:

  1. 개별 뉴스 아이템을 별도 컴포넌트로 분리하여 각각 훅 인스턴스를 가지게 하거나
  2. 훅 내부에서 URL별로 에러 상태를 추적하도록 수정
🐛 해결 방안 1: 개별 컴포넌트 분리 (권장)

NewsCards에서 사용할 개별 카드 컴포넌트를 생성합니다:

// NewsCard.tsx (새 파일)
const NewsCard = ({ news }: { news: News }) => {
  const { getSrc, handleError } = useImageFallback("/svgs/placeholders/news-thumbnail-placeholder.svg");
  
  return (
    <a target="_blank" href={news.url} rel="noreferrer">
      <div className="flex gap-4">
        <Image
          className="h-[90px] w-[170px] shrink-0 rounded-xl object-cover"
          src={getSrc(news.imageUrl)}
          alt={news.title}
          width={170}
          height={90}
          onError={handleError}
        />
        {/* ... rest of content */}
      </div>
    </a>
  );
};
🤖 Prompt for AI Agents
In `@apps/web/src/hooks/useImageFallback.ts` around lines 8 - 19, The hook
useImageFallback currently stores a single boolean hasError so one failing image
flips all images; change it to track error state per image URL (e.g., a
Record<string, boolean> or Map) and update getSrc and handleError to accept the
image key/originalSrc so they check/set the per-URL flag; specifically, replace
hasError with something like failedMap, make handleError take the originalSrc
(or an id) and set failedMap[originalSrc] = true, and make getSrc(originalSrc)
return failedMap[originalSrc] ? fallbackSrc : originalSrc so multiple images can
independently fall back while preserving the existing function names
useImageFallback, getSrc, handleError and exposed hasError can be removed or
replaced by a getter that reports failure for a given URL.

@manNomi manNomi merged commit 309b5e2 into main Feb 1, 2026
2 of 6 checks passed
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.

2 participants