diff --git a/01-styled-components/README.md b/01-styled-components/README.md deleted file mode 100644 index 3776be6..0000000 --- a/01-styled-components/README.md +++ /dev/null @@ -1,91 +0,0 @@ -# 01. styled-components를 적용해서 리팩토링하기 - -## 🎯 요구사항 - -- 초록스터디-`self-paced-react`의 step5 코드를 가져와 스타일링하는 미션입니다. -- styled-components 라이브러리를 이용해서 컴포넌트들에게 css를 입히고 스타일링 해보세요. -- styled-components를 왜 사용하는지, 별도의 css파일로 분리한 방법과 어떤 trade-off가 있는지 PR에 적어주세요. - - (선택) 브라우저가 웹 페이지를 렌더링하는 구조와 과정에 대해서도 공부해보세요. - - **🔑keywords** : DOM Tree, CSSOM Tree, Render Tree -- 프로젝트내 별도의 css파일은 존재하지 않아야합니다.❌ - - App.css는 허용되며 아래의 코드와 동일해야합니다. - -```css -* { - padding: 0; - margin: 0; - box-sizing: border-box; -} - -ul, -li { - list-style: none; -} - -html, -body { - font-family: sans-serif; - font-size: 16px; -} - -/* Colors *****************************************/ -:root { - --primary-color: #ec4a0a; - --lighten-color: #f6a88a; - --grey-100: #ffffff; - --grey-200: #d0d5dd; - --grey-300: #667085; - --grey-400: #344054; - --grey-500: #000000; -} -``` - -### 😗구현 예시 - -- 컴포넌트의 이름이나 구조는 마음대로 변경해도 좋습니다. - -```javascript -import React from "react"; -import styled from "styled-components"; - -// Button 컴포넌트를 styled-components로 정의 -const Button = styled.button` - background-color: #ec4a0a; - color: white; - border: none; - border-radius: 8px; - padding: 10px 20px; - font-size: 16px; - cursor: pointer; - - &:hover { - background-color: #f6a88a; - } -`; - -const App = () => { - return ( -
-

Hello, styled-components!

- -
- ); -}; - -export default App; -``` - -## ✅ 키워드 - -- **styled-component** - - Css in JS - - Scoped Styling - -## 🧙‍♀️ 진행 가이드 - -- 진행시간 : 1시간 내에 완료하는 것을 목표로 합니다. -- vscode 사용시 extension에서 `vscode-styled-components`를 설치해주세요. - -## 🔗 참고 문서 - -- [styled-components 공식문서](https://styled-components.com/docs) diff --git a/02-state-management-tools/2.1-ContextAPI/README.md b/02-state-management-tools/2.1-ContextAPI/README.md new file mode 100644 index 0000000..019c2c9 --- /dev/null +++ b/02-state-management-tools/2.1-ContextAPI/README.md @@ -0,0 +1,61 @@ +# 02-1. 전역상태관리 - Context API + +## 🎯 요구사항 + +- Context API를 사용해서 애플리케이션 내의 **props drilling** 문제를 해결하세요. + - props로 **똑같은** 데이터 혹은 함수를 전달하지 않도록 해야합니다. + - props를 쓴다면 그 이유를 PR에 적어주세요. +- PR에 Context API를 **왜** 사용하는지, 기존의 코드구조와 어떤 **trade-off**가 있는지 적어주세요. +- Context API와 데이터를 사용하는 Component 사이의 **관계를 도식화**하고 이미지를 PR에 첨부해주세요. + - 실제 코드와 상관없이 일반적인 관계를 나타내야합니다. + - 도식화 방식은 자유롭게 하셔도 좋습니다. + - (추천) **Figma** + +### 😗구현 예시 + +- 컴포넌트의 이름이나 구조는 마음대로 변경해도 좋습니다. +- 아래의 코드는 Context를 설정하는 예시입니다. + +```javascript +import { createContext, useState } from "react"; + +// Context 생성 +const UserContext = createContext({ + user: { name: "", email: "" }, + setUser: () => {}, +}); + +// Provider 컴포넌트 +export const UserProvider = ({ children }) => { + const [user, setUser] = useState({ + name: "John Doe", + email: "johndoe@example.com", + }); + + return ( + + {children} + + ); +}; + +export default UserContext; +``` + +## ✅ 키워드 + +- props drilling +- 전역상태관리 + - Context + - Provider + - Consumer +- Hook : useContext + +## 🧙‍♀️ 진행 가이드 + +- 진행시간 : 2시간 내에 완료하는 것을 목표로 합니다. + +## 🔗 참고 문서 + +- [Context API 공식문서](https://ko.legacy.reactjs.org/docs/context.html) +- [리액트를 다루는 기술(저:김민준(velopert))](https://thebook.io/080203/0501/) diff --git a/02-state-management-tools/2.1-ContextAPI/assets/context-diagram.svg b/02-state-management-tools/2.1-ContextAPI/assets/context-diagram.svg new file mode 100644 index 0000000..c217c52 --- /dev/null +++ b/02-state-management-tools/2.1-ContextAPI/assets/context-diagram.svg @@ -0,0 +1,78 @@ + + + + + + + Context API — Provider와 Consumer의 관계 + + + + createContext() + 통로(Context 객체) 생성 + + + + + + + Context.Provider + value={{ data, handler }} → 하위 컴포넌트 전체에 공급 + + + + Component A + + useContext(Context) + → data 사용 + + + + Component B + props 전달 없음 + (Context 미사용) + + + + Component C + props 없음 + (중간 컴포넌트) + + + + + + + + + + Component D + + useContext(Context) + → handler 사용 + + + + Component E + + useContext(Context) + → data 사용 + + + + + Context를 직접 소비하는 컴포넌트 (useContext 사용) + + 중간 컴포넌트 (props 전달 불필요) + + + + + + + + + + + + diff --git a/02-state-management-tools/2.2-Zustand/README.md b/02-state-management-tools/2.2-Zustand/README.md new file mode 100644 index 0000000..04b09fc --- /dev/null +++ b/02-state-management-tools/2.2-Zustand/README.md @@ -0,0 +1,46 @@ +# 02-2. 전역상태관리 - Zustand + +## 🎯 요구사항 + +- Context API로 구성한 애플리케이션을 Zustand 기반 전역 상태로 마이그레이션하세요. +- props에 대한 요구사항은 2-1 요구사항과 같습니다. +- Zustand를 **왜** 사용하는지, Context API와 비교했을때 어떤 점이 달랐는지, 또 trade-off가 있는지 적어주세요. + - 기술적인 것도 좋고 개발자의 경험 측면에서도 좋습니다. +- (선택): 카테고리 필터의 선택된 카테고리가 새로고침 후에도 유지되도록 구현해보세요 + +### 😗구현 예시 + +- 컴포넌트의 이름이나 구조를 정한 이유가 명확해야하며 타인에게 설명할 수 있어야합니다. +- 아래 코드는 Zustand 스토어를 설정하는 예시입니다. + +```javascript +import { create } from "zustand"; + +// Zustand 스토어 예시 +export const useBear = create((set) => ({ + // state + bears: 0, + + // actions + increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), + removeAllBears: () => set({ bears: 0 }), + updateBears: (newBears) => set({ bears: newBears }), +})); +``` + +## ✅ 키워드 + +- props drilling +- 전역상태관리 + - Zustand + - create + - set / get + +## 🧙‍♀️ 진행 가이드 + +- 진행시간 : 2시간 내에 완료하는 것을 목표로 합니다. + +## 🔗 참고 문서 + +- [Zustand 공식문서](https://recoiljs.org/docs/introduction/installation/) +- [Zustand와 React Context](https://tkdodo.eu/blog/zustand-and-react-context) diff --git a/02-state-management-tools/2.3-TanStack Query/README.md b/02-state-management-tools/2.3-TanStack Query/README.md new file mode 100644 index 0000000..6f5d88e --- /dev/null +++ b/02-state-management-tools/2.3-TanStack Query/README.md @@ -0,0 +1,53 @@ +# 02-3. 서버상태관리 - TanStack Query + +💡해당 미션은 **여러 사용자가 하나의 서버를 공유하고, 식당 목록이 주기적으로 업데이트되는 환경**을 가정하여 진행합니다. + +## 🎯 요구사항 + +- TanStack Query를 사용해 서버 상태를 클라이언트 상태와 분리하고, 효율적인 데이터 캐싱과 요청 관리를 구현해 보세요. + - 쿼리 및 뮤테이션 설정은 명확한 이유가 있다면 자유롭게 변경해도 좋습니다. +- TanStack Query를 **왜** 사용하는지, 서버 상태와 클라이언트 상태를 분리하였을때 어떤 점이 달랐는지, 또 trade-off가 있는지 적어주세요. + - 기술적인 것도 좋고 개발자의 경험 측면에서도 좋습니다. +- TanStack Query Devtools를 이용하여 Query의 변화와 Mutation의 발생을 확인해보세요. +- (선택) 뮤테이션 로직에 낙관적 업데이트(Optimistic Update)를 적용해 보고 어떤 상황에서 낙관적 업데이트가 효과적인지, 그리고 주의해야 할 점은 무엇인지 적어주세요. + - Browser Throttling 기능을 활용하여 네트워크 속도를 느리게 설정한 뒤 낙관적 업데이트가 실제로 어떻게 동작하는지 확인해 보세요. + +### 😗구현 예시 + +- 컴포넌트의 이름이나 구조를 정한 이유가 명확해야하며 타인에게 설명할 수 있어야합니다. +- 아래는 main.jsx의 설정 모습입니다. + +```javascript +import { createRoot } from "react-dom/client"; +import App from "./App.jsx"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; + +const queryClient = new QueryClient(); + +createRoot(document.getElementById("root")).render( + + + , +); +``` + +## ✅ 키워드 + +- props drilling +- 서버 상태관리 + - TanStack Query + - QueryClient + - Query Key + - useQuery + - useMutation + - Optimistic Update + +## 🧙‍♀️ 진행 가이드 + +- 진행시간 : 4시간 내에 완료하는 것을 목표로 합니다. + +## 🔗 참고 문서 + +- [TanStack Query](https://tanstack.com/query/latest/docs/framework/react/overview) +- [TanStack Query 메인테이너 Tk Dodo 님의 블로그](https://tkdodo.eu/blog/tags/react-query) +- [테코톡(시모의 Tanstack Query)](https://www.youtube.com/watch?v=RfK15tw8H-I) diff --git a/README.md b/README.md index 4c47c42..347d5c8 100644 --- a/README.md +++ b/README.md @@ -1,180 +1,155 @@ -# styled-components를 적용해서 리팩토링하기 +# 전역상태관리 - Context API ## 🎯 개인 목표 및 목표 달성을 위한 행동 가이드 이번 미션을 통해 다음과 같은 학습 경험들을 쌓는 것을 목표로 한다. -- styled-components의 기본 문법과 사용법을 익히고, CSS-in-JS 방식이 기존 별도 CSS 파일 방식과 어떤 차이가 있는지 직접 체감한다. -- 단순히 동작하는 코드를 넘어, 컴포넌트마다 스코프가 격리된 스타일을 작성하는 습관을 형성한다. -- styled-components를 처음 접하더라도 공식 문서를 스스로 찾아 읽고 적용하는 자기주도 학습 역량을 키운다. -- CSS 파일 방식 vs CSS-in-JS 방식의 trade-off를 정리해 PR에 나만의 언어로 서술한다. +- 현재 코드에서 props drilling이 어디서 발생하는지 직접 찾아보고, Context API가 이를 어떻게 해소하는지 체감한다. +- `createContext`, `Provider`, `useContext`의 역할과 데이터 흐름을 이해하고, 세 요소가 어떻게 연결되는지 스스로 설명할 수 있는 수준으로 익힌다. +- Context API를 쓰는 것이 적절한 상황과 그렇지 않은 상황(trade-off)을 이해하고, 그 판단 근거를 PR에 직접 서술한다. +- 컴포넌트와 Context 간의 관계를 도식화해보며 데이터 흐름을 시각적으로 이해하는 경험을 쌓는다. ## 📝 기능 구현 목록 -- `styled-components` 패키지 설치 -- 모든 컴포넌트의 CSS Module 파일을 제거하고 styled-components로 전환 - - `Header`, `CategoryFilter`, `RestaurantList` - - `Modal`, `AddRestaurantModal`, `RestaurantDetailModal` -- `props`를 활용한 조건부 스타일링 적용 (`$required`, `$primary`) -- `App.css`에서 Typography 유틸리티 클래스 제거 (각 컴포넌트 스타일로 이동) +- `RestaurantContext` 생성 — `newRestaurants`, `registerRestaurant`, `isLoading`, `error` 관리 +- `RestaurantProvider`를 `main.jsx`에서 감싸는 구조로 구현 +- `useRestaurantContext` 커스텀 훅 분리 (null guard 포함) +- Context와 props 역할 분리 + - `RestaurantList` — Context에서 서버 데이터, props로 `selectedCategory`, `onRestaurantClick` + - `AddRestaurantModal` — Context에서 `registerRestaurant`, props로 `onClose` + - `CategoryFilter` — props로 `category`, `onCategoryChange` +- `App.jsx` — UI 상태(`selectedCategory`, `clickedRestaurant`, `isAddModalOpen`) 로컬 관리 ## 📚 학습 내용 -### 1. styled-components 기본 문법 +### 1. props drilling -- `styled.태그명` 뒤에 백틱으로 CSS를 작성하면 해당 태그에 스타일이 적용된 React 컴포넌트가 만들어진다. -- 백틱 안에서 자식 요소 선택자(`label { }`, `input { }`)를 중첩해서 쓸 수 있다. styled-components가 런타임에 고유 클래스명(예: `.sc-abc123`)을 생성하고, 중첩 선택자를 `.sc-abc123 input { }` 형태로 변환하기 때문이다. -- `&`는 생성된 클래스명 자신을 가리키는 선택자로, `&:hover`, `&:last-child` 같은 의사 클래스에 사용한다. +props drilling은 데이터가 필요하지 않은 중간 컴포넌트들이 아래로 전달하기 위해 props를 받아야 하는 상황이다. 컴포넌트 트리가 깊어질수록 불필요한 의존이 쌓여 유지보수가 어려워진다. -### 2. Scoped Styling 원리 +### 2. Context API의 세 요소 -- 런타임에 컴포넌트마다 고유 클래스명을 생성해 `