-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[6주차] SNIFF 미션 제출합니다. #12
base: master
Are you sure you want to change the base?
Changes from all commits
0488330
c54f496
2c21a77
0dee550
f96a004
6605b41
8b78fc6
9917fac
c5e74da
48b009b
86ca97a
a39fb88
5a008dd
f72f0ea
0893eae
2b5dee2
b84ffc7
dd7a7d1
a097775
96eb778
7ec9cfc
f0310d0
42ba27e
b1ef104
35c6f4b
4b06445
bb36436
b8d5fef
b90debb
734f547
70d476a
7e1a32e
f8120d5
962c69b
c2fdba9
1570094
8beee67
d983810
10ddda9
fd29aea
326b44f
9ac9473
bac6d9b
577cb13
0d6f94a
aa77cf2
5da8e26
f20f9d0
d178f61
3d01443
6b7a21d
65c282b
3587f8e
7d2c543
3d9855d
b958cfe
9a75b75
46ef60b
132c601
9cd6134
186191b
2eedd96
51e9c71
b1d0eb5
78aac31
79767dd
2fab28a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
NEXT_PUBLIC_API_KEY="e76f188b77121ac1189879f8d38c1314" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"extends": ["next/core-web-vitals", "prettier"], | ||
"parserOptions": { | ||
"project": "./tsconfig.json" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
## PR 요약 | ||
|
||
> summary | ||
|
||
## 변경된 점 | ||
|
||
> changes |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
name: git push into another repo to deploy to vercel | ||
|
||
on: | ||
push: | ||
branches: [master] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
container: pandoc/latex | ||
steps: | ||
- uses: actions/checkout@v2 | ||
- name: Install mustache (to update the date) | ||
run: apk add ruby && gem install mustache | ||
- name: creates output | ||
run: sh ./build.sh | ||
- name: Pushes to another repository | ||
id: push_directory | ||
uses: cpina/github-action-push-to-another-repository@master | ||
env: | ||
API_TOKEN_GITHUB: ${{ secrets.DAEGYUN_GITHUB_SECRET }} | ||
with: | ||
source-directory: 'output' | ||
destination-github-username: oooppq | ||
destination-repository-name: next-netflix-18th | ||
user-email: ${{ secrets.DAEGYUN_GITHUB_EMAIL }} | ||
commit-message: ${{ github.event.commits[0].message }} | ||
target-branch: master | ||
- name: Test get variable exported by push-to-another-repository | ||
run: echo $DESTINATION_CLONED_DIRECTORY |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
.yarn/install-state.gz | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# # local env files | ||
# .env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"singleQuote": true, | ||
"useTabs": false, | ||
"trailingComma": "all", | ||
"semi": true, | ||
"printWidth": 80, | ||
"tabWidth": 2 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,50 +1,45 @@ | ||
# 5주차 미션: Next-Netflix | ||
## 패키지 매니저 | ||
|
||
## 서론 | ||
> yarn | ||
|
||
안녕하세요, 프론트 운영진 **노수진**입니다 😸 | ||
### 이유 | ||
|
||
이번주부터는 새 프로젝트인 **Netflix 클론코딩**을 진행합니다. 이번 미션은 Next.js를 사용해 보며 SSR을 학습하고 Figma로 주어지는 디자인을 활용해 스타일링 하는 방법을 이해하는 것을 목표로 합니다. | ||
- 딱히 없음. yarn berry나 pnpm 등의 신상 패키지 매니저를 쓰면서까지 빌드 시간을 단축시킬 프로젝트가 아님. | ||
- npm에 비해 cli가 깔끔하고, 안내 log가 친절함. | ||
|
||
또한 이번주부터는 프론트 페어와 함께하는 과제인 만큼 각 팀별로 미리 호흡을 맞춰 보는 좋은 기회가 될 것 같습니다. 모두 화이팅입니다🔥 | ||
### 설치 | ||
|
||
## 미션 | ||
- node 설치(아마 되어있을 듯) | ||
- npm -g install yarn | ||
|
||
### 미션 목표 | ||
### 기본 동작 | ||
|
||
- Next.js 사용법을 공부해봅니다. | ||
- Figma로 주어지는 디자인으로 스타일링 하는 방식에 익숙해집니다. | ||
- Git을 이용한 협업 방식에 익숙해집니다. | ||
- yarn add( = npm install ~ ) | ||
- yarn create( = npx ~ ) | ||
- 프로젝트 cli(yarn dev, build, start, lint 등, = npm run ~ ) | ||
|
||
### 기한 | ||
## 프로젝트 시작 | ||
|
||
- 2023년 11월 10일 (기한 엄수) | ||
- 이 repo를 자신의 repo에 fork | ||
- git clone https://github.com/[your_id]/next-netflix-18th.git | ||
- 프로젝트 디렉토리에서 yarn install | ||
|
||
### 필수 요건 | ||
## branch 전략 | ||
|
||
- [결과화면](https://next-netflix-17th-sepia.vercel.app/)의 랜딩 페이지와 메인 페이지를 구현합니다. | ||
- [Figma](https://www.figma.com/file/UqdXDovIczt1Gl0IjknHQf/Netflix?node-id=0%3A1)의 디자인을 그대로 구현합니다. | ||
- Open api를 사용해서 데이터 패칭을 진행합니다. (ex. [themoviedb API](https://developers.themoviedb.org/3/getting-started/introduction)) | ||
- `yarn`, `yarn berry`, `npm`, `pnpm`등 패키지 매니저를 직접 선택해 Next.js를 세팅해 봅니다. | ||
- 기능을 구현하기 전 team repo에서 최신 버전의 master 상태를 pull한 후 개발 진행 | ||
- 큼지막한 기능 별로 feature/기능이름 과 같은 형태로 branch 생성 후 코드 작성 | ||
- 작성이 완료되면 바로 merge 하는게 아니라 pr 생성(new pull request 버튼 누르면 자동으로 pr template이 적용되어 있음) | ||
- 상대방이 approve 하면 merge 하는 것을 원칙으로 하나 서로 얘기해보고 괜찮다 싶으면 스스로 master에 merge(무튼 merge 하기 전에 상대방에게 확인받기는 해야 함) | ||
|
||
### 선택 사항 | ||
## 배포 | ||
|
||
- SSR(Server Side Rendering)을 적용해서 구현합니다. | ||
- 웹 폰트를 사용합니다. | ||
- 반응형을 고려합니다. | ||
- 팀 repo 그대로 vercel에 배포하려면 요금을 지불해야 함 | ||
- 따라서, 팀 repo를 오대균 github에 fork 하여, 오대균 repo에서 배포 함 | ||
- 수동으로 배포하면 번거로우니 다음과 같은 flow로 배포되도록 설정함 | ||
> 1. team repo master branch에 push 발생 | ||
> 2. 오대균 repo의 master branch에 변경사항 자동으로 적용 | ||
> 3. vercel이 이를 인식하고 자동으로 배포 반영 | ||
|
||
## **Key Question** | ||
## 궁금한 점이 있다면 | ||
|
||
- Server Side Rendering과 Client Side Rendering의 차이 | ||
- SEO란 | ||
- 전반적인 협업 과정 | ||
|
||
## 링크 및 참고자료 | ||
|
||
- [랜딩페이지 영상](https://lottiefiles.com/kr/) | ||
- [Next.js Docs](https://beta.nextjs.org/docs) | ||
- [Next.js 13에서 변한 것들](https://velog.io/@hang_kem_0531/Next.js-13%EC%9D%B4-%EB%82%98%EC%99%80%EB%B2%84%EB%A0%B8%EB%8B%A4) | ||
- [Next.js 14에서 변한 것들](https://velog.io/@lee_1124/Next.js-14-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8) | ||
- [Git 협업 가이드](https://velog.io/@jinuku/Git-%ED%98%91%EC%97%85-%EA%B0%80%EC%9D%B4%EB%93%9C) | ||
- [디자이너와 개발자가 협업하기 위한 피그마 기본 기능](https://chingguhl.tistory.com/entry/%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%EA%BC%AD-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%A0-%ED%94%BC%EA%B7%B8%EB%A7%88-10%EA%B0%80%EC%A7%80-%EA%B8%B0%EB%8A%A5-%EB%94%94%EC%9E%90%EC%9D%B4%EB%84%88%EC%99%80-%EA%B0%9C%EB%B0%9C%EC%9E%90%EA%B0%80-%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-%EC%9C%84%ED%95%9C-%ED%94%BC%EA%B7%B8%EB%A7%88-%EA%B8%B0%EB%B3%B8-%EA%B8%B0%EB%8A%A5) | ||
- [React에서 무한 스크롤 구현하기](https://tech.kakaoenterprise.com/149) | ||
- 아무 때나 말하세요 |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,51 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import React from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import ContentsSlider from '@/components/browse/ContentsSlider'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import HomeNavBar from '@/components/browse/HomeNavBar'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import HomeTop from '@/components/browse/HomeTop'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { TContent } from '@/types'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
import { getMovies } from '@/utils/Api'; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface BrowseProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
searchParams: { [key: string]: string | undefined }; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저는 useSearchParams를 사용했는데 직접 구현하신 거 좋은 것 같습니다 |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const Browse = async ({ searchParams }: BrowseProps) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const Top = await getMovies('top_rated'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const Popular = await getMovies('popular'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const Upcoming = await getMovies('upcoming'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const Nowplaying = await getMovies('now_playing'); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
const defaultData = { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rank: 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
category: 'Top Rate', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
posterPath: Top[0].poster_path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<div className="bg-black w-full min-h-full pb-12 relative"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<HomeNavBar /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<HomeTop | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
posterPath={searchParams.posterPath || defaultData.posterPath} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
rank={ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
searchParams.rank | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
? Number(searchParams.rank) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
: searchParams.posterPath | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
? null | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
: defaultData.rank | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
category={searchParams.category || defaultData.category} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ContentsSlider | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
title="Preview" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
isRanking={false} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
isPreview={true} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
contents={Nowplaying} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
/> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ContentsSlider title="Nigeria Today" isRanking={true} contents={Top} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ContentsSlider title="Popular" isRanking={false} contents={Popular} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
<ContentsSlider title="Upcoming" isRanking={false} contents={Upcoming} /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Comment on lines
+38
to
+46
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정보를 리스트 선언 후 map 함수로 렌더링 한다면 가독성과 추후 슬라이더 추가시에도 편리할 것 같다는 개인적인 의견 드립니다 ㅎㅎ
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 배워갑니다~! |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
</div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
export default Browse; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
@import url('https://fonts.cdnfonts.com/css/sf-pro-display'); | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
|
||
html { | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
||
body { | ||
font-family: 'SF Pro Display', sans-serif; | ||
background-color: black; | ||
width: 100%; | ||
height: 100%; | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import type { Metadata } from 'next'; | ||
import './globals.css'; | ||
import NavBar from '@/components/common/NavBar'; | ||
|
||
export const metadata: Metadata = { | ||
title: 'sniff-netflix', | ||
description: 'netflix clone project', | ||
viewport: | ||
'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0', | ||
}; | ||
|
||
export default function RootLayout({ | ||
children, | ||
}: { | ||
children: React.ReactNode; | ||
}) { | ||
return ( | ||
<html lang="en"> | ||
<body> | ||
{children} | ||
<NavBar /> | ||
</body> | ||
</html> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import React from 'react'; | ||
import DetailTop from '@/components/detail/DetailTop'; | ||
import DetailOverview from '@/components/detail/DetailOverview'; | ||
import { getMovieDetails } from '@/utils/Api'; | ||
import { TContent } from '@/types'; | ||
|
||
interface DetailPageProps { | ||
params: { id: string }; | ||
} | ||
const Page = async ({ params }: DetailPageProps) => { | ||
const movie: TContent = await getMovieDetails(params.id); | ||
|
||
return ( | ||
<div className="min-h-screen bg-black"> | ||
<DetailTop posterPath={movie.poster_path} /> | ||
<DetailOverview title={movie.title} overview={movie.overview} /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default Page; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import dynamic from 'next/dynamic'; | ||
|
||
const page = () => { | ||
const Logo = dynamic(() => import('@/components/LandingLogo'), { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저도 다음에는 dynamic을 이용해서 구현해봐야겠어요~! |
||
ssr: false, | ||
}); | ||
|
||
return ( | ||
<div className="w-full h-full bg-black flex align-middle"> | ||
<Logo /> | ||
</div> | ||
); | ||
}; | ||
|
||
export default page; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
/* eslint-disable react-hooks/exhaustive-deps */ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이 페이지는 최상단에 use client 를 선언하셨는데 시간이 없어 리팩토링을 하지 못한것인지 특별한 이유가 있는지 개인적으로 궁금하네요 ㅎㅎ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 페이지 내에서 리엑트 훅을 사용하려면 csr로 페이지를 구성해야 하는 것 같드라구요! |
||
'use client'; | ||
|
||
import SearchBar from '@/components/search/SearchBar'; | ||
import SearchResultList from '@/components/search/SearchResultList'; | ||
import { useDebounce } from '@/hooks/useDebounce'; | ||
import { TContent } from '@/types'; | ||
import { getMovies, getSearchedMovies } from '@/utils/Api'; | ||
import { useEffect, useState } from 'react'; | ||
import { useInView } from 'react-intersection-observer'; | ||
|
||
const SearchPage = () => { | ||
const [movies, setMovies] = useState<TContent[]>([]); | ||
const [keyword, setKeyword] = useState<string>(''); | ||
const [init, setInit] = useState<boolean>(true); | ||
const [ref, inview] = useInView(); | ||
const [pageNum, setPageNum] = useState<number>(1); | ||
const [totalPageNum, setTotalPageNum] = useState<number>(1); | ||
|
||
useEffect(() => { | ||
if (!keyword) { | ||
(async () => { | ||
// next의 fetch는 같은 요청에 대해 caching을 진행하므로, | ||
// 첫 요청 이후에는 caching된 데이터를 가져올 것(?) | ||
const defaultMovies = await getMovies('popular'); | ||
setMovies(defaultMovies); | ||
setPageNum(1); | ||
setTotalPageNum(1); | ||
setInit(false); | ||
})(); | ||
} | ||
}, [keyword]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 지금 보니까 vercel 뭐 가격 정책때문에 이미지 요청이 막히는 것 같네요ㅋㅋㅋ.. 뭐 무슨 limit이 있다고 했는데 오늘 딱 그 limit에 도달했나봐요 함 해결해볼게요ㅜㅜ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. next 이미지 optimization 설정을 꺼주니까 해결되었네요! |
||
|
||
useEffect(() => { | ||
if (pageNum > 1) { | ||
(async () => { | ||
const data = await getSearchedMovies(keyword, pageNum); | ||
setMovies([...movies, ...data.results]); | ||
})(); | ||
} | ||
}, [pageNum]); | ||
|
||
useEffect(() => { | ||
if (inview && pageNum < totalPageNum) { | ||
setPageNum(pageNum + 1); | ||
} | ||
}, [inview]); | ||
Comment on lines
+19
to
+47
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 필요한 부분을 세부 클라이언트 컴포넌트에 선언한다면 최상단에 'use client'를 없앨수도 있겠네요 ㅎㅎ 저희도 시간 때문에 서치페이지 'use client'로 선언해버렸는데 이제 리팩토링 해봐야됩니다 ㅋㅋㅋㅋㅋㅋ There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 약간 귀찮아서 걍 페이지 자체를 csr로 구성했는데 ssr로 구성하고 내부에 csr 컴포넌트를 넣는 것이 성능적으로 뛰어나다면 앞으로 그렇게 해봐야겠네요ㅎㅎ |
||
|
||
const handleOnChangeQuery = async ( | ||
e: React.ChangeEvent<HTMLInputElement>, | ||
) => { | ||
const query = e.target.value.trim(); | ||
if (query) { | ||
const data = await getSearchedMovies(query); | ||
setMovies(data.results); | ||
setPageNum(data.page); | ||
setTotalPageNum(data.total_pages); | ||
} | ||
setKeyword(query); | ||
if (!query) setInit(true); | ||
}; | ||
Comment on lines
+49
to
+61
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. handleChangeQuery를 통해 검색어 변화가 있을때 이렇게 처리를 할수도 있겠네요..! 저희는 불러온 리스트에서 필터링을 했었는데, 이런 방법도 있군요! |
||
|
||
return ( | ||
<div> | ||
<SearchBar | ||
keyword={keyword} | ||
setKeyword={setKeyword} | ||
setInit={setInit} | ||
handleOnChangeQuery={useDebounce(handleOnChangeQuery, 500)} | ||
/> | ||
Comment on lines
+68
to
+70
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. debounce 를 통해 과도한 데이터 fetching 방지하신 디테일 좋네요 ㅎㅎ |
||
<h2 className="text-white text-[27px] ml-2.5 mt-5 mb-4 font-bold"> | ||
{keyword.length === 0 ? 'Polular' : 'Top Searches'} | ||
</h2> | ||
{movies.length || init ? ( | ||
<SearchResultList movies={movies} /> | ||
) : ( | ||
<div className="text-white text-center mt-20 px-3 break-words">{`There are no movies that matched "${keyword}". | ||
`}</div> | ||
)} | ||
<div className="" ref={ref}></div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SearchPage; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저희는 vercel 을 사용한적이 없어 아직 팀 레포 그대로 배포하도 공짜로 사용 가능하여 그냥 했는데, github action 을 이용하여 이를 해결하신점 매우 멋지네요!!!^^