Skip to content

Commit

Permalink
doc: 단계별 요구 사항 및 참고 자료, 키워드 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
woowapark committed Apr 2, 2024
0 parents commit d92efec
Show file tree
Hide file tree
Showing 21 changed files with 4,714 additions and 0 deletions.
19 changes: 19 additions & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
"eslint:recommended",
"plugin:react/recommended",
"plugin:react/jsx-runtime",
"plugin:react-hooks/recommended",
],
ignorePatterns: ["dist", ".eslintrc.cjs"],
parserOptions: { ecmaVersion: "latest", sourceType: "module" },
settings: { react: { version: "18.2" } },
plugins: ["react-refresh"],
rules: {
"react/jsx-no-target-blank": "off",
"react/prop-types": "off",
"react-refresh/only-export-components": ["warn", { allowConstantExport: true }],
},
};
24 changes: 24 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
80 changes: 80 additions & 0 deletions 01-introduction/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# 01 Introduction

React는 UI를 렌더링 하기 위한 JavaScript 라이브러리입니다.
> React is a JavaScript library for rendering user interfaces (UI).
> https://react.dev/learn/describing-the-ui

## ✨ React의 원칙과 목표

React를 사용해 앱을 구현하는 데에는 JavaScript/TypeScript로 앱을 직접 구현하는 것보다는 조금 더 정해진 가이드라인이 있습니다.
`설계자의 의도`가 그것이죠. React는 새로운 언어나 표준이 아니며, React팀이 그들의 설계 의도에 기반해 만든 하나의 라이브러리입니다.
사용하는 데에 여전히 정답이 정해져 있지 않은 영역들이 많이 있지만, `권장하지 않는 것`에 대한 가이드는 비교적 명확하게 찾아볼 수 있습니다. 그 가이드는 보통 공식 문서에서 찾을 수 있고요. 이때의 `권장하지 않는 것`들은 그 자체가 잘못되었기 때문이 아니라, `React를 만든 사람들의 의도에서 벗어나기 때문에` 잘못된 것으로 취급됩니다. 즉, 보기에 아주 읽기 좋고 깔끔한 코드라 하더라도 React 팀에서 의도한 설계와 벗어난다면 개발자가 의도하지 않은 동작이 일어날 수도 있고 알 수 없는 버그와 마주할 수도 있다는 뜻입니다.

즉, 'React를 잘하기 위한 학습'이란 `React에서 의도한 바를 잘 이해하고 그 설계 원칙에 잘 따르는` 코드를 작성하는 법에 대한 학습과 연습이라 할 수 있습니다.
물론 이 학습의 가장 근본적인 목적은 React를 이해하는 것이 아니라 사용자에게 더 가치있는 서비스를 제공하기 위함이어야 할 것이고요.

### 원칙
- 1 UI를 컴포넌트 단위로 나누어 구현한다. 각 컴포넌트는 독립적(isolated)이며, 순수함(purity)을 유지해야 한다.
- 2 Single Source of Truth로부터 나온 데이터의 일관성을 유지해야 한다.
- 3 단방향의 데이터 흐름(one-way/unidirectional data flow)을 유지해야 한다.
- 4 선언적 UI

### 목표
위의 원칙을 바탕으로 결국은 여러 측면에서 더 '유지보수하기 좋은'-이미 구현한 걸 파악하고 수정하기 쉬우면서, 확장하기도 쉬운- 코드를 작성하는 것을 목표로 한다.
- 1 재사용하기 쉬운 (reusable)
- 2 조합하기 쉬운 (composable)
- 3 예측하기 쉬운 (predictable / easy to debug)

코드를 지향한다.


> 라이브러리를 학습할 때 해당 라이브러리의 설계 원칙과 목표를 먼저 생각해보는 방식은 React를 학습할 때 뿐만 아니라, 이후에 다양한 상태관리 라이브러리를 학습할 때에도 비슷하게 적용할 수 있습니다.
> 각각의 라이브러리는 해결하고자 하는 문제가 있으며, 그 문제를 잘 해결하기 위한 과정에서 나름의 설계 원칙을 세우고 원칙에 따라 일관되게 코드를 작성하려 합니다.
> 영문으로 검색하는 경우 `mental model`, `design principle`, `paradigm` 등을 붙여서 찾아보면 해당 라이브러리에서 지향하는 바에 대한 설명을 찾아볼 수 있습니다. 보통 라이브러리의 공식 문서, 라이브러리 컨트리뷰터들이 작성한 아티클 혹은 컨퍼런스 발표 등에서 찾아볼 수 있어요. 이 자료에서 확인할 수 있는 원칙들이 말 그대로 '저자의 의도'이니 가장 정확한 가이드라인이라 할 수 있습니다.
## 🦅 공식 문서 Overview
[React 공식 문서](https://react.dev/)에서 필요한 대부분의 학습 자료를 모두 찾을 수 있습니다. 설계 원칙부터 사용법, 연습 문제를 직접 풀어볼 수 있는 IDE까지 내장되어 있으니 가능하면 공식 문서를 활용해 학습해보는 연습을 추천합니다.

공식 문서는 크게 아래와 같은 구성으로 이루어져 있습니다.
- Learn
- Reference
- API Reference
- Reference
- Usage
- Troubleshooting
- Rules of React

Self-Paced React에서 연습용 앱의 각 단계별 요구 사항을 구현할 때 참고할 만한 공식 문서 링크를 몇 개씩 함께 달아두었습니다.


## 권장하는 학습 단계
이 자료는 JavaScript/TypeScript로 간단한 애플리케이션을 구현해보았지만 React는 아직 학습해본 적 없는 크루를 대상으로 합니다.
- 1 Self-Paced React: React를 사용해 '일단 돌아가게 하는 법'을 연습해본다.
- 2 우아한테크코스 레벨2 미션&피드백: React를 '잘' 활용하는 법, 'React다운' 코드를 쓰는 방법을 좀 더 복잡한 UI를 완성도 높게 구현해보면서 연습한다. 그게 '왜' 잘 쓰는 법인지를 공식 문서 기준으로 학습한다.
- 3 optional: 잘 활용하는 것을 넘어서서 더 깊은 동작 원리를 학습한다.

## 시작 전 워밍 업
[Quick Start](https://react.dev/learn) 페이지의 내용을 차근차근 따라해 보세요. 아주 간단한 React 사용법을 전반적으로 알아볼 수 있습니다.

대략적인 React 코드의 생김새에 익숙해졌나요?
[Thinking in React](https://react.dev/learn/thinking-in-react)를 읽으며 UI를 React로 구현하는 과정을 살펴보세요. Self-Paced React 에서 구현해볼 작은 앱도 이 [Thinking in React](https://react.dev/learn/thinking-in-react) 문서에서 가이드하는 흐름을 참고해 단계별 요구 사항을 제시할 예정입니다.

[Thinking in React](https://react.dev/learn/thinking-in-react) 문서까지 살펴봤다면, 다음 단계로 넘어가 주세요. (이 문서의 모든 것을 이해해야 한다는 뜻은 아닙니다! 가볍게 훑어보고 넘어가세요. 지금 모든 걸 이해하지 않아도 괜찮습니다.)

## 참고: React(core)와 React Renderer의 관계
`main.jsx`파일을 한번 열어보세요. 아래와 같은 import 문이 있는 것을 확인하실 수 있습니다.
```javascript
import React from "react";
import ReactDOM from "react-dom/client";
```
거칠게 나눠보자면 React로 애플리케이션을 구현할 때에는 React(core)와 React Renderer를 함께 사용하게 됩니다. `ReactDOM`이 React renderer의 한 종류로 웹 브라우저 환경에서 React코드를 실행하기 위해 사용합니다.

![react and react renderers](../images/01-react-react-renderers.jpg)

실제로 React Native를 처음 소개할 때에는 [`Learn once, write everywhere`](https://blog.outsider.ne.kr/1124) 라는 슬로건을 내세우기도 했습니다. (정말로 이 슬로건을 잘 실현했는지는 일단 논외로 두겠습니다)

흔히 접할 수 있는 ReactDOM이나 React Native 외에도, [awesome react renderer](https://github.com/chentsulin/awesome-react-renderer)를 보시면 작성한 React 코드를 다양한 환경에서 실행시킬 수 있는 React Renderer들을 확인할 수 있고, 심지어는 직접 Renderer를 구현할 수도 있습니다.

이 자료에서는 React Renderer, React Core와 React Renderer의 연결 구조와 관련한 더 깊은 이해를 위한 설명은 제외합니다.
앞으로의 자료에서는 이러한 전체적인 구조와 깊은 동작 원리보다는 우선 React 자체를 사용해 코드를 작성하는 것에 대한 부분을 다룹니다.
36 changes: 36 additions & 0 deletions 02-first-component/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# 🎯 요구 사항
- `/templates` 에 있는 html 템플릿을 그대로 `App.jsx`에서 그릴 수 있게 해보세요.
- `App.jsx`를 여러 개의 컴포넌트로 분리해서 그려보세요.
- 스타일도 별도의 css파일로 분리하여 각 컴포넌트에서 import합니다.
- (선택) `module.css` 를 사용해 보세요.

## 구현 결과 예시
- 예를 들어, `App.jsx`의 return문을 아래와 같이 작성했을 때에 앱이 정상적으로 그려지도록 구현해 주세요.
- 컴포넌트의 이름이나 구조는 마음대로 변경해도 좋습니다
```javascript
return (
<>
<GNB />
<main>
<CategoryFilter />
<RestaurantList />
<Modal/>
</main>
</>
)
```

# 🔗 참고 문서
- [Thinking in React](https://react.dev/learn/thinking-in-react)의 Step1-2 에 있는 것처럼 나만의 컴포넌트 단위를 나누어 보세요.
- [Your First Component](https://react.dev/learn/your-first-component)

# ✅ 키워드
- JSX
- `class` -> `className`
- `for` -> `htmlFor`
- self closing tag
- Fragment
- `{}` 내에 쓸 수 있는 JS 식
- React Component
- 기본 구조
- export / import
26 changes: 26 additions & 0 deletions 03-rendering-lists/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

# 🎯 요구 사항
- `RestaurantList` 가 restaurants 배열을 받아서 그릴 수 있도록 변경해 보세요.
- restaurants 배열을 `RestaurantList` 의 props로 내려받도록 변경해 보세요.
- 카테고리 필터에 따라 필터된 음식점 목록을 보여줄 수 있도록 변경해 보세요.

## 구현 결과 예시
```javascript
// App.jsx
<RestaurantList restaurants={restaurants}/>
```

# 🔗 참고 문서
- [Thinking in React](https://react.dev/learn/thinking-in-react)의 Step3-4
- [Passing Props to a Component](https://react.dev/learn/passing-props-to-a-component)
- [Rendering Lists](https://react.dev/learn/rendering-lists)
- [State: A Component's Memory](https://react.dev/learn/state-a-components-memory)
- [API Reference: useState](https://react.dev/reference/react/useState)

# ✅ 키워드
- Props
- State
- useState
- Keys

> [Rendering Lists](https://react.dev/learn/rendering-lists) 문서에 ['Why does React need keys?'](https://react.dev/learn/rendering-lists#why-does-react-need-keys)는 지금 꼭 이해하지 않아도 괜찮습니다. 그냥 React에서 목록을 동적으로 그릴 때에는 이런 것들을 사용해야 하는구나~ 정도로만 알고 일단 넘어가세요. 우선 사용하는 법에 익숙해지는 것이 먼저입니다 :)
19 changes: 19 additions & 0 deletions 04-modal/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

# 🎯 요구 사항
- `RestaurantList` 의 아이템을 클릭하면, 클릭한 아이템의 정보를 보여주는 모달이 뜨도록 변경해 주세요. '확인' 버튼을 클릭하거나 모달 뒤의 backdrop을 클릭하면 모달이 닫혀야 합니다.
- (작은 단계로 구현해보기 1) 아이템을 클릭하면 정해진 텍스트를 그대로 보여주는 모달을 열고 닫습니다.
- (작은 단계로 구현해보기 2) 클릭한 아이템의 정보를 모달에 내려줄 수 있도록 개선합니다.

## 구현 결과 예시
```javascript
// App.jsx
{isModalOpen && <RestaurantInfoModal {/** 적절한 props */}/>}
```

# 🔗 참고 문서
- [Thinking in React](https://react.dev/learn/thinking-in-react)의 Step5
- [Responding to Events](https://react.dev/learn/responding-to-events)

# ✅ 키워드
- event handler (feat. side effect)
- conditional rendering
35 changes: 35 additions & 0 deletions 05-form/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

# 🎯 요구 사항
- GNB의 레스토랑 추가 버튼을 클릭하면 레스토랑 추가 폼이 모달로 뜨도록 구현해 주세요
- (작은 단계로 구현해보기 1) 이전 단계에서 만든 레스토랑 상세 정보 모달을 쓰지 않고 레스토랑 추가용 모달을 따로 만들어서 띄웁니다.
- (작은 단계로 구현해보기 2) 이전 단계에서 만든 모달을 재사용하여 구현합니다.
- `<input/>`, `<textarea/>`에 값을 입력하고 '확인' 버튼을 클릭하면 레스토랑 목록에 추가되도록 구현해 주세요.
- 유효성 검사는 하지 않습니다. 아주 간단하게 입력값을 처리해보는 구현만 해도 충분합니다.

# 🔗 참고 문서
- [Sharing State Between Components](https://react.dev/learn/sharing-state-between-components)

# ✅ 키워드
- lifting state up
- controlled vs uncontrolled
- children props

> 재사용할 수 있는 모달을 만들 때 `children`을 활용해 보세요. 아래와 같은 식으로 UI를 구성할 수 있습니다.
```javascript
// 레스토랑 추가 모달
<Modal>
// 설명을 위한 예시용 마크업입니다. 실제로 사용하는 마크업은 template/ 하위의 html을 참고하거나 직접 원하는대로 구현하여 사용해 주세요.
<label></label>
<input />
<label></label>
<textarea />
</Modal>

// 레스토랑 정보 모달
<Modal>
// 설명을 위한 예시용 마크업입니다. 실제로 사용하는 마크업은 template/ 하위의 html을 참고하거나 직접 원하는대로 구현하여 사용해 주세요.
<h2></h2>
<p></p>
</Modal>
```
41 changes: 41 additions & 0 deletions 06-effects/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# 🎯 요구 사항
- API로 레스토랑 목록을 불러와 `<RestaurantList />`에 내려줍니다.
- 레스토랑 추가 모달에서 확인 버튼을 클릭하면 POST 요청을 보냅니다.
- 모달이 닫히고, 레스토랑 목록을 다시 불러옵니다.

# 🔗 참고 문서
- [Synchronizing with Effects](https://react.dev/learn/synchronizing-with-effects)
> Effects let you specify side effects that are caused by rendering itself, rather than by a particular event.
- [API Reference: useEffect](https://react.dev/reference/react/useEffect)
> useEffect is a React Hook that lets you synchronize a component with an external system.
구현을 다 해본 뒤에 Introduction에서 살펴보았던 설계 원칙과 관련해 조금 더 학습해보고 싶다면 아래 문서들도 추가로 확인해 보세요.
- [You Might Not Need an Effect](https://react.dev/learn/you-might-not-need-an-effect)
> You do need Effects to synchronize with external systems.
> In React, data flows from the parent components to their children.
- [Components and Hooks must be pure](https://react.dev/reference/rules/components-and-hooks-must-be-pure)
> Purity in Components and Hooks is a key rule of React that makes your app predictable, easy to debug, and allows React to automatically optimize your code.
> Side effects should not run in render, as React can render components multiple times to create the best possible user experience.
> One important principle in React is local reasoning: the ability to understand what a component or hook does by looking at its code in isolation. Hooks should be treated like “black boxes” when they are called.
# ✅ 키워드
- effect (feat. side effect)
- useEffect

# 🧙‍♀️ `json-server`로 가짜 서버 띄워 활용하기
연습용 앱이기 때문에 [`json-server`](https://github.com/typicode/json-server)를 활용해 간단한 가짜 REST API를 구축해 사용합니다.
- `npm run server`를 실행합니다. (혹은 `npx json-server db.json` 를 직접 실행해도 상관없습니다)
- `GET http://localhost:3000/restaurants`으로 `db.json`에 있는 레스토랑 목록을 불러올 수 있습니다.
```javascript
// GET 예시
const response = await fetch("http://localhost:3000/restaurants");

// POST 예시
const response = await fetch("http://localhost:3000/restaurants", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(restaurant),
});
```
18 changes: 18 additions & 0 deletions 07-references/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# 07 References
- [React 공식 문서](https://react.dev/)
- [overreacted](https://overreacted.io/)
- https://www.joshwcomeau.com/react/common-beginner-mistakes/

## TypeScript
- TotalTypeScript [React with TypeScript](https://www.totaltypescript.com/tutorials/react-with-typescript)

## Testing
- Storybook
- RTL(React Testing Library)

## Pattern
- [patterns.dev](https://www.patterns.dev/#patterns) > React Patterns
- 컴포넌트 구현 패턴 & 렌더링 패턴

## (optional) Deep Dive
- [React Internals Deep Dive](https://jser.dev/series/react-source-code-walkthrough/)
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Self Paced React

## 🎯 이 학습 자료의 목표 경험
React를 사용해 자주 사용되는 UI들을 아주 기초적인 수준으로 구현해봅니다.
이 과정에서 React의 설계 원칙을 고려하며 개발하는 연습의 첫 단계를 경험해봅니다.
- JavaScript 기반의 React 프로젝트를 직접 실행할 수 있다.
- React에서 컴포넌트를 선언하고 사용할 수 있다.
- 아래와 같은 UI를 가장 기초적인 수준에서 구현할 수 있다. (유효성 검사, 그 외 UX 대응 등 모두 X)
- 목록 UI
- 모달 UI
- 폼 UI

### ❌ 다루지 않는 것
- TypeScript
- RSC(React Server Component)
- 테스트 도구
- Storybook
- RTL(React Testing Library)
- 라우팅, 상태 관리 등을 위한 서드파티 라이브러리
- React의 깊이있는 동작 원리
- React 컴포넌트 구현 패턴
- Context API
- Ref
- useState/useEffect 이외의 hook, custom hook

### ✅ 다루는 것
- 'React의 설계 원칙에 맞는' 코드를 작성하기 위한 학습에서 참고할 만한 자료
- JSX
- useState
- useEffect

## 🦮 목차
### 1 Introduction
### 2 컴포넌트 선언하고 사용하기: Component 기본 구조와 JSX
### 3 목록 UI 구현하기: Props와 State
### 4 모달 UI 구현하기: side-effect(feat. event handler)
### 5 폼 UI 구현하기: controlled vs uncontrolled
### 6 API 연동하기: side-effect(feat. effects)
### 7 References
34 changes: 34 additions & 0 deletions db.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"restaurants": [
{
"id": "a01",
"name": "피양콩할마니",
"description": "평양 출신의 할머니가 수십 년간 운영해온 비지 전문점 피양콩 할마니. 두부를 빼지 않은 되비지를 맛볼 수 있는 곳으로, ‘피양’은 평안도 사투리로 ‘평양’을 의미한다. 딸과 함께 운영하는 이곳에선 맷돌로 직접 간 콩만을 사용하며, 일체의 조미료를 넣지 않은 건강식을 선보인다. 콩비지와 피양 만두가 이곳의 대표 메뉴지만, 할머니가 옛날 방식을 고수하며 만들어내는 비지전골 또한 이 집의 역사를 느낄 수 있는 특별한 메뉴다. 반찬은 손님들이 먹고 싶은 만큼 덜어 먹을 수 있게 준비돼 있다.",
"category": "한식"
},
{
"id": "a02",
"name": "잇쇼우",
"description": "잇쇼우는 정통 자가제면 사누끼 우동이 대표메뉴입니다. 기술은 정성을 이길 수 없다는 신념으로 모든 음식에 최선을 다하는 잇쇼우는 고객 한분 한분께 최선을 다하겠습니다",
"category": "일식"
},
{
"id": "a03",
"name": "이태리키친",
"description": "늘 변화를 추구하는 이태리키친입니다.",
"category": "양식"
},
{
"id": "a04",
"name": "호아빈 삼성점",
"description": "푸짐한 양에 국물이 일품인 쌀국수",
"category": "아시안"
},
{
"id": "a05",
"name": "도스타코스 선릉점",
"description": "멕시칸 캐주얼 그릴",
"category": "기타"
}
]
}
Binary file added images/01-react-react-renderers.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<!doctype html>
<html lang="ko">

<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Self-Paced React</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>

</html>
Loading

0 comments on commit d92efec

Please sign in to comment.