Skip to content

Commit 05dae4d

Browse files
authored
docs: clean up and fix debug documentation (#562)
1 parent 710b4f0 commit 05dae4d

File tree

8 files changed

+35
-30
lines changed

8 files changed

+35
-30
lines changed

fundamentals/debug/pages/diagnose/map.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,25 @@
3131
아래 코드에는 치명적인 오류가 있는데요, 작업 지도를 하나씩 검증하며 어디에 문제가 발생하는지 살펴보아요.
3232

3333
```tsx 8,15,19,26
34-
import React, { useState } from "react";
34+
import { useState } from "react";
3535

36-
const ValidatedInput = () => {
36+
function ValidatedInput() {
3737
const [input, setInput] = useState("");
3838
const [isValid, setIsValid] = useState(true);
3939

4040
const validate = (value) => {
41-
//2. 입력이 바뀔 때마다 유효성 검사 함수가 실행돼요:"
41+
// 2. 입력이 바뀔 때마다 유효성 검사 함수가 실행돼요
4242
const valid = value.length < 5;
4343
return valid;
4444
};
4545

4646
const handleChange = (e) => {
4747
const value = e.target.value;
48-
//1. 사용자가 검색 입력창에 키워드를 입력해요
48+
// 1. 사용자가 검색 입력창에 키워드를 입력해요
4949
setInput(value);
5050

5151
const result = validate(value);
52-
//3. 검사 결과에 따라 true/false를 반환해요
52+
// 3. 검사 결과에 따라 true/false를 반환해요
5353
setIsValid(result);
5454
};
5555

@@ -60,15 +60,15 @@ const ValidatedInput = () => {
6060
{isValid && <div style={{ color: "red" }}>Error message</div>}
6161
</div>
6262
);
63-
};
63+
}
6464
export default ValidatedInput;
6565
```
6666

6767
![](../../images/diagnose/map-check.png)
6868

6969
## 에러 도출
7070

71-
검증 결과, `isValid &&` 조건으로 작성된 에러 UI 렌더링 부분에 **논리 오류**가 있었어요.`isValid === false`로 작성해야 하는데, `isValid &&`로 되어 있어서, **정상적인 UI가 아닌, 잘못된 조건에 의해 오류 메시지가 렌더링**되고 있었어요.
71+
검증 결과, `isValid &&` 조건으로 작성된 에러 UI 렌더링 부분에 **논리 오류**가 있었어요.`isValid === false &&`로 작성해야 하는데, `isValid &&`로 되어 있어서, **정상적인 UI가 아닌, 잘못된 조건에 의해 오류 메시지가 렌더링**되고 있었어요.
7272

7373
```tsx 4
7474
return (

fundamentals/debug/pages/fix/correct.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,15 @@ console.log(selectedUser?.name ?? "사용자 없음");
5454
```tsx
5555
function SearchBox() {
5656
const [query, setQuery] = useState("");
57-
const [result, setResult] = useState("");
57+
const [results, setResults] = useState([]);
5858

5959
useEffect(() => {
6060
if (!query) return;
6161

6262
fetch(`/api/search?q=${query}`)
6363
.then((res) => res.json())
6464
.then((data) => {
65-
setResult(data);
65+
setResults(data);
6666
});
6767
}, [query]);
6868

fundamentals/debug/pages/fix/dead-code.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ A/B 테스트가 끝났는데 분기 코드가 남아 있으면, 독자가 “
5656

5757
```tsx
5858
export function RecommendationBanner({ variant }: { variant: "A" | "B" }) {
59-
//TODO:: 종료된 실험 제거 (실험안 A으로 종료)
59+
//TODO: 종료된 실험 제거 (실험안 A로 종료)
6060
if (variant === "A") {
6161
return <BannerA />;
6262
} else {

fundamentals/debug/pages/fix/pure.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,11 @@ function OrderSummary({
7272

7373
## 예시: React Hook을 활용해 팝업창을 보여줄 때
7474

75-
react의 hook예시도 들어볼게요. 모달을 보여주는 로직이에요.
75+
react의 hook 예시도 들어볼게요. 모달을 보여주는 로직이에요.
7676

7777
### 기존코드
7878

79-
`localStorage`, `isTodayShown`등과 같은 여러 로직이 `useEffect` 내부에 흩어져 있어 모듈화되어 있지 않아요. 그래서 가독성도 떨어지고, 테스트도 어려워요3.
79+
`localStorage`, `isTodayShown`등과 같은 여러 로직이 `useEffect` 내부에 흩어져 있어 모듈화되어 있지 않아요. 그래서 가독성도 떨어지고, 테스트도 어려워요.
8080

8181
```tsx
8282
const STORAGE_KEY = "notification-modal-shownAt";
@@ -141,6 +141,8 @@ export function setLocalStorageValue(key: string, value: string): void {
141141
**utils/modal.ts**
142142

143143
```tsx
144+
import { getLocalStorageValue, setLocalStorageValue } from "./localStorage";
145+
144146
export function getIsModalShownToday(modalKey: string) {
145147
const lastShown = getLocalStorageValue(modalKey);
146148
const todayDateString = new Date().toDateString();
@@ -158,7 +160,7 @@ export function setModalShownToday(modalKey: string) {
158160

159161
```tsx
160162
import { useEffect, useState } from "react";
161-
import { useNotificationAgreementState } from "./useNotificationAgreementState"; // 필요 시 경로 조정
163+
import { getIsModalShownToday, setModalShownToday } from "./utils/modal";
162164

163165
const MODAL_KEY = "test1";
164166
export function useIsModalShow() {
@@ -170,7 +172,7 @@ export function useIsModalShow() {
170172
setModalShownToday(MODAL_KEY);
171173
setShowModal(true);
172174
}
173-
}, [isAgreed]);
175+
}, []);
174176

175177
const close = () => {
176178
setShowModal(false);
@@ -186,15 +188,15 @@ export function useIsModalShow() {
186188
**HomePage.tsx**
187189

188190
```tsx
189-
import { useIsModalShow } from './hooks/useIsModalShow';
191+
import { useIsModalShow } from "./hooks/useIsModalShow";
190192

191193
function HomePage() {
192194
const { showModal, close } = useIsModalShow();
193195

194196
return (
195197
<>
196198
<h1>Welcome!</h1>
197-
<Modal isOpen={showModal} onAgree={agree} onClose={close} />}
199+
<Modal isOpen={showModal} onClose={close} />
198200
</>
199201
);
200202
}

fundamentals/debug/pages/prevent/util.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ UI 개발 도중 사용한 더미 이름, 가짜 텍스트(“김토스님”,
7878

7979
### 해결방법
8080

81-
ESLint로 특정 문자열(“김토스”, “홍길동”, “테스트용” 등) 포함 시 에러 발생하도록 설정해요. `no-restricted-syntax`는특정 구문(Syntax)을 아예 사용하지 못하도록 제한하는 ESLint 규칙이에요.
81+
ESLint로 특정 문자열(“김토스”, “홍길동”, “테스트용” 등) 포함 시 에러 발생하도록 설정해요. `no-restricted-syntax`는 특정 구문(Syntax)을 아예 사용하지 못하도록 제한하는 ESLint 규칙이에요.
8282

8383
```js 6
8484
module.exports = {

fundamentals/debug/pages/reproduce/repeat.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
예를 들어, 동일한 요청이 여러 번 반복될 때 비정상적인 화면이 보여지는 버그 리포트를 받았다고 가정해 볼게요. 이 문제를 재현하기 위해, 다음처럼 **자동 클릭 함수**를 만들어 반복적인 클릭 상황을 만들어 볼 수 있어요. 그리고 디버거를 걸어서 중간 중간 값이 어떻게 변경되는지 추적해볼 수 있어요.
1212

1313
```tsx
14-
import React, { useState } from "react";
14+
import { useState } from "react";
1515

1616
function simulateRapidClicks(
1717
target: HTMLElement,
@@ -26,7 +26,7 @@ function simulateRapidClicks(
2626
}, interval);
2727
}
2828

29-
const DoubleClickTest = () => {
29+
function DoubleClickTest() {
3030
const [count, setCount] = useState(0);
3131
const [disabled, setDisabled] = useState(false);
3232

@@ -53,7 +53,7 @@ const DoubleClickTest = () => {
5353
<button onClick={handleAutoClick}>자동 광클 재현</button>
5454
</div>
5555
);
56-
};
56+
}
5757

5858
export default DoubleClickTest;
5959
```

fundamentals/debug/pages/reproduce/simply.md

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88

99
예를 들어, 숫자 배열에서 짝수만 필터링하는 로직에 문제가 생겼다고 가정해볼게요. 원래 코드에서는 컴포넌트에서 하는 일이 많아서 어디서부터 문제가 발생한 건지 알기 어려워요.
1010

11-
현재 컴포넌트에서는 데이터 fetching, 필터링 로직, 상태 업데이트, 사용자 이벤트 처리가 하나의 함수 안에 모여 있어요. 이처럼 책임이 분리되지 않으면, 특정 결과(filteredNumbers)가 잘못되었을 때 어떤 로직에서 문제가 발생했는지 파악하기가 어려워요. 특히 여러 상태 변화가 엮여 있을 경우, 상태 간의 상호작용이나 렌더 타이밍까지 함께 고려해야 하므로 디버깅이 복잡해질 수 있어요.
11+
현재 컴포넌트에서는 데이터 fetching, 필터링 로직, 상태 업데이트, 사용자 이벤트 처리가 하나의 함수 안에 모여 있어요. 이처럼 책임이 분리되지 않으면, 특정 결과(`filteredNumbers`)가 잘못되었을 때 어떤 로직에서 문제가 발생했는지 파악하기가 어려워요. 특히 여러 상태 변화가 엮여 있을 경우, 상태 간의 상호작용이나 렌더 타이밍까지 함께 고려해야 하므로 디버깅이 복잡해질 수 있어요.
1212

1313
```tsx
14-
import React, { useState, useEffect } from "react";
14+
import { useState, useEffect } from "react";
1515

1616
function filterEvenNumbers(numbers) {
1717
return numbers.filter((num) => {
18-
return num % 2 === 1;
18+
return num % 2 === 0;
1919
});
2020
}
2121

@@ -73,28 +73,31 @@ export default ComplexComponent;
7373

7474
### 간단하게 줄여보기
7575

76-
위 코드를 아래 코드처럼 간단하게 줄여서 테스트해볼 수 있어요. 원래 컴포넌트의 상태 관리, 비동기 호출, UI 요소를 제거하고, 핵심 로직인 filterEvenNumbers 함수만 간단한 배열로 테스트할 수 있도록 최소한의 코드로 줄였어요.
76+
위 코드를 아래 코드처럼 간단하게 줄여서 테스트해볼 수 있어요. 원래 컴포넌트의 상태 관리, 비동기 호출, UI 요소를 제거하고, 핵심 로직인 `filterEvenNumbers` 함수만 간단한 배열로 테스트할 수 있도록 최소한의 코드로 줄였어요.
7777

7878
이렇게 코드를 단순화하면 복잡한 상태 관리나 네트워크 요청 없이도 문제가 발생하는 조건만으로 에러를 재현할 수 있어요.
7979
이런 방식으로 문제를 단순하게 재현하고, 원인을 찾은 다음 원래 코드에 다시 반영하면 돼요.
8080

8181
```tsx
82-
import React, { useEffect } from "react";
82+
import { useState, useEffect } from "react";
8383

8484
function filterEvenNumbers(numbers) {
8585
return numbers.filter((num) => {
86-
return num % 2 === 1;
86+
return num % 2 === 0;
8787
});
8888
}
8989

90-
const SimpleComponent = () => {
90+
function SimpleComponent() {
91+
const [filteredNumbers, setFilteredNumbers] = useState([]);
92+
9193
useEffect(() => {
9294
const testArray = [1, 2, 3, 4, 5, 6];
9395
const result = filterEvenNumbers(testArray);
96+
setFilteredNumbers(result);
9497
}, []);
9598

96-
return <div>테스트 중...</div>;
97-
};
99+
return <div>filteredNumbers: {filteredNumbers.join(", ")}</div>;
100+
}
98101

99102
export default SimpleComponent;
100103
```

fundamentals/debug/pages/reproduce/trace.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,4 @@
1616

1717
**이전 상태가 현재 동작에 영향을 줄 수 있어요**
1818

19-
- 버그가 발생한 화면만 보지 말고, **그 전에 어떤 상태였는지를 함께 살펴봐야 해요.** 예를들어, `A 화면에서 특정 항목을 선택한 후, B 화면으로 넘어왔을 때만 발생함`처럼, **이전 컨텍스트가 버그의 중요한 재현 조건이 되는 경우**가 많아요.
19+
- 버그가 발생한 화면만 보지 말고, **그 전에 어떤 상태였는지를 함께 살펴봐야 해요.** 예를 들어, `A 화면에서 특정 항목을 선택한 후, B 화면으로 넘어왔을 때만 발생함`처럼, **이전 컨텍스트가 버그의 중요한 재현 조건이 되는 경우**가 많아요.

0 commit comments

Comments
 (0)