Skip to content
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주차] gotcha팀 미션 제출합니다 #14

Open
wants to merge 71 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
13d5e27
[feat]nextjs 프로젝트 생성
silverain02 Nov 8, 2023
841d111
[chore] 파일경로이동
silverain02 Nov 8, 2023
f7dd432
[chore]폴더 구조 수정
silverain02 Nov 9, 2023
107d08e
Merge pull request #1 from team-gotcha/feature/1_setting
silverain02 Nov 9, 2023
f3ff54d
[chore] 라우팅수정
silverain02 Nov 9, 2023
d8ab520
Merge pull request #2 from team-gotcha/feature/1_setting
silverain02 Nov 9, 2023
dc56d11
feat : lottie 띄우기
Nov 9, 2023
7f93a87
feat : 애니메이션 이후 main 이동
Nov 9, 2023
4726352
style : globalstyle 설정
Nov 9, 2023
565fe63
[feat] axios 인스턴스화, data fetching test
silverain02 Nov 9, 2023
53de400
style : Header, NavBar style
Nov 9, 2023
f2d34aa
[feat] img 데이터 fetching
silverain02 Nov 9, 2023
54af881
[chore]폴더정리
silverain02 Nov 9, 2023
727764c
Merge pull request #3 from team-gotcha/feature/3_mainpage
mod-siw Nov 9, 2023
7362a46
Merge branch 'master' into feature/1_setting
silverain02 Nov 9, 2023
13a33f7
Merge pull request #4 from team-gotcha/feature/1_setting
silverain02 Nov 9, 2023
318f8d9
style : MainControlBox style
Nov 9, 2023
81e9cdc
Merge branch 'master' into feature/3_mainpage
mod-siw Nov 9, 2023
fc16c08
Merge pull request #5 from team-gotcha/feature/3_mainpage
mod-siw Nov 9, 2023
839ea3a
[chore] 브랜치충돌 해결
silverain02 Nov 9, 2023
5e9e156
Merge branch 'master' into feature/4_movieList
silverain02 Nov 9, 2023
185a48f
Merge pull request #6 from team-gotcha/feature/4_movieList
silverain02 Nov 9, 2023
4ffd269
style : MainImage style
Nov 9, 2023
313ca85
Merge pull request #7 from team-gotcha/feature/3_mainpage
mod-siw Nov 9, 2023
07e4b9a
[feat] movie이미지리스트
silverain02 Nov 9, 2023
ef4fb35
[feat] data추가
silverain02 Nov 9, 2023
a76c3ac
[feat]main random img bar
silverain02 Nov 10, 2023
b2f8cd9
Merge pull request #8 from team-gotcha/feature/4_movieList
silverain02 Nov 10, 2023
10b702f
[feat]화면 반응형으로 조정
silverain02 Nov 10, 2023
7da6aeb
Merge pull request #9 from team-gotcha/feature/4_movieList
silverain02 Nov 10, 2023
ced3a4c
[chore] preview크기조정
silverain02 Nov 10, 2023
738139f
Merge pull request #10 from team-gotcha/feature/4_movieList
silverain02 Nov 10, 2023
ecbad8b
style : 이미지 크기 오류 해결 및 재설정
Nov 10, 2023
f6dcd49
Update README.md
silverain02 Nov 10, 2023
28ac8cf
style : 세부 디테일 수정
Nov 10, 2023
e4f877f
??? : use client를 없애보려는 발악 - 실패함
Nov 10, 2023
8ece9e1
??? : 실패하고서 원상 복귀 해놓기 + 약간의 반응형 수정
Nov 10, 2023
583ef41
Merge pull request #11 from team-gotcha/feature/5_scroll
mod-siw Nov 10, 2023
c355e3c
type : type 설정 수정
Nov 10, 2023
25f9579
Merge pull request #12 from team-gotcha/feature/5_scroll
mod-siw Nov 10, 2023
a45a8b3
[chore] API key 숨김 처리
silverain02 Nov 14, 2023
c5ae4d8
[chore] api 통합
silverain02 Nov 14, 2023
5bb17cd
style : 메인페이지 styled -> tailwind 변경
Nov 14, 2023
fcf1a5a
style : Header, Navbar styled -> tailwind 변경 ( 항목 하나 X)
Nov 14, 2023
5f7a250
style : MainContent styled -> tailwind 변경
Nov 14, 2023
7ae6111
[feat] api SSR방식으로 변경
silverain02 Nov 15, 2023
0306120
Merge pull request #13 from team-gotcha/feature/7_apiConnectRe
silverain02 Nov 15, 2023
1737dbc
Merge branch 'master' into feature/6_styleChange
mod-siw Nov 15, 2023
669f712
Feature/6 style change
mod-siw Nov 15, 2023
cbeca62
[feat] 이미지 url 오류 수정
silverain02 Nov 15, 2023
4921b42
[feat] 상세페이지 라우팅 처리
silverain02 Nov 15, 2023
2fd517b
[feat] api 통신
silverain02 Nov 15, 2023
18b555c
[feat] API연동 CSR방식으로 변경
silverain02 Nov 15, 2023
c2407d9
[feat] API연동, 스켈레톤 구성
silverain02 Nov 15, 2023
43fc3e9
[chore] Image수정
silverain02 Nov 16, 2023
0e1b447
[feat]상세페이지 마크업
silverain02 Nov 16, 2023
a741f08
[fix] mainImage안뜨는 오류 수정
silverain02 Nov 16, 2023
a4c2150
Merge pull request #15 from team-gotcha/feature/8_detail
silverain02 Nov 16, 2023
39d7503
[feat] 검색 기능 구현
Nov 17, 2023
3df89f1
[feat] 검색 기능 구현
mod-siw Nov 17, 2023
5f89f22
Update Header.tsx
mod-siw Nov 17, 2023
3f4c744
Update NavBar.tsx
mod-siw Nov 17, 2023
826b836
Update page.tsx
mod-siw Nov 17, 2023
a79e43d
[style] 메인 이미지 디테일 수정
Nov 17, 2023
5c1d349
[feat] NavBar pathname 따라 움직이는 로직 추가
Nov 17, 2023
8d3cf17
[refactor] deploy 위한 시도
Nov 17, 2023
69a9e71
[fix] deploy 위한 오류 수정
mod-siw Nov 17, 2023
73e1269
[fix]deploy 위한 수정 2
mod-siw Nov 17, 2023
05ea54d
Merge pull request #18 from team-gotcha/feature/11_detailCheck
mod-siw Nov 17, 2023
d70af5d
[fix] deploy 위한 수정 3
mod-siw Nov 17, 2023
1256228
[chore]주석제거
silverain02 Nov 18, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": "next/core-web-vitals"
}
35 changes: 35 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# 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
.env
# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,19 @@
- [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)

# PR멘트

## Key Question

### SSR과 CSR의 차이
SSR은 서버 쪽에서 렌더링 준비를 마친 상태에서 클라이언트에게 전달하는 방식이고, 반대로 CSR은 서버에서 요청을 받아 클라이언트로 파일을 보내면 클라이언트 측에서 렌더링을 시작하는 방식이다.
웹페이지 로딩 시간에 있어서 성능차이가 있는데, SSR이 상대적으로 첫 페이지를 로딩하는 시간이 빠르고 나머지 페이지를 로딩하는 시간이 더 느리다 (첫페이지 로딩 과정을 반복하기 때문)
이전 과제까지 사용한 React에서는 라우팅을 통해 CSR을 사용했고, 이번 NextJS에서는 app 폴더 내 url pathname에 맞춘 폴더를 만들어 SSR을 사용했는데 확실히 클라이언트 쪽에서 라우팅 처리를 하지 않아도 되니 작업하는데는 편했지만 페이지 전환 시 로딩 시간이 길어지는 느낌이 있었다.

### SEO
SEO(Search Engine Optimization)는 Search Engine, 구글과 같은 검색엔진에 친화적인 사이트를 만들어 검색 결과의 트래픽 양과 질을 극대화하는 작업이다. 검색엔진은 크롤링을 통해 웹사이트를 읽는데 동적으로 컨텐츠가 생성되는 CSR에 비해 SSR은 애초에 서버사이드에서 컴파일되어 클라이언트로 넘어와서 크롤러 대응에 용이하다

### 협업과정
파트 분리와 gitflow에 기반해 협업하고자 했다. 팀 레포에서 Header,NavBar,Landing, ControlBar / MovieList, api, Slide 로 나누어 각 기능별 브랜치를 파서 구현 후 PR을 올려 merge했다
특정 기능이 완료되어야 이후 작업을 할 수 있는게 있어서 초기세팅과 api연동, 마크업은 분리해서 계획을 짜는 게 좋을 것 같다~!
13 changes: 13 additions & 0 deletions api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import axios from "axios";

const BASE_URL = "https://api.themoviedb.org/3/";

const api = axios.create({
baseURL: BASE_URL,
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ` + process.env.NEXT_PUBLIC_AUTH,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.env 파일 숨기신 점 잘하신 거 같아요:)

Comment on lines +4 to +9
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

axios 인스턴스 설정 좋네요 ㅎㅎ

},
});

export default api;
20 changes: 20 additions & 0 deletions api/movieApi.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import api from "./index";

// export async function getMovies(url: string) {
// const res = await fetch(`https://api.themoviedb.org/3/${url}`);
// return res.json();
// }

export const getMovies = (url: string) => {
return api.get(url).then((res: any) => res.data);
};

export const getImageUrl = (path = "", size = 400) => {
return `https://image.tmdb.org/t/p/w${size}${path}`;
};

export const getSearchResults = (searchQuery: string) => {
return api
.get(`https://api.themoviedb.org/3/search/movie?query=${searchQuery}`)
.then((res: any) => res.data);
};
46 changes: 46 additions & 0 deletions app/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';
import React, { useState, useEffect } from 'react';
import Image from 'next/image';

const Header = () => {
const MENU_LIST = ['TV Shows', 'Movies', 'My List'];
const [scrollPosition, setScrollPosition] = useState(0);

const handleScroll = () => {
setScrollPosition(window.scrollY);
};

useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);

return (
<div
className={`fixed top-0 flex justify-between items-center w-full max-w-[450px] h-[57px] px-4 md:px-5 lg:px-6 py-8 pr-8 z-50 transition-all duration-300 ease ${

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tailwind로 바꾸신 점 좋은 것 같습니다:)

scrollPosition > 100

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Header안에서 scrollPosition에 따라 배경을 다르게 하신 디테일 너무 좋아요~~

? 'bg-black'
: 'bg-gradient-to-b from-[rgba(18, 18, 18, 0.9)] to-[rgba(18, 18, 18, 0)]'
}`}
>
<div>
<Image
src={'/images/netflix-logo.svg'}
width={57}
height={57}
alt="logo"
/>
Comment on lines +29 to +34
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

next/image 를 통해 최적화 하신 점 좋네요 ㅎㅎ

</div>
{MENU_LIST.map((menu) => {
return (
<span key={menu} className="text-white text-17.2 cursor-pointer">
{menu}
</span>
);
})}
</div>
);
};
export default Header;
20 changes: 20 additions & 0 deletions app/components/LandingLogo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
"use client";

import { useRouter } from "next/navigation";
import Lottie from "react-lottie-player";
import netflix from "@/public/netflix_landing.json";

const LandingLogo = () => {
const router = useRouter();
return (
<Lottie
animationData={netflix}
style={{ width: "100%" }}
play
loop={false}
onComplete={() => router.push("/main")}
/>
);
};

export default LandingLogo;
37 changes: 37 additions & 0 deletions app/components/MainControlBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import React from "react";
import Image from "next/image";

const MainControlBox = () => {
return (
<div className="flex flex-col items-center gap-11 pt-2.5 px-11 pb-11 w-full">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Taillwind css 를 잘 적용하시는 거 같아요!!

Comment on lines +4 to +6
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 tailwind 로 마이그레이션 성공하셨네요 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ 축하드립니다

<div className="flex items-center justify-center">
<Image src={"/images/topten.svg"} width={15} height={15} alt="topten" />
<div className="text-white text-13px font-bold line-height-2rem text-center ml-5">
in Nigeria Today
</div>
</div>
<div className="w-full flex flex-row justify-around">
<div className="flex flex-col items-center justify-center gap-1 text-white cursor-pointer">
<Image src={"/images/plus.svg"} width={24} height={24} alt="plus" />
<span>My List</span>
</div>

<button className="flex items-center justify-center bg-neutral-300 rounded-md w-28 h-11 gap-2.5 cursor-pointer border-none">
<Image
src={"/images/play_icon.svg"}
width={24}
height={24}
alt="play_icon"
/>
<span className="font-semibold text-xl">Play</span>
</button>

<div className="flex flex-col items-center justify-center gap-1 text-white cursor-pointer">
<Image src={"/images/info.svg"} width={24} height={24} alt="info" />
<span>Info</span>
</div>
</div>
</div>
);
};
export default MainControlBox;
65 changes: 65 additions & 0 deletions app/components/MainImage.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"use client";
import Image from "next/image";
import { useEffect, useState } from "react";
import { getImageUrl } from "@/api/movieApi";

interface MainImageProps {
data: {
results?: {
id: number;
poster_path: string;
}[];
};
}

const MainImage = ({ data }: MainImageProps) => {
const [randomNum, setRandomNum] = useState(0);
const [opacity, setOpacity] = useState(100);

const getRandomNum = () => {
setRandomNum(Math.floor(Math.random() * 10) + 1);
};

const handleOpacity = () => {
setOpacity(0);
setTimeout(() => setOpacity(100), 500);
};

useEffect(() => {
if (randomNum === 0) {
getRandomNum();
}
const timeout = setTimeout(() => {
setRandomNum(((randomNum + 1) % 3) + 1);
}, 10000);
const timeopacity = setTimeout(() => {
handleOpacity();
}, 9500);

return () => {
clearTimeout(timeout);
clearTimeout(timeopacity);
};
}, [randomNum]);

return (
<div className="relative flex justify-center items-start w-full h-3/5 ">
{data?.results && randomNum !== 0 && (
<img
src={getImageUrl(data?.results[randomNum].poster_path)}
alt="banner_img"
style={{
width: "100%",
height: "100%",
objectFit: "cover",
opacity: opacity / 100,
transition: "all 0.5s ease-in-out",
}}
/>
)}
<div className="absolute z-10 w-full h-full bg-gradient-to-b from-black via-transparent to-black"></div>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gradient 적용하신 디테일 좋은 것 같습니다:)

</div>
);
};

export default MainImage;
53 changes: 53 additions & 0 deletions app/components/MainItemList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use client';
import React from 'react';
import { getImageUrl } from '../../api/movieApi';
import Image from 'next/image';
import { useRouter } from 'next/navigation';

interface MainItemListProps {
title: string;
data: {
results: {
id: number;
poster_path: string;
}[];
};
circle: boolean;
}

const MainItemList = ({ title, data, circle }: MainItemListProps) => {
const router = useRouter();
const movePage = (id: number) => {
router.push(`/detail/${id}`);
};

return (
<div className="w-full h-full flex flex-col">
<div className="font-bold text-2xl text-white pb-4">{title}</div>
<div className="flex flex-row justify-between w-full overflow-x-scroll gap-4 scrollbar-none">
{data.results &&
data.results.map((movie) => (
<div
key={movie.id}
onClick={() => movePage(movie.id)}
className={`min-w-[100px] ${
circle ? 'h-[100px] rounded-full' : 'h-[150px] rounded-md'
} overflow-hidden relative transition-transform transform scale-100 hover:scale-95 hover:transition-all duration-200 ease-in-out`}
>
<Image
src={getImageUrl(movie.poster_path)}
alt="movie poster"
width={100}
height={circle ? 100 : 161}
loading="eager"
placeholder="blur"
blurDataURL="https://via.placeholder.com/100"
style={{ objectFit: 'cover' }}
/>
</div>
))}
</div>
</div>
);
};
export default MainItemList;
Loading