Skip to content

Commit

Permalink
๐Ÿ“ [#3] Online Store Renewal Retrospective ์•„ํ‹ฐํด์„ ์ถ”๊ฐ€ํ•œ๋‹ค
Browse files Browse the repository at this point in the history
  • Loading branch information
hyoungqu23 committed Feb 3, 2024
1 parent ef2f47a commit 4ef7e39
Showing 1 changed file with 149 additions and 0 deletions.
149 changes: 149 additions & 0 deletions contents/articles/online-store-renewal-retrospective.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
---
title: ์˜จ๋ผ์ธ ์Šคํ† ์–ด ์‹ ๊ทœ ํŽ˜์ด์ง€ ๋ฆฌ๋‰ด์–ผ ํ”„๋กœ์ ํŠธ ํšŒ๊ณ 
description: ๋กœ์ปฌ์•ค๋ผ์ดํ”„์˜ ์˜จ๋ผ์ธ ์Šคํ† ์–ด๋ฅผ ๋ฆฌ๋‰ด์–ผ ๊ธฐ์—… ๊ณผ์ œ
createdAt: 2022-09-05
category: React
tags:
- React
- TypeScript
- Team Project
- Retrospective
- Wanted PreOnBoarding Frontend Course
---

## ์‹œ์ž‘

https://github.com/wanted-pre-onboarding-fe-6th-team2/pre-onboarding-assignment-week-1-2-team-2

[ํ”„๋ฃจ๋–ผ-์˜ค๋Š˜๋„ํ”„๋ฃปํ•ด!](https://fruitte-renewal.netlify.app/)

์ด๋ฒˆ ๊ณผ์ œ๋Š” ๊ธฐ์กด ์šด์˜ ์„œ๋น„์Šค์ธ ์˜จ๋ผ์ธ ์Šคํ† ์–ด์˜ ์‹ ๊ทœ ํŽ˜์ด์ง€๋ฅผ ์ œ์ž‘ํ•˜๋Š” ๊ณผ์ œ์ด๋‹ค. API๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋”๋ฏธ ๋ฐ์ดํ„ฐ๋กœ ์ž‘์—…์„ ์ง„ํ–‰ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์ ์ด ์กฐ๊ธˆ ์•„์‰ฌ์› ๋‹ค. API ํ˜ธ์ถœ์„ ํ•˜๋ฉด ์ตœ์ ํ™”๋ผ๋˜์ง€ ๊ด€์‹ฌ์‚ฌ์˜ ๋ถ„๋ฆฌ๋ฅผ ์œ„ํ•œ ์ฝ”๋“œ ๋ถ„๋ฆฌ๋ผ๋˜์ง€ ํ•™์Šตํ•˜๋ฉด์„œ ์ฝ”๋“œ๋ฅผ ์–ด๋–ป๊ฒŒ ํ•˜๋ฉด ๋” ๊น”๋”ํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ง€ ๊ณ ๋ฏผํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

[ํ”„๋ฃป์Šคํ† ์–ด](https://www.fruitte.co.kr/fruitstore)

์•„๋ฌดํŠผ ์—†๋Š” ๊ฑด ์ด๋ฏธ ์—†๋Š” ๊ฒƒ์ด๋‹ˆ๊นŒ ์ง„ํ–‰ํ•˜๊ธฐ๋กœ ํ•˜๊ณ  ํŒ€์›๋“ค๊ณผ ๋‹ด๋‹น ์ž‘์—…์„ ๋‚˜๋ˆˆ ํ›„์— ์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€๋ฅผ ๋‹ด๋‹นํ•˜๊ฒŒ ๋๋‹ค.

## ์š”๊ตฌ์‚ฌํ•ญ ๋ถ„์„

์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€๋Š” ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๋ฅผ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.

- ์ƒํ’ˆ ๋ชฉ๋ก์˜ UI
- 10๊ฐœ ๋‹จ์œ„์˜ ํŽ˜์ด์ง€๋„ค์ด์…˜

์ƒํ’ˆ ๋ชฉ๋ก UI์˜ ๊ฒฝ์šฐ์—๋Š” ๊ฒฐ๊ตญ `map`์„ ํ™œ์šฉํ•ด ์ƒํ’ˆ ๋ชฉ๋ก ์•„์ดํ…œ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ Œ๋”๋งํ•ด์ฃผ๋ฉด ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋‹ค๋ฅธ ์ด์Šˆ๋‚˜ ๋ฌธ์ œ๋  ์ƒํ™ฉ์€ ์—†์„ ๊ฒƒ์ด๋ผ๊ณ  ์˜ˆ์ƒํ–ˆ๋‹ค. ๋‹ค๋งŒ, 10๊ฐœ ๋‹จ์œ„์˜ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ธฐ๋Šฅ์˜ ๊ฒฝ์šฐ API ํ˜ธ์ถœ์— `page`, `limit`๋ฅผ ๋„˜๊ฒจ์ฃผ๋Š” ๋ฐฉ์‹์€ ๊ตฌํ˜„ํ•ด๋ดค์ง€๋งŒ, API ํ˜ธ์ถœ ์—†์ด ๊ตฌํ˜„ํ•ด์•ผํ•˜๊ธฐ์— ์–ด๋–ค ๋ฐฉ์‹์œผ๋กœ ์ง„ํ–‰ํ•ด์•ผ ํ•˜๋Š”์ง€ ๊ณ ๋ฏผ์ด ์žˆ์—ˆ๋‹ค.

## API ์—†๋Š” ํŽ˜์ด์ง€๋„ค์ด์…˜ ๊ตฌํ˜„ํ•˜๊ธฐ

ํŽ˜์ด์ง€๋„ค์ด์…˜์˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ์ž์ฒด๋ฅผ ์•Œ๊ณ  ์žˆ์œผ๋ฉด ์ดํ›„์— ์–ด๋””์„œ๋“  ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์„ ๊ฑฐ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค. ํŽ˜์ด์ง€๋„ค์ด์…˜์˜ ๋กœ์ง์—์„œ `page`์™€ `limit`๋ฅผ ํ™œ์šฉํ•ด ์ƒํ’ˆ ๋ฐฐ์—ด์—์„œ ์ผ๋ถ€๋ฅผ ์ž˜๋ผ๋‚ด๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, `page`๊ฐ€ `2`์ด๊ณ  `limit`๊ฐ€ `10`์ด๋ผ๋ฉด, 11๋ฒˆ์งธ ์ƒํ’ˆ๋ถ€ํ„ฐ 20๋ฒˆ์งธ ์ƒํ’ˆ๊นŒ์ง€๋ฅผ ์ž˜๋ผ์„œ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์ด๋‹ค.

๊ฒฐ๊ตญ, API์— ๋„˜๊ฒจ์ฃผ๋Š” `page`, `limit`๋ฅผ `state`๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ๊ตฌํ˜„ํ•˜๋ฉด ๋  ๊ฒƒ ๊ฐ™๋‹ค๋Š” ์ƒ๊ฐ์„ ํ–ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ํ•˜๋‚˜์˜ ์ปดํฌ๋„ŒํŠธ๋กœ ๊ตฌํ˜„ํ•˜๊ณ , ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ๋ฅผ ์ƒํ’ˆ ๋ชฉ๋ก ์ปดํฌ๋„ŒํŠธ ์ƒ์œ„์— ๋‘๋ฉด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ–ˆ๋‹ค.

```jsx
// common/Pagination/Pagination.jsx

import React, { useState, Children, isValidElement, cloneElement } from 'react';
import PaginationButton from '@/components/common/Pagination/PaginationButton';
import * as Styled from '@/components/common/Pagination/Pagination.styled';

const Pagination = ({ data, children }) => {
// 1 page๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •
const [currentPage, setCurrentPage] = useState(1);

// 10๊ฐœ๋ฅผ limit๋กœ ํ•จ
const itemsPerPage = 10;

// ์ฆ‰, page์™€ limit๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ธ๋ฑ์‹ฑ ์ฒ˜๋ฆฌํ•˜๊ธฐ
const indexOfLast = currentPage * itemsPerPage;
const indexOfFirst = indexOfLast - itemsPerPage;

// ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์— ๋งž๊ฒŒ ๋ฐฐ์—ด ์ž๋ฅด๊ธฐ
const currentItems = items => {
let currentItems = 0;
currentItems = items.slice(indexOfFirst, indexOfLast);
return currentItems;
};

return ();
};

export default Pagination;
```

๊ฒฐ๊ตญ ์›ํ•˜๋Š” ๋Œ€๋กœ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์ฒ˜๋Ÿผ ์ƒํ’ˆ ๋ชฉ๋ก์˜ ๋ฐฐ์—ด์„ ๋‚˜๋ˆ„๋Š”๋ฐ์—๋Š” ์„ฑ๊ณตํ–ˆ์ง€๋งŒ, Props๋Š” ์ฝ๊ธฐ ์ „์šฉ์ด๊ธฐ์— ์ˆ˜์ •ํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ children ์ปดํฌ๋„ŒํŠธ์— ์ถ”๊ฐ€์ ์ธ Props๋กœ ์ „๋‹ฌํ•  ์ˆ˜๊ฐ€ ์—†์—ˆ๋‹ค. [React ๊ณต์‹ ๋ฌธ์„œ](https://ko.reactjs.org/docs/react-api.html#cloneelement)๋ฅผ ๋ณด๋ฉด children ์ปดํฌ๋„ŒํŠธ๋ฅผ `[React.cloneElement](https://ko.reactjs.org/docs/react-api.html#cloneelement)`๋กœ ๋ณต์ œํ•˜์—ฌ Props๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์ด๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์–ด ์žˆ์–ด, ์ด๋ฅผ ํ™œ์šฉํ•ด JSX๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ์ถ”ํ›„ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ์˜ ํŽ˜์ด์ง€๋„ค์ด์…˜์„ ์‰ฝ๊ฒŒ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ–ˆ๋‹ค.

```jsx
// common/Pagination/Pagination.jsx

import React, { useState, Children, isValidElement, cloneElement } from 'react';
import PaginationButton from '@/components/common/Pagination/PaginationButton';
import * as Styled from '@/components/common/Pagination/Pagination.styled';

const Pagination = ({ data, children }) => {
// 1 page๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •
const [currentPage, setCurrentPage] = useState(1);

// 10๊ฐœ๋ฅผ limit๋กœ ํ•จ
const itemsPerPage = 10;

// ์ฆ‰, page์™€ limit๋ฅผ ์กฐํ•ฉํ•˜์—ฌ ์ธ๋ฑ์‹ฑ ์ฒ˜๋ฆฌํ•˜๊ธฐ
const indexOfLast = currentPage * itemsPerPage;
const indexOfFirst = indexOfLast - itemsPerPage;

// ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์— ๋งž๊ฒŒ ๋ฐฐ์—ด ์ž๋ฅด๊ธฐ
const currentItems = (items) => {
let currentItems = 0;
currentItems = items.slice(indexOfFirst, indexOfLast);
return currentItems;
};

return (
<Styled.PaginationSection>
**
{cloneElement(children, {
data: currentItems(data),
page: currentPage,
totalItemNumber: data.length,
})}
**
<PaginationButton
itemsPerPage={itemsPerPage}
totalItemNumber={data.length}
page={currentPage}
paginate={setCurrentPage}
/>
</Styled.PaginationSection>
);
};

export default Pagination;
```

๋ฌผ๋ก , `limit`๋ฅผ Props๋กœ ์ฒ˜๋ฆฌํ•˜์—ฌ ๊ธฐ์ค€ ๊ฐœ์ˆ˜๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ์กฐ๊ธˆ ๋” ์žฌ์‚ฌ์šฉ์„ฑ์— ๋„์›€์ด ๋  ๊ฒƒ ๊ฐ™๋‹ค.

```jsx
const Pagination = ({ data, limit, children }) => {
// 1 page๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์„ค์ •
const [currentPage, setCurrentPage] = useState(1);

// limit๋ฅผ props๋กœ ๋ฐ›์•„์˜ด
const itemsPerPage = limit;

// ...
```
## ๊ธฐ์กด ์Šคํ† ์–ด ๊ฐœ์„ ์ 
- ๊ธฐ์กด ์›น์‚ฌ์ดํŠธ์˜ ๊ฒฝ์šฐ, ๋ชจ๋“  ์ƒํ’ˆ ๋ชฉ๋ก์— ๋ Œ๋”๋ง๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ถ”ํ›„ ์Šคํ† ์–ด์— ๋” ๋งŽ์€ ์ƒํ’ˆ์ด ์ž…์ ๋  ๊ฒฝ์šฐ์— ์ „์ฒด ๋ Œ๋”๋ง ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ์„ ๊ณ ๋ คํ•˜์—ฌ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์„ ์ถ”๊ฐ€ํ•ด ์‚ฌ์šฉ์ž์˜ ๋Œ€๊ธฐ ์‹œ๊ฐ„๊ณผ ์„œ๋ฒ„์˜ ๋กœ๋“œ ์‹œ๊ฐ„์„ ์ค„์˜€๋‹ค.
- ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜์—ฌ ๋‹ค๋ฅธ ํŽ˜์ด์ง€์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ™•์žฅ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ์ž‘์—…ํ–ˆ๋‹ค.
- ์ƒํ’ˆ ์ œ๋ชฉ ๋“ฑ UI๊ฐ€ ๊นจ์ง€๋Š” ๋ถ€๋ถ„์„ ๊ฐœ์„ ํ•˜๊ณ , ์ž‘์€ ์ด๋ฏธ์ง€ ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ์ถ”๊ฐ€ํ•ด UI๋ฅผ ์กฐ๊ธˆ ๋” ๋ถ€๋“œ๋Ÿฝ๊ฒŒ ๋งŒ๋“ค์—ˆ๋‹ค.
- UX๋ฅผ ๋†’์ด๊ธฐ ์œ„ํ•ด ์ƒํ’ˆ ๋ชฉ๋ก ํŽ˜์ด์ง€์—์„œ ์ข‹์•„์š” ๋ฒ„ํŠผ์„ ์ถ”๊ฐ€ํ–ˆ๋‹ค.
## ๋งˆ๋ฌด๋ฆฌ
๊ธฐ๋ณธ์— ํ•ด๋‹นํ•˜๋Š” ๋ชฉ๋ก ํŽ˜์ด์ง€๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด์„œ ํŽ˜์ด์ง€๋„ค์ด์…˜ ๋กœ์ง์„ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๋‹ˆ ์กฐ๊ธˆ ๋” ๊นŠ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ์ข‹์€ ๊ณผ์ œ์˜€๋‹ค. UI/UX๋ฅผ ๊ณ ๋ คํ•˜๋ฉด์„œ Emotion์œผ๋กœ ์ž‘์—…์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ ์–ด๋–ค ๋ถ€๋ถ„์ด ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ์ž์—๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์น  ์ง€ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ, ์•„์ง ์ด๋Ÿฌํ•œ ๋ถ€๋ถ„์—์„œ๋Š” ๋ถ€์กฑํ•œ ๊ฒƒ ๊ฐ™์•„์„œ ์ถ”ํ›„์— UX ๊ด€๋ จํ•ด์„œ ํ•™์Šตํ•˜๋Š” ๊ฒƒ๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™๋‹ค.
๋! ๐Ÿ™‹๐Ÿปโ€โ™‚๏ธ
## ์ฐธ๊ณ  ์ž๋ฃŒ
- **[React cloneElement()](https://ko.reactjs.org/docs/react-api.html#cloneelement)**

0 comments on commit 4ef7e39

Please sign in to comment.