Skip to content

Commit f07ff16

Browse files
milooyjongtaek-oh
andauthored
Refactor/til prompt (#607)
* docs: 불필요한 prompt 정리 * refactor: 레이아웃 컴포넌트를 main.tsx에서 추출 (why: 다른 라우트 컴포넌트들의 분리 기준과 일관성을 맞춰주기 위해) * refactor: TimelinePage 컴포넌트 body에 있던 로직들을 최대한 응집해주기 (인라인, 사용처와 최대한 가깝게 이동) * refactor: TimelinePage 리팩토링 마무리 - PostInput 관련 로직 응집 - UserAvatar 컴포넌트 분리 + useAuth 응집 - UnauthenticatedState -> GoToLogin으로 이름 변경 * refactor: sortOption을 url query params로 분리 * refactor: SprintChallenge 컴포넌트 내부 구현 단순화 * chore: 리팩토링 할만한 포인트 메모 * refactor: PostInput을 PostWriteSection으로 리팩토링 (div -> form) --------- Co-authored-by: jongtaek-oh <[email protected]>
1 parent 82210f8 commit f07ff16

File tree

13 files changed

+245
-354
lines changed

13 files changed

+245
-354
lines changed

fundamentals/today-i-learned/.claude/development.md

Lines changed: 8 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,6 @@
1414
- 의존성 해결은 워크스페이스 루트에서 관리됨
1515
- 개별 패키지 작업 시에도 상위 yarn 설정을 참조
1616

17-
## TDD 및 커밋 규칙
18-
19-
### TDD 주기 (필수)
20-
21-
1. **Red**: 실패하는 테스트 작성
22-
2. **Green**: 테스트를 통과하는 최소한의 코드 구현
23-
3. **Refactor**: 테스트가 통과하는 상태에서 코드 개선
24-
25-
### 구조적/행위적 변경 분리 (필수)
26-
27-
- **구조적 변경**: 이름 변경, 메서드 추출, 파일 이동 등
28-
- **행위적 변경**: 실제 기능 추가/수정
29-
- **절대 같은 커밋에 섞지 않음**
30-
31-
### 커밋 규칙
32-
33-
- 모든 테스트가 통과할 때만 커밋
34-
- 컴파일러/린터 경고 해결 후 커밋
35-
- `--no-verify` 사용 금지
36-
- 구조적 변경을 먼저, 행위적 변경을 나중에
37-
3817
## Import 규칙 (필수)
3918

4019
### 절대 경로 필수
@@ -149,12 +128,6 @@ import { CreatePost } from "./components/CreatePost";
149128
// ❌ 금지: 코드 설명
150129
// 사용자 정보를 가져오는 함수
151130
function getUserInfo() {}
152-
153-
// ❌ 금지: TODO 주석
154-
// TODO: 나중에 리팩토링
155-
156-
// ❌ 금지: 인라인 설명
157-
const userId = user.id; // 사용자 ID
158131
```
159132

160133
**올바른 예시:**
@@ -173,6 +146,14 @@ function calculateEditDistance() {}
173146

174147
#### 관심사 분리 (Separation of Concerns)
175148

149+
작성되는 코드는 단일 책임 원칙에 따라 관심사 분리가 되어야 한다
150+
151+
- 각 함수/컴포넌트는 하나의 명확한 책임만 가짐
152+
- 기능별로 작은 단위로 분해
153+
- 재사용 가능한 단위로 구성
154+
155+
예시)
156+
176157
- **비즈니스 로직**: 커스텀 훅으로 분리
177158
- **UI 로직**: 순수 컴포넌트로 분리
178159
- **스타일링**: 래퍼 컴포넌트로 격리
@@ -194,15 +175,3 @@ function PureComponent({ data, handlers }) {
194175
// 순수 UI 렌더링만
195176
}
196177
```
197-
198-
#### 단일 책임 원칙
199-
200-
- 각 함수/컴포넌트는 하나의 명확한 책임만 가짐
201-
- 기능별로 작은 단위로 분해
202-
- 재사용 가능한 단위로 구성
203-
204-
### 테스트 코드 가독성
205-
206-
- 테스트 이름: 영어로 행동 중심 작성
207-
- `describe`/`it`에서 무엇을 테스트하는지 명확히 표현
208-
- Given-When-Then 구조 사용

fundamentals/today-i-learned/src/api/hooks/useDiscussions.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import {
2323
type DiscussionsApiParams
2424
} from "@/api/remote/discussions";
2525

26+
// NOTE: 만약 쿼리 옵션으로 분리된다면 각각의 쿼리 옵션에서 인라인하기 (중앙 집권형 쿼리 키 x)
2627
export const DISCUSSIONS_QUERY_KEYS = {
2728
all: ["discussions"] as const,
2829
lists: () => [...DISCUSSIONS_QUERY_KEYS.all, "list"] as const,
@@ -210,7 +211,10 @@ export function useCreateDiscussion() {
210211
});
211212
}
212213

214+
// TODO: queryOptions로 분리 + 사용처에서 useQuery를 드러낼 수 있으면 좋겠다
215+
// NOTE: 다른 remote fetching 훅들도 useQuery + queryOptions로 만들 수 있기를 희망
213216
export function useMyContributions({
217+
// FIXME: 외부에서 주입하는 의존성 어떻게 처리할지 고민해보기
214218
owner = ENV_CONFIG.GITHUB_OWNER,
215219
repo = ENV_CONFIG.GITHUB_REPO,
216220
enabled = true
@@ -230,6 +234,7 @@ export function useMyContributions({
230234
authorLogin: user.login
231235
});
232236
},
237+
// NOTE: (잡초?) enabled 너 꼭 필요해?
233238
enabled: enabled && !!user?.accessToken && !!user?.login,
234239
staleTime: 1000 * 60 * 10, // 10분
235240
gcTime: 1000 * 60 * 30, // 30분

fundamentals/today-i-learned/src/components/features/auth/UnauthenticatedState.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { useAuth } from "@/contexts/AuthContext";
22
import { Button } from "@/components/shared/ui/Button";
33
import { css } from "@styled-system/css";
44

5-
export function UnauthenticatedState() {
5+
export function GoToLogin() {
66
const { login } = useAuth();
77

88
return (

fundamentals/today-i-learned/src/components/features/sprint/SprintGrid.tsx

Lines changed: 0 additions & 38 deletions
This file was deleted.

fundamentals/today-i-learned/src/components/features/sprint/SprintHeader.tsx

Lines changed: 0 additions & 60 deletions
This file was deleted.

fundamentals/today-i-learned/src/components/shared/layout/Layout.tsx renamed to fundamentals/today-i-learned/src/components/shared/layout/RootLayout.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,25 @@
11
import { css } from "@styled-system/css";
2+
import { Outlet, ScrollRestoration } from "react-router-dom";
23
import { LayoutNavigation } from "./LayoutNavigation";
34

4-
export const Layout: React.FC<{ children: React.ReactNode }> = ({
5-
children
6-
}) => {
5+
export const RootLayout = () => {
76
return (
87
<div className={layoutContainer}>
98
<LayoutNavigation />
10-
<main className={mainContent}>{children}</main>
9+
<main className={mainContent}>
10+
<ScrollRestoration
11+
getKey={(location) => {
12+
if (
13+
location.pathname === "/" ||
14+
location.pathname === "/today-i-learned/"
15+
) {
16+
return location.key;
17+
}
18+
return null;
19+
}}
20+
/>
21+
<Outlet />
22+
</main>
1123
</div>
1224
);
1325
};

fundamentals/today-i-learned/src/contexts/AuthContext.tsx

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ interface AuthProviderProps {
2424
children: ReactNode;
2525
}
2626

27+
// FIXME: 리액트 쿼리로 바꿔요 -> persist를 쓸지 고려해보기
28+
// FIXME: 로컬 스토리지 의존성 제거하기 -> 만약 필요할 경우 캐시에 의존하도록 하기
2729
export function AuthProvider({ children }: AuthProviderProps) {
2830
const [user, setUser] = useState<User | null>(null);
2931
const [isLoading, setIsLoading] = useState(true);
@@ -40,11 +42,6 @@ export function AuthProvider({ children }: AuthProviderProps) {
4042
};
4143

4244
useEffect(() => {
43-
if (typeof window === "undefined") {
44-
setIsLoading(false);
45-
return;
46-
}
47-
4845
const savedUser = localStorage.getItem("github_user");
4946
if (savedUser) {
5047
try {

fundamentals/today-i-learned/src/main.tsx

Lines changed: 3 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
import { OverlayProvider } from "overlay-kit";
22
import React from "react";
33
import ReactDOM from "react-dom/client";
4-
import {
5-
createBrowserRouter,
6-
RouterProvider,
7-
Outlet,
8-
ScrollRestoration
9-
} from "react-router-dom";
4+
import { createBrowserRouter, Outlet, RouterProvider } from "react-router-dom";
5+
106
import SearchPage from "./pages/search/SearchPage.tsx";
117
import { ErrorBoundary } from "./components/shared/ErrorBoundary.tsx";
12-
import { Layout } from "./components/shared/layout/Layout";
138
import { AuthProvider } from "./contexts/AuthContext.tsx";
149
import { ThemeProvider } from "./contexts/ThemeContext.tsx";
1510
import "./index.css";
@@ -18,25 +13,7 @@ import { MyPage } from "./pages/profile/MyPage";
1813
import { TimelinePage } from "./pages/timeline/TimelinePage";
1914
import { QueryProvider } from "./providers/QueryProvider.tsx";
2015
import { ToastProvider } from "./contexts/ToastContext";
21-
22-
const RootLayout = () => {
23-
return (
24-
<Layout>
25-
<ScrollRestoration
26-
getKey={(location) => {
27-
if (
28-
location.pathname === "/" ||
29-
location.pathname === "/today-i-learned/"
30-
) {
31-
return location.key;
32-
}
33-
return null;
34-
}}
35-
/>
36-
<Outlet />
37-
</Layout>
38-
);
39-
};
16+
import { RootLayout } from "./components/shared/layout/RootLayout.tsx";
4017

4118
const router = createBrowserRouter(
4219
[

0 commit comments

Comments
 (0)