Repository navigation
Conversation
📝 WalkthroughWalkthrough3개의 독립 React + TypeScript + Vite 프로젝트를 신규 추가했다. Mission01은 TMDB API를 활용한 영화 검색 SPA이고, Practice01은 Mission01: TMDB 영화 검색 앱
Practice01: useCallback 훅 실습
Practice02: useMemo 훅 실습
Sequence Diagram(s)sequenceDiagram
participant 사용자
participant MovieFilter
participant HomePage
participant useFetch
participant axiosClient
participant TMDB_API
participant MovieModal
사용자->>MovieFilter: 검색어/언어/성인 여부 입력
MovieFilter->>HomePage: onSubmit(draftFilters)
HomePage->>HomePage: submittedFilters 갱신
HomePage->>useFetch: submittedFilters 전달
useFetch->>axiosClient: GET /search/movie (AbortController)
axiosClient->>TMDB_API: api_key + 필터 파라미터
TMDB_API-->>axiosClient: MovieResponse
axiosClient-->>useFetch: data
useFetch-->>HomePage: { data, isLoading, error }
HomePage->>HomePage: useMemo로 results 가공
사용자->>HomePage: MovieCard 클릭
HomePage->>MovieModal: selectedMovie 전달
사용자->>MovieModal: 닫기 또는 오버레이 클릭
MovieModal->>HomePage: onClose 호출
HomePage->>HomePage: selectedMovie 초기화
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (1)
Week10/SJ01-max/Mission01/src/components/MovieFilter.tsx (1)
29-46: ⚡ Quick win폼 입력 필드에 명시적 레이블 연결 추가 권장
영화 제목 입력과 언어 선택기가 명시적인
htmlFor/id연결이 없습니다. 접근성 향상을 위해 다음과 같이 개선하는 것이 좋습니다:💡 제안된 레이블 연결 개선
- <div className="flex-1"> - <label className="mb-1 block text-sm font-semibold text-gray-700"> - 영화 제목 - </label> - <Input value={query} onChange={onQueryChange} /> - </div> + <div className="flex-1"> + <label htmlFor="movie-query" className="mb-1 block text-sm font-semibold text-gray-700"> + 영화 제목 + </label> + <Input id="movie-query" value={query} onChange={onQueryChange} /> + </div>Input 컴포넌트에
idprop을 추가로 지원하도록 수정하면 됩니다.interface InputProps { + id?: string; value: string; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; } function Input({ id, value, onChange }: InputProps) { return ( <input + id={id} value={value} onChange={onChange} placeholder="영화 제목을 입력하세요" className="w-full rounded border border-gray-300 px-3 py-2 text-sm" /> ); }🤖 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 `@Week10/SJ01-max/Mission01/src/components/MovieFilter.tsx` around lines 29 - 46, The form inputs in MovieFilter.tsx lack explicit label connections for accessibility. Modify the Input component to accept and render an id prop. Then in MovieFilter.tsx, add an id prop to the Input component used for the movie title query field, add a corresponding htmlFor attribute to the label wrapping "영화 제목", and add an id to the checkbox input with a corresponding htmlFor on its surrounding label to ensure all form controls are properly associated with their labels for screen reader users.
🤖 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 `@Week10/SJ01-max/Mission01/src/api/axiosClient.ts`:
- Around line 3-11: The axiosClient creation does not validate that the
VITE_TMDB_API_KEY environment variable is defined before using it. Add a
validation check immediately after retrieving import.meta.env.VITE_TMDB_API_KEY
to ensure it exists; if it is undefined or empty, throw a descriptive error that
clearly indicates the missing environment variable. This prevents silent API
failures and makes debugging easier by providing an explicit error message at
initialization time rather than when requests fail.
In `@Week10/SJ01-max/Mission01/src/components/MovieCard.tsx`:
- Around line 15-18: The interactive card element in MovieCard.tsx uses a div
with an onClick handler, which is not keyboard-accessible and prevents users
from navigating and interacting with it via keyboard. Replace the div element
with a button element to enable keyboard navigation and selection, keeping the
onClick handler with onSelect(movie) and the className intact. This semantic
change ensures the card selection is accessible to all users including those
relying on keyboard or assistive technologies.
In `@Week10/SJ01-max/Mission01/src/components/MovieModal.tsx`:
- Around line 16-23: Add accessibility semantics and keyboard support to the
MovieModal component. The inner modal content container (the div with
onClick={(e) => e.stopPropagation()} and the white background) needs two ARIA
attributes: role="dialog" and aria-modal="true" to properly communicate modal
state to screen readers. Additionally, implement ESC key handling by adding a
useEffect hook that listens for the Escape key and calls the onClose callback
when pressed, ensuring keyboard users can close the modal. The ESC handler
should have proper cleanup to remove the event listener when the component
unmounts or when onClose changes.
In `@Week10/SJ01-max/Mission01/src/hooks/useFetch.ts`:
- Around line 17-21: When the query filter is empty in the useFetch hook
useEffect, the data state is reset to null but the error state from previous
requests is not cleared, causing stale error messages to remain visible. Add a
call to reset the error state (likely setError(null)) alongside setData(null) in
the condition that checks if filters.query is empty to ensure both data and
error states are properly initialized when the user clears their search query.
In `@Week10/SJ01-max/Practice01/src/index.css`:
- Around line 14-16: The `value-keyword-case` stylelint rule is being violated
in the CSS custom properties --sans, --heading, and --mono definitions (and
another occurrence at line 24). Convert all mixed-case font family names to
lowercase to comply with the rule: change `Roboto` to `roboto` and `Consolas` to
`consolas` in the respective font-family declarations. Ensure all keyword values
in the CSS use consistent lowercase formatting to pass the stylelint validation
gate.
In `@Week10/SJ01-max/Practice02/src/index.css`:
- Around line 14-16: Fix the stylelint `value-keyword-case` rule violations in
the CSS custom properties for font families. Review and adjust the casing of the
font family values in the CSS variables defined for --sans, --heading, and
--mono (at lines 14-16 and line 24) to comply with stylelint's case
requirements. Ensure all CSS keyword values follow consistent lowercase
formatting as expected by the configured stylelint rules to prevent lint
failures.
In `@Week10/SJ01-max/Practice02/src/utils/math.ts`:
- Around line 9-19: The findPrimeNumbers function does not validate the max
parameter, causing a RangeError when max is non-integer (like 10.5), Infinity,
or NaN when passed to new Array(max + 1). Before creating the sieve array,
normalize max by converting it to a finite integer using Math.floor() and add a
check to ensure max is a valid number. If max becomes invalid after
normalization, return an empty array just like the existing check for max < 2.
---
Nitpick comments:
In `@Week10/SJ01-max/Mission01/src/components/MovieFilter.tsx`:
- Around line 29-46: The form inputs in MovieFilter.tsx lack explicit label
connections for accessibility. Modify the Input component to accept and render
an id prop. Then in MovieFilter.tsx, add an id prop to the Input component used
for the movie title query field, add a corresponding htmlFor attribute to the
label wrapping "영화 제목", and add an id to the checkbox input with a corresponding
htmlFor on its surrounding label to ensure all form controls are properly
associated with their labels for screen reader users.
🪄 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: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 4cecdc3b-d1ff-4165-9263-c59b44bfd440
⛔ Files ignored due to path filters (15)
Week10/SJ01-max/Mission01/package-lock.jsonis excluded by!**/package-lock.jsonWeek10/SJ01-max/Mission01/public/favicon.svgis excluded by!**/*.svgWeek10/SJ01-max/Mission01/public/icons.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice01/package-lock.jsonis excluded by!**/package-lock.jsonWeek10/SJ01-max/Practice01/public/favicon.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice01/public/icons.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice01/src/assets/hero.pngis excluded by!**/*.pngWeek10/SJ01-max/Practice01/src/assets/react.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice01/src/assets/vite.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice02/package-lock.jsonis excluded by!**/package-lock.jsonWeek10/SJ01-max/Practice02/public/favicon.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice02/public/icons.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice02/src/assets/hero.pngis excluded by!**/*.pngWeek10/SJ01-max/Practice02/src/assets/react.svgis excluded by!**/*.svgWeek10/SJ01-max/Practice02/src/assets/vite.svgis excluded by!**/*.svg
📒 Files selected for processing (58)
Week10/SJ01-max/Mission01/.gitignoreWeek10/SJ01-max/Mission01/README.mdWeek10/SJ01-max/Mission01/eslint.config.jsWeek10/SJ01-max/Mission01/index.htmlWeek10/SJ01-max/Mission01/package.jsonWeek10/SJ01-max/Mission01/postcss.config.jsWeek10/SJ01-max/Mission01/src/App.tsxWeek10/SJ01-max/Mission01/src/api/axiosClient.tsWeek10/SJ01-max/Mission01/src/components/Input.tsxWeek10/SJ01-max/Mission01/src/components/LanguageSelector.tsxWeek10/SJ01-max/Mission01/src/components/MovieCard.tsxWeek10/SJ01-max/Mission01/src/components/MovieFilter.tsxWeek10/SJ01-max/Mission01/src/components/MovieList.tsxWeek10/SJ01-max/Mission01/src/components/MovieModal.tsxWeek10/SJ01-max/Mission01/src/components/SelectBox.tsxWeek10/SJ01-max/Mission01/src/constants/movie.tsWeek10/SJ01-max/Mission01/src/hooks/useFetch.tsWeek10/SJ01-max/Mission01/src/index.cssWeek10/SJ01-max/Mission01/src/main.tsxWeek10/SJ01-max/Mission01/src/pages/HomePage.tsxWeek10/SJ01-max/Mission01/src/types/movie.tsWeek10/SJ01-max/Mission01/src/utils/movie.tsWeek10/SJ01-max/Mission01/tsconfig.app.jsonWeek10/SJ01-max/Mission01/tsconfig.jsonWeek10/SJ01-max/Mission01/tsconfig.node.jsonWeek10/SJ01-max/Mission01/vite.config.tsWeek10/SJ01-max/Practice01/.gitignoreWeek10/SJ01-max/Practice01/README.mdWeek10/SJ01-max/Practice01/eslint.config.jsWeek10/SJ01-max/Practice01/index.htmlWeek10/SJ01-max/Practice01/package.jsonWeek10/SJ01-max/Practice01/src/App.cssWeek10/SJ01-max/Practice01/src/App.tsxWeek10/SJ01-max/Practice01/src/UseCallbackPage.tsxWeek10/SJ01-max/Practice01/src/components/CountButton.tsxWeek10/SJ01-max/Practice01/src/components/TextInput.tsxWeek10/SJ01-max/Practice01/src/index.cssWeek10/SJ01-max/Practice01/src/main.tsxWeek10/SJ01-max/Practice01/tsconfig.app.jsonWeek10/SJ01-max/Practice01/tsconfig.jsonWeek10/SJ01-max/Practice01/tsconfig.node.jsonWeek10/SJ01-max/Practice01/vite.config.tsWeek10/SJ01-max/Practice02/.gitignoreWeek10/SJ01-max/Practice02/README.mdWeek10/SJ01-max/Practice02/eslint.config.jsWeek10/SJ01-max/Practice02/index.htmlWeek10/SJ01-max/Practice02/package.jsonWeek10/SJ01-max/Practice02/src/App.cssWeek10/SJ01-max/Practice02/src/App.tsxWeek10/SJ01-max/Practice02/src/UseMemoPage.tsxWeek10/SJ01-max/Practice02/src/components/TextInput.tsxWeek10/SJ01-max/Practice02/src/index.cssWeek10/SJ01-max/Practice02/src/main.tsxWeek10/SJ01-max/Practice02/src/utils/math.tsWeek10/SJ01-max/Practice02/tsconfig.app.jsonWeek10/SJ01-max/Practice02/tsconfig.jsonWeek10/SJ01-max/Practice02/tsconfig.node.jsonWeek10/SJ01-max/Practice02/vite.config.ts
| const axiosClient = axios.create({ | ||
| baseURL: "https://api.themoviedb.org/3", | ||
| params: { | ||
| api_key: import.meta.env.VITE_TMDB_API_KEY, | ||
| }, | ||
| headers: { | ||
| accept: "application/json", | ||
| }, | ||
| }); |
There was a problem hiding this comment.
환경 변수 누락 시 런타임 검증 필요
VITE_TMDB_API_KEY가 정의되지 않았을 경우 undefined가 쿼리 파라미터로 전달되어 모든 API 요청이 실패하지만, 명확한 에러 메시지 없이 조용히 실패합니다.
🛡️ 제안: 초기화 시점에 API 키 존재 여부 검증
import axios from "axios";
+const apiKey = import.meta.env.VITE_TMDB_API_KEY;
+
+if (!apiKey) {
+ throw new Error("VITE_TMDB_API_KEY 환경 변수가 설정되지 않았습니다.");
+}
+
const axiosClient = axios.create({
baseURL: "https://api.themoviedb.org/3",
params: {
- api_key: import.meta.env.VITE_TMDB_API_KEY,
+ api_key: apiKey,
},
headers: {
accept: "application/json",
},
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const axiosClient = axios.create({ | |
| baseURL: "https://api.themoviedb.org/3", | |
| params: { | |
| api_key: import.meta.env.VITE_TMDB_API_KEY, | |
| }, | |
| headers: { | |
| accept: "application/json", | |
| }, | |
| }); | |
| import axios from "axios"; | |
| const apiKey = import.meta.env.VITE_TMDB_API_KEY; | |
| if (!apiKey) { | |
| throw new Error("VITE_TMDB_API_KEY 환경 변수가 설정되지 않았습니다."); | |
| } | |
| const axiosClient = axios.create({ | |
| baseURL: "https://api.themoviedb.org/3", | |
| params: { | |
| api_key: apiKey, | |
| }, | |
| headers: { | |
| accept: "application/json", | |
| }, | |
| }); |
🤖 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 `@Week10/SJ01-max/Mission01/src/api/axiosClient.ts` around lines 3 - 11, The
axiosClient creation does not validate that the VITE_TMDB_API_KEY environment
variable is defined before using it. Add a validation check immediately after
retrieving import.meta.env.VITE_TMDB_API_KEY to ensure it exists; if it is
undefined or empty, throw a descriptive error that clearly indicates the missing
environment variable. This prevents silent API failures and makes debugging
easier by providing an explicit error message at initialization time rather than
when requests fail.
| <div | ||
| onClick={() => onSelect(movie)} | ||
| className="cursor-pointer overflow-hidden rounded-lg bg-white shadow" | ||
| > |
There was a problem hiding this comment.
카드 선택 동작을 키보드로도 수행 가능하게 바꿔주세요.
현재 클릭 가능한 요소가 div라서 키보드 탐색/실행이 막혀 모달 진입이 어려워집니다. 상호작용 루트를 button으로 바꾸는 쪽이 안전합니다.
접근성 보완 예시 diff
- <div
- onClick={() => onSelect(movie)}
- className="cursor-pointer overflow-hidden rounded-lg bg-white shadow"
- >
+ <button
+ type="button"
+ onClick={() => onSelect(movie)}
+ className="w-full cursor-pointer overflow-hidden rounded-lg bg-white text-left shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500"
+ >
@@
- </div>
+ </button>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <div | |
| onClick={() => onSelect(movie)} | |
| className="cursor-pointer overflow-hidden rounded-lg bg-white shadow" | |
| > | |
| <button | |
| type="button" | |
| onClick={() => onSelect(movie)} | |
| className="w-full cursor-pointer overflow-hidden rounded-lg bg-white text-left shadow focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500" | |
| > |
🤖 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 `@Week10/SJ01-max/Mission01/src/components/MovieCard.tsx` around lines 15 - 18,
The interactive card element in MovieCard.tsx uses a div with an onClick
handler, which is not keyboard-accessible and prevents users from navigating and
interacting with it via keyboard. Replace the div element with a button element
to enable keyboard navigation and selection, keeping the onClick handler with
onSelect(movie) and the className intact. This semantic change ensures the card
selection is accessible to all users including those relying on keyboard or
assistive technologies.
| <div | ||
| onClick={onClose} | ||
| className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4" | ||
| > | ||
| <div | ||
| onClick={(e) => e.stopPropagation()} | ||
| className="max-h-full w-full max-w-2xl overflow-y-auto rounded-lg bg-white" | ||
| > |
There was a problem hiding this comment.
모달 접근성 시맨틱과 키보드 닫기 처리를 추가해주세요.
Line 16-23 구간 모달 컨테이너에 role="dialog"/aria-modal="true"가 없고 ESC 키 닫기 핸들링도 없어, 스크린리더·키보드 사용자에게 모달 상태가 명확히 전달되지 않습니다.
수정 예시
- <div
- onClick={onClose}
- className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4"
- >
+ <div
+ onClick={onClose}
+ onKeyDown={(e) => {
+ if (e.key === "Escape") onClose();
+ }}
+ role="dialog"
+ aria-modal="true"
+ aria-label={`${movie.title} 상세 정보`}
+ tabIndex={-1}
+ className="fixed inset-0 z-50 flex items-center justify-center bg-black/70 p-4"
+ >🤖 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 `@Week10/SJ01-max/Mission01/src/components/MovieModal.tsx` around lines 16 -
23, Add accessibility semantics and keyboard support to the MovieModal
component. The inner modal content container (the div with onClick={(e) =>
e.stopPropagation()} and the white background) needs two ARIA attributes:
role="dialog" and aria-modal="true" to properly communicate modal state to
screen readers. Additionally, implement ESC key handling by adding a useEffect
hook that listens for the Escape key and calls the onClose callback when
pressed, ensuring keyboard users can close the modal. The ESC handler should
have proper cleanup to remove the event listener when the component unmounts or
when onClose changes.
| useEffect(() => { | ||
| if (!filters.query) { | ||
| setData(null); | ||
| return; | ||
| } |
There was a problem hiding this comment.
쿼리가 비었을 때 에러 상태도 초기화 필요
query가 비어 있으면 data를 null로 초기화하지만, 이전 요청에서 발생한 error 상태는 그대로 유지됩니다. 사용자가 검색어를 지운 후에도 이전 에러 메시지가 화면에 남게 됩니다.
🐛 제안: 에러 상태도 함께 초기화
useEffect(() => {
if (!filters.query) {
setData(null);
+ setError(null);
return;
}🤖 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 `@Week10/SJ01-max/Mission01/src/hooks/useFetch.ts` around lines 17 - 21, When
the query filter is empty in the useFetch hook useEffect, the data state is
reset to null but the error state from previous requests is not cleared, causing
stale error messages to remain visible. Add a call to reset the error state
(likely setError(null)) alongside setData(null) in the condition that checks if
filters.query is empty to ensure both data and error states are properly
initialized when the user clears their search query.
| --sans: system-ui, 'Segoe UI', Roboto, sans-serif; | ||
| --heading: system-ui, 'Segoe UI', Roboto, sans-serif; | ||
| --mono: ui-monospace, Consolas, monospace; |
There was a problem hiding this comment.
Stylelint 규칙 위반으로 lint 단계가 깨질 수 있습니다.
Line 14, Line 15, Line 16, Line 24의 값 대소문자가 현재 value-keyword-case 규칙과 충돌합니다. 린트 게이트를 사용 중이면 이 PR이 차단될 수 있습니다.
수정 예시 diff
- --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
- --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
- --mono: ui-monospace, Consolas, monospace;
+ --sans: system-ui, 'Segoe UI', roboto, sans-serif;
+ --heading: system-ui, 'Segoe UI', roboto, sans-serif;
+ --mono: ui-monospace, consolas, monospace;
@@
- text-rendering: optimizeLegibility;
+ text-rendering: optimizelegibility;Also applies to: 24-24
🧰 Tools
🪛 Stylelint (17.13.0)
[error] 14-14: Expected "Roboto" to be "roboto" (value-keyword-case)
(value-keyword-case)
[error] 15-15: Expected "Roboto" to be "roboto" (value-keyword-case)
(value-keyword-case)
[error] 16-16: Expected "Consolas" to be "consolas" (value-keyword-case)
(value-keyword-case)
🤖 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 `@Week10/SJ01-max/Practice01/src/index.css` around lines 14 - 16, The
`value-keyword-case` stylelint rule is being violated in the CSS custom
properties --sans, --heading, and --mono definitions (and another occurrence at
line 24). Convert all mixed-case font family names to lowercase to comply with
the rule: change `Roboto` to `roboto` and `Consolas` to `consolas` in the
respective font-family declarations. Ensure all keyword values in the CSS use
consistent lowercase formatting to pass the stylelint validation gate.
Source: Linters/SAST tools
| --sans: system-ui, 'Segoe UI', Roboto, sans-serif; | ||
| --heading: system-ui, 'Segoe UI', Roboto, sans-serif; | ||
| --mono: ui-monospace, Consolas, monospace; |
There was a problem hiding this comment.
Stylelint 오류를 정리해 린트 실패 가능성을 제거하세요.
Line 14, Line 15, Line 16, Line 24에서 value-keyword-case 규칙 위반이 보고됩니다. 현재 설정에서 스타일 린트를 돌리면 실패할 수 있으니 이 PR에서 같이 맞추는 게 안전합니다.
🔧 제안 수정안
- --sans: system-ui, 'Segoe UI', Roboto, sans-serif;
- --heading: system-ui, 'Segoe UI', Roboto, sans-serif;
- --mono: ui-monospace, Consolas, monospace;
+ --sans: system-ui, 'Segoe UI', roboto, sans-serif;
+ --heading: system-ui, 'Segoe UI', roboto, sans-serif;
+ --mono: ui-monospace, consolas, monospace;
- text-rendering: optimizeLegibility;
+ text-rendering: optimizelegibility;Also applies to: 24-24
🧰 Tools
🪛 Stylelint (17.13.0)
[error] 14-14: Expected "Roboto" to be "roboto" (value-keyword-case)
(value-keyword-case)
[error] 15-15: Expected "Roboto" to be "roboto" (value-keyword-case)
(value-keyword-case)
[error] 16-16: Expected "Consolas" to be "consolas" (value-keyword-case)
(value-keyword-case)
🤖 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 `@Week10/SJ01-max/Practice02/src/index.css` around lines 14 - 16, Fix the
stylelint `value-keyword-case` rule violations in the CSS custom properties for
font families. Review and adjust the casing of the font family values in the CSS
variables defined for --sans, --heading, and --mono (at lines 14-16 and line 24)
to comply with stylelint's case requirements. Ensure all CSS keyword values
follow consistent lowercase formatting as expected by the configured stylelint
rules to prevent lint failures.
Source: Linters/SAST tools
| export function findPrimeNumbers(max: number): (number | null)[] { | ||
| if (max < 2) return []; | ||
|
|
||
| const sieve = new Array<boolean>(max + 1).fill(true); | ||
| sieve[0] = false; | ||
| sieve[1] = false; | ||
|
|
||
| for (let i = 2; i * i <= max; i++) { | ||
| if (sieve[i]) { | ||
| for (let j = i * i; j <= max; j += i) { | ||
| sieve[j] = false; |
There was a problem hiding this comment.
비정수/무한대 입력 시 배열 길이 예외로 크래시가 발생합니다.
Line 12의 new Array(max + 1)은 max가 10.5, Infinity, NaN이면 RangeError를 유발합니다. max를 유한한 정수로 정규화한 뒤 sieve를 생성해야 합니다.
수정 예시
export function findPrimeNumbers(max: number): (number | null)[] {
- if (max < 2) return [];
+ if (!Number.isFinite(max)) return [];
+ const safeMax = Math.floor(max);
+ if (safeMax < 2) return [];
- const sieve = new Array<boolean>(max + 1).fill(true);
+ const sieve = new Array<boolean>(safeMax + 1).fill(true);
sieve[0] = false;
sieve[1] = false;
- for (let i = 2; i * i <= max; i++) {
+ for (let i = 2; i * i <= safeMax; i++) {
if (sieve[i]) {
- for (let j = i * i; j <= max; j += i) {
+ for (let j = i * i; j <= safeMax; j += i) {
sieve[j] = false;
}
}
}🤖 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 `@Week10/SJ01-max/Practice02/src/utils/math.ts` around lines 9 - 19, The
findPrimeNumbers function does not validate the max parameter, causing a
RangeError when max is non-integer (like 10.5), Infinity, or NaN when passed to
new Array(max + 1). Before creating the sieve array, normalize max by converting
it to a finite integer using Math.floor() and add a check to ensure max is a
valid number. If max becomes invalid after normalization, return an empty array
just like the existing check for max < 2.
📝 미션 번호
10주차 practice01
10주차 practice02
10주차 Misson 1
📋 구현 사항
📎 스크린샷
📝 미션 번호
10주차 practice02
📋 구현 사항
📎 스크린샷
📝 미션 번호
10주차 Misson 1
📋 구현 사항
📎 스크린샷
✅ 체크리스트
🤔 질문 사항
Summary by CodeRabbit
릴리스 노트
New Features
Chores