-
Notifications
You must be signed in to change notification settings - Fork 0
fix: 3차 QA #193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: 3차 QA #193
Changes from all commits
bad0d1f
4859ad9
c243dfe
c9ba2a9
1151c79
d825705
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,8 +47,14 @@ export const getRoomMembers = async (roomId: number): Promise<RoomMembersRespons | |
| try { | ||
| const response = await apiClient.get<RoomMembersResponse>(`/rooms/${roomId}/users`); | ||
| return response.data; | ||
| } catch (error) { | ||
| } catch (error: any) { | ||
| console.error('독서메이트 조회 API 오류:', error); | ||
|
|
||
| // 방 접근 권한이 없는 경우 | ||
| if (error.response?.data?.code === 140011) { | ||
| throw new Error('방 접근 권한이 없습니다.'); | ||
| } | ||
|
|
||
|
Comment on lines
+50
to
+57
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chaincatch 문의 any 제거 및 오류 정제 — ESLint(no-explicit-any) 해결 ESLint 에러(Unexpected any)를 유발하는 다음과 같이 수정 제안: - } catch (error: any) {
+ } catch (error: unknown) {
console.error('독서메이트 조회 API 오류:', error);
-
- // 방 접근 권한이 없는 경우
- if (error.response?.data?.code === 140011) {
- throw new Error('방 접근 권한이 없습니다.');
- }
-
+
+ // 방 접근 권한이 없는 경우
+ const apiCode =
+ typeof (error as { response?: { data?: { code?: number } } })?.response?.data?.code === 'number'
+ ? (error as { response?: { data?: { code?: number } } }).response!.data!.code
+ : undefined;
+ if (apiCode === 140011) {
+ throw new Error('방 접근 권한이 없습니다.');
+ // TS 4.6+ 사용 시 원인 보존:
+ // throw new Error('방 접근 권한이 없습니다.', { cause: error });
+ }
throw error;
}추가 제안:
검증 스크립트(리포지토리 내 🏁 Script executed: #!/bin/bash
# catch (error: any) 패턴 점검
rg -nP --type=ts --type=tsx -C1 'catch\s*\(\s*error\s*:\s*any\s*\)'Length of output: 97 rg가 🏁 Script executed: #!/bin/bash
# catch (error: any) 패턴 점검 (.ts, .tsx 파일)
rg -n -C1 "catch\s*\(\s*error\s*:\s*any\s*\)" -g "*.ts" -g "*.tsx"Length of output: 901 catch(error: any) 제거 및 unknown으로 대체 — 여러 파일에 일관성 있게 적용 필요 ESLint
예시 (src/api/rooms/getRoomMembers.ts): - } catch (error: any) {
+ } catch (error: unknown) {
console.error('독서메이트 조회 API 오류:', error);
- // 방 접근 권한이 없는 경우
- if (error.response?.data?.code === 140011) {
- throw new Error('방 접근 권한이 없습니다.');
- }
+ // 방 접근 권한이 없는 경우
+ const apiCode =
+ typeof (error as { response?: { data?: { code?: number } } })?.response?.data?.code === 'number'
+ ? (error as { response?: { data?: { code?: number } } }).response!.data!.code
+ : undefined;
+ if (apiCode === 140011) {
+ // TS 4.6+ 환경에서는 원인(cause)도 함께 전달 가능
+ // throw new Error('방 접근 권한이 없습니다.', { cause: error });
+ throw new Error('방 접근 권한이 없습니다.');
+ }
throw error;
}추가 제안:
검증 스크립트 (catch(error: any) 패턴 전역 점검): rg -n -C1 "catch\s*\(\s*error\s*:\s*any\s*\)" -g "*.ts" -g "*.tsx"🧰 Tools🪛 ESLint[error] 50-50: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||
| throw error; | ||
| } | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -269,14 +269,20 @@ const RecordItem = ({ record, shouldBlur = false }: RecordItemProps) => { | |
| const handleClick = useCallback(() => { | ||
| // 클릭으로 더보기 메뉴 표시 | ||
| if (isMyRecord) { | ||
| openMoreMenu({ | ||
| const menuOptions: any = { | ||
| onEdit: handleEdit, | ||
| onDelete: handleDeleteConfirm, | ||
| onPin: handlePinConfirm, | ||
| onClose: closePopup, | ||
| type: 'post', | ||
| isWriter: true, | ||
| }); | ||
| }; | ||
|
|
||
| // 기록(text)일 때만 핀하기 기능 추가 | ||
| if (type === 'text') { | ||
| menuOptions.onPin = handlePinConfirm; | ||
| } | ||
|
|
||
| openMoreMenu(menuOptions); | ||
| } else { | ||
|
Comment on lines
+272
to
286
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ESLint: any 사용으로 린트 오류 발생 — 명시적 타입으로 교체 필요 menuOptions에 any를 사용해 (@typescript-eslint/no-explicit-any) 오류가 납니다. Menu 옵션 타입을 선언해 적용해 주세요. 변경 예시(diff, 해당 블록): - const menuOptions: any = {
+ const menuOptions: MoreMenuOptions = {
onEdit: handleEdit,
onDelete: handleDeleteConfirm,
onClose: closePopup,
type: 'post',
isWriter: true,
};
// 기록(text)일 때만 핀하기 기능 추가
if (type === 'text') {
- menuOptions.onPin = handlePinConfirm;
+ menuOptions.onPin = handlePinConfirm;
}
openMoreMenu(menuOptions);파일 상단(예: import 아래)에 타입 추가(보조 코드): type MoreMenuOptionsBase = {
onClose: () => void;
type: 'post';
isWriter: boolean;
};
type WriterMenuOptions = MoreMenuOptionsBase & {
onEdit: () => void;
onDelete: () => void;
onPin?: () => void; // text일 때만 노출
};
type ReaderMenuOptions = MoreMenuOptionsBase & {
onReport: () => void;
isWriter: false;
};
// 이 블록에서는 작성자 옵션을 사용
type MoreMenuOptions = WriterMenuOptions;openMoreMenu가 공용 타입을 갖고 있다면 해당 타입으로 교체하는 것이 최선입니다. 🧰 Tools🪛 ESLint[error] 272-272: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||
| openMoreMenu({ | ||
| onReport: handleReport, | ||
|
|
@@ -285,6 +291,7 @@ const RecordItem = ({ record, shouldBlur = false }: RecordItemProps) => { | |
| } | ||
| }, [ | ||
| isMyRecord, | ||
| type, | ||
| openMoreMenu, | ||
| handleReport, | ||
| handleEdit, | ||
|
|
@@ -365,7 +372,7 @@ const RecordItem = ({ record, shouldBlur = false }: RecordItemProps) => { | |
| <img src={commentIcon} alt="댓글" /> | ||
| <span>{commentCount}</span> | ||
| </ActionButton> | ||
| {isMyRecord && ( | ||
| {isMyRecord && type === 'text' && ( | ||
| <ActionButton | ||
| onClick={ | ||
| shouldBlur | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -97,8 +97,21 @@ const GroupDetail = () => { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setError(response.message); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } catch (error: any) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| console.error('방 상세 정보 조회 실패:', error); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 모집기간이 만료된 방인 경우 - 진행중인 방으로 리다이렉트 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error.message === '모집기간이 만료된 방입니다.') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| navigate(`/group/detail/joined/${roomId}`, { replace: true }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if (error.message === '방 접근 권한이 없습니다.') { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| navigate('/group', { replace: true }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+100
to
+114
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any 제거 및 안전한 message 접근(+ 변수명 섀도잉 해소) ESLint 에러(@typescript-eslint/no-explicit-any)를 해결하고, state 변수 아래처럼 수정을 제안합니다: - } catch (error: any) {
- console.error('방 상세 정보 조회 실패:', error);
-
- // 모집기간이 만료된 방인 경우 - 진행중인 방으로 리다이렉트
- if (error.message === '모집기간이 만료된 방입니다.') {
+ } catch (err: unknown) {
+ console.error('방 상세 정보 조회 실패:', err);
+
+ const msg = err instanceof Error ? err.message : '';
+
+ // 모집기간이 만료된 방인 경우 - 진행중인 방으로 리다이렉트
+ if (msg === '모집기간이 만료된 방입니다.') {
navigate(`/group/detail/joined/${roomId}`, { replace: true });
return;
}
-
- // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
- if (error.message === '방 접근 권한이 없습니다.') {
+
+ // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
+ if (msg === '방 접근 권한이 없습니다.') {
navigate('/group', { replace: true });
return;
}📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 100-100: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setError('방 정보를 불러오는데 실패했습니다.'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| setIsLoading(false); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -74,9 +74,16 @@ const ParticipatedGroupDetail = () => { | |||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||
| setError(response.message); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
| } catch (err) { | ||||||||||||||||||||||||||||||||||||||||||
| setError('방 정보를 불러오는 중 오류가 발생했습니다.'); | ||||||||||||||||||||||||||||||||||||||||||
| } catch (err: any) { | ||||||||||||||||||||||||||||||||||||||||||
| console.error('방 상세 정보 조회 오류:', err); | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트 | ||||||||||||||||||||||||||||||||||||||||||
| if (err.message === '방 접근 권한이 없습니다.') { | ||||||||||||||||||||||||||||||||||||||||||
| navigate('/group', { replace: true }); | ||||||||||||||||||||||||||||||||||||||||||
| return; | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| setError('방 정보를 불러오는 중 오류가 발생했습니다.'); | ||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+77
to
+86
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ESLint: any 제거 및 안전한 에러 판별로 보강 필요 catch (err: any)는 린트 규칙에 위배됩니다. unknown으로 받고 Error 인스턴스 여부를 판정해 주세요. 메시지 비교도 그 안에서 수행하면 안전합니다. - } catch (err: any) {
+ } catch (err: unknown) {
console.error('방 상세 정보 조회 오류:', err);
-
- // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
- if (err.message === '방 접근 권한이 없습니다.') {
+ // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
+ if (err instanceof Error && err.message === '방 접근 권한이 없습니다.') {
navigate('/group', { replace: true });
return;
}
setError('방 정보를 불러오는 중 오류가 발생했습니다.');📝 Committable suggestion
Suggested change
🧰 Tools🪛 ESLint[error] 77-77: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||
| } finally { | ||||||||||||||||||||||||||||||||||||||||||
| setLoading(false); | ||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -42,9 +42,16 @@ const GroupMembers = () => { | |
| } else { | ||
| setError(response.message); | ||
| } | ||
| } catch (err) { | ||
| setError('독서메이트 목록을 불러오는 중 오류가 발생했습니다.'); | ||
| } catch (err: any) { | ||
| console.error('독서메이트 조회 오류:', err); | ||
|
|
||
| // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트 | ||
| if (err.message === '방 접근 권한이 없습니다.') { | ||
| navigate('/group', { replace: true }); | ||
| return; | ||
| } | ||
|
|
||
| setError('독서메이트 목록을 불러오는 중 오류가 발생했습니다.'); | ||
| } finally { | ||
|
Comment on lines
+45
to
55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 💡 Verification agent 🧩 Analysis chain
현 상태는 ESLint 오류( - } catch (err: any) {
- console.error('독서메이트 조회 오류:', err);
-
- // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
- if (err.message === '방 접근 권한이 없습니다.') {
- navigate('/group', { replace: true });
- return;
- }
-
- setError('독서메이트 목록을 불러오는 중 오류가 발생했습니다.');
+ } catch (err: unknown) {
+ console.error('독서메이트 조회 오류:', err);
+
+ // 방 접근 권한이 없는 경우 - 모임 홈으로 리다이렉트
+ if (err instanceof Error && err.message === '방 접근 권한이 없습니다.') {
+ navigate('/group', { replace: true });
+ return;
+ }
+
+ setError('독서메이트 목록을 불러오는 중 오류가 발생했습니다.');선택 개선(후속 PR 권장): 메시지 문자열 비교 대신 에러의 다음 유틸을 도입하면 메시지/코드 모두 지원 가능합니다. const ACCESS_DENIED_CODE = 140011 as const;
const isAccessDenied = (e: unknown) =>
(typeof (e as any)?.code === 'number' && (e as any).code === ACCESS_DENIED_CODE) ||
(e instanceof Error && e.message === '방 접근 권한이 없습니다.');그리고 레포 전반 메시지 의존 여부 점검 스크립트: 🏁 Script executed: #!/bin/bash
# 문자열 의존 탐색
rg -nP --glob '!**/node_modules/**' "방 접근 권한이 없습니다\."Length of output: 1447
예시: GroupMembers.tsx - } catch (err: any) {
- console.error('독서메이트 조회 오류:', err);
+ } catch (err: unknown) {
+ console.error('독서메이트 조회 오류:', err);선택 리팩토링 제안 const ACCESS_DENIED_CODE = 140011 as const;
const isAccessDenied = (e: unknown) =>
(typeof (e as any)?.code === 'number' && (e as any).code === ACCESS_DENIED_CODE) ||
(e instanceof Error && e.message === '방 접근 권한이 없습니다.');
if (isAccessDenied(err)) {
navigate('/group', { replace: true });
return;
}🧰 Tools🪛 ESLint[error] 45-45: Unexpected any. Specify a different type. (@typescript-eslint/no-explicit-any) 🤖 Prompt for AI Agents |
||
| setLoading(false); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
catch 문의 any 제거 및 Axios 타입 가드로 안전한 분기
ESLint가 지적한 대로 any 사용을 제거하고, Axios 에러에만 안전하게 분기하도록 가드를 추가하는 편이 좋습니다. 또한 rethrow 시 원본 에러 객체를 유지하십시오.
아래와 같이 변경을 제안합니다:
추가로, 파일 상단에 아래 import가 필요합니다(선택 적용):
+import { isAxiosError } from 'axios';Also applies to: 58-58
🧰 Tools
🪛 ESLint
[error] 45-45: Unexpected any. Specify a different type.
(@typescript-eslint/no-explicit-any)
🤖 Prompt for AI Agents