codestates / codestates/Lumiere
[Dev-Log] 진가람 2021-12-09
- Dominant language
- TypeScript
- Stars
- 7
- Forks
- 4
- PR merge metrics
- No merged PRs in 30d
Description
> ### 오늘은 어떻게 프로젝트에 기여했나요?
- 상품과 작가리스트 및 관리자 페이지에 Pagination 적용
- 같은 API요청에서 권한에 따라 데이터 분기
- 불필요하게 중복되는 코드 리팩토링
>
> ### 오늘의 프로젝트에서 힘든 점은 무엇인가요?
>
- 미루다가 오늘 페이지네이션을 적용했다. countDocuments 메소드를 알게됐다!
페이지네이션을 처음 해봐서 다양하게 찾아봤다.
대부분 skip과 limit를 사용하여 구현하던데 그 방법의 성능 문제에 대한 정보를 찾아냈다.
skip을 사용하지 않고 _id 고유 아이디를 활용한 방법이 더 효율적이라는 걸 보고 적용하려했으나
그 또한 문제가 있었다. _id를 사용한 방법은 점진적인 페이지 이동만 가능하다.
즉 1에서 2페이지는 가능하나 1에서 3으로는 뛰어넘을 수 없다. 따라서 skip을 이용했다!
https://darrengwon.tistory.com/826
https://www.codementor.io/@arpitbhayani/fast-and-efficient-pagination-in-mongodb-9095flbqr
>
```js
// getArtists Handler
const page = Number(req.query.pageNumber) || 1; // 쿼리로 페이지 넘버를 받고
const pageSize = 9; // 한 페이지에 들어갈 데이터의 수 정하기
const count = await Artist.countDocuments({}); // 총 데이터의 수
const artists = await Artist.find({}, { likes: 0 })
.sort({ _id: -1 })
.limit(pageSize) // 제한을 주고
.skip(pageSize * (page - 1)) // 스킵도 준다
.exec();
res.json({ artists, page, pages: Math.ceil(count / pageSize) });
// 해당 페이지의 필요 데이터, 해당 페이지, 총 페이지를 응답으로 줬다
```
>
- 기획때부터 e-Commerce가 볼륨이 큰 만큼 요청도 많고 세세해서 API를 짜는데 긴가민가한게 많았다.
특히 같은 GET(ex. getProducts)요청이지만 권한에 따라 데이터의 깊이가 달라야한다면,
과연 같은 API에서 분기를 나눠하는 것인가 아니면 별개의 API를 만들 것인가 하는 것이었다.
처음에는 포괄적이게 관리자 권한에 필요한 방대한 데이터로 일괄적으로 주고
클라이언트에서 필요 데이터를 뽑아 사용하도록 했으나, 뭔가 계속 찝찝했다.
분명 유출하면 큰일나는 데이터도 아니고 좀 더 상품과 작가의 디테일한 정보일 뿐이지만,
되도록 필요 데이터만 DB에서 뽑아 이쁘게 정리해서 주고 싶었다.
결국 하나의 API에서 필요에 맞게 분기를 나누는 것으로 정했고, 권한 확인에 필요한 함수를 만들었다.
원래는 핸들러 진입 전 커스텀 미들웨어 auth로 권한에 따라 제한한다.
```js
// @desc Fetch all products
// @route GET /api/products/
// @access Public
const getProducts = asyncHandler(async (req, res) => {
const page = Number(req.query.pageNumber) || 1;
let pageSize;
let count;
let products;
const decodedData = isAuthorized(req);
if (decodedData) {
req.user = await User.findById(decodedData.xx).select('-general.password');
if (req.user.isAdmin === true) {
pageSize = 10;
count = await Product.countDocuments({});
products = await Product.find({})
.populate('artist', ['name', 'aka', 'code', 'record'])
.sort({ _id: -1 })
.limit(pageSize)
.skip(pageSize * (page - 1))
.exec();
res.json({ products, page, pages: Math.ceil(count / pageSize) });
return;
} // 관리자 권한일 시 더 세세한 정보
}
pageSize = 28;
count = await Product.countDocuments({ inStock: true });
products = await Product.find(
{ inStock: true },
{
artCode: 0,
'info.details': 0,
'info.createdAt': 0,
theme: 0,
inStock: 0,
}, // 유저에겐 불필요한 정보 제거
)
.populate('artist', ['name'])
.sort({ _id: -1 })
.limit(pageSize)
.skip(pageSize * (page - 1))
.exec();
res.json({ products, page, pages: Math.ceil(count / pageSize) });
});
```
>
> ### 내일은 프로젝트에 기여하기 위해 무엇을 해야 하나요?
>
> - [x] OAuth 정보 찾아보고 구현하기 (카카오, 구글, 네이버)
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.