Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d8d5aac
개발 환경 구성
cdm1263 Apr 17, 2023
a9e08fc
eslint, prettier, settings.josn 구성. MovieSearch 컴포넌트 구성
cdm1263 Apr 21, 2023
ab9a6bd
포스터 클릭시 영화 정보페이지로 넘어가도록 MovieInfo 컴포넌트 구현
cdm1263 Apr 22, 2023
5362bfc
App.jsx를 베이스로 components 분리 및 관리, NavigationBar 생성
cdm1263 Apr 25, 2023
92fdf5d
검색된 영화 리스트 영역을 MovieList component로 분리
cdm1263 Apr 25, 2023
fc61d11
fetch 영역 App.jsx로 이동 및 컴포넌트별 기능 최소화. components scss 모듈화
cdm1263 Apr 25, 2023
a4f4fc5
MovieSearch, NavigationBar scss 부분 완성
cdm1263 Apr 27, 2023
366160d
Fetch 함수영역 컴포넌트화. Loading Spinner 추가
cdm1263 Apr 28, 2023
682e1a6
MovieInfoTop으로 input대신 영화 제목 표시
cdm1263 Apr 28, 2023
4a51d94
fetch영역 app으로 통합, select의 value를 참조해 영화를 반복 호출하도록 getMovies 함수 수정
cdm1263 Apr 30, 2023
4c2e032
MovieInfo style 적용
cdm1263 May 2, 2023
93572ec
Logo 컴포넌트 분리, Top 컴포넌트와 Search 컴포넌트 분리, 연도별 검색기능 추가, Search 컴포넌트 화면 중…
cdm1263 May 2, 2023
2057656
netlify.toml 생성
cdm1263 May 2, 2023
d058345
README 작성. About 완성
cdm1263 May 2, 2023
4b51a42
README 부족했던 점 추가
cdm1263 May 2, 2023
046def6
MovieInfo에서의 MovieInfo.module.scss 경로별칭 수정
cdm1263 May 2, 2023
ed42a8c
오타 수정
cdm1263 May 2, 2023
0f98679
경로 수정
cdm1263 May 2, 2023
9fe9a05
배포 사이트 링크 README에 추가
cdm1263 May 2, 2023
50ddd0d
검색 결과가 나오지 않는 경우 에러가 나는 현상 해결
cdm1263 May 4, 2023
6f92bc5
About 수정
cdm1263 May 12, 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
11 changes: 11 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:prettier/recommended"
],
"plugins": [
"react",
"prettier"
]
}
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?
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"semi": false,
"singleQuote": true,
"endOfLine": "lf",
"singleAttributePerLine": true,
"bracketSameLine": true,
"trailingComma": "none",
"arrowParens": "avoid"
}
236 changes: 38 additions & 198 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,219 +1,59 @@
# 🎬 영화 검색

주어진 API를 활용해 '[완성 예시](https://stupefied-hodgkin-d9d350.netlify.app/)' 처럼 자유롭게 영화 검색 기능을 구현해보세요!
과제 수행 및 리뷰 기간은 별도 공지를 참고하세요!

## 과제 수행 및 제출 방법

```
KDT기수번호_이름 | E.g, KDT0_ParkYoungWoong
```

1. 현재 저장소를 로컬에 클론(Clone)합니다.
1. 자신의 본명으로 브랜치를 생성합니다.(구분 가능하도록 본명을 꼭 파스칼케이스로 표시하세요, `git branch KDT0_ParkYoungWoong`)
1. 자신의 본명 브랜치에서 과제를 수행합니다.
1. 과제 수행이 완료되면, 자신의 본명 브랜치를 원격 저장소에 푸시(Push)합니다.(`main` 브랜치에 푸시하지 않도록 꼭 주의하세요, `git push origin KDT0_ParkYoungWoong`)
1. 저장소에서 `main` 브랜치를 대상으로 Pull Request 생성하면, 과제 제출이 완료됩니다!(E.g, `main` <== `KDT0_ParkYoungWoong`)

- `main` 혹은 다른 사람의 브랜치로 절대 병합하지 않도록 주의하세요!
- Pull Request에서 보이는 설명을 다른 사람들이 이해하기 쉽도록 꼼꼼하게 작성하세요!
- Pull Request에서 과제 제출 후 절대 병합(Merge)하지 않도록 주의하세요!
- 과제 수행 및 제출 과정에서 문제가 발생한 경우, 바로 담당 멘토나 강사에서 얘기하세요!

## 요구사항

필수 요구사항은 꼭 달성해야 하는 목표로, 수정/삭제는 불가하고 추가는 가능합니다.
선택 요구사항은 단순 예시로, 자유롭게 추가/수정/삭제해서 구현해보세요.
각 요구사항은 달성 후 마크다운에서 `- [x]`로 표시하세요.
<a href="https://kdt5-chadongmin--omdbapi-movie-search.netlify.app/">영화 검색 배포 사이트</a>

### ❗ 필수

- [ ] 영화 제목으로 검색이 가능해야 합니다!
- [ ] 검색된 결과의 영화 목록이 출력돼야 합니다!
- [ ] 단일 영화의 상세정보(제목, 개봉연도, 평점, 장르, 감독, 배우, 줄거리, 포스터 등)를 볼 수 있어야 합니다!
- [ ] 실제 서비스로 배포하고 접근 가능한 링크를 추가해야 합니다.
- [x] 영화 제목으로 검색이 가능해야 합니다!
- [x] 검색된 결과의 영화 목록이 출력돼야 합니다!
- [x] 단일 영화의 상세정보(제목, 개봉연도, 평점, 장르, 감독, 배우, 줄거리, 포스터 등)를 볼 수 있어야 합니다!
- [x] 실제 서비스로 배포하고 접근 가능한 링크를 추가해야 합니다.

### ❔ 선택

- [ ] 한 번의 검색으로 영화 목록이 20개 이상 검색되도록 만들어보세요.
- [ ] 영화 개봉연도로 검색할 수 있도록 만들어보세요.
- [ ] 영화 목록을 검색하는 동안 로딩 애니메이션이 보이도록 만들어보세요.
- [x] 한 번의 검색으로 영화 목록이 20개 이상 검색되도록 만들어보세요.
- [x] 영화 개봉연도로 검색할 수 있도록 만들어보세요.
- [x] 영화 목록을 검색하는 동안 로딩 애니메이션이 보이도록 만들어보세요.
- [ ] 무한 스크롤 기능을 추가해서 추가 영화 목록을 볼 수 있도록 만들어보세요.
- [ ] 영화 포스터가 없을 경우 대체 이미지를 출력하도록 만들어보세요.
- [ ] 영화 상세정보가 출력되기 전에 로딩 애니메이션이 보이도록 만들어보세요.
- [x] 영화 상세정보가 출력되기 전에 로딩 애니메이션이 보이도록 만들어보세요.
- [ ] 영화 상세정보 포스터를 고해상도로 출력해보세요. (실시간 이미지 리사이징)
- [ ] 차별화가 가능하도록 프로젝트를 최대한 예쁘게 만들어보세요.
- [x] 차별화가 가능하도록 프로젝트를 최대한 예쁘게 만들어보세요.
- [ ] 영화와 관련된 기타 기능도 고려해보세요.

## API 기본 사용법

```curl
curl https://omdbapi.com/?apikey=7035c60c
\ -X 'GET'
```

## 영화 목록 검색

영화 목록은 한 번에 최대 10개까지 검색할 수 있습니다.

파라미터 | 설명 | 기본값
---|----------------------|---
`s` | 검색할 영화 제목(필수!) | -
`y` | 검색할 개봉연도, 빈 값은 전체 검색 | -
`page` | 검색할 페이지 번호 | `1`

요청 코드 예시:

```js
async function getMovies(title, year = '', page = 1) {
const s = `&s=${title}`
const y = `&y=${year}`
const p = `&page=${page}`
try {
const res = await fetch(`https://omdbapi.com/?apikey=7035c60c${s}${y}${p}`)
const json = await res.json()
if (json.Response === 'True') {
const { Search: movies, totalResults } = json
return {
movies,
totalResults
}
}
return json.Error
} catch (error) {
console.log(error)
}
}
```

응답 데이터 타입 및 예시:

```ts
interface ResponseValue {
Search: Movie[] // 검색된 영화 목록, 최대 10개
totalResults: string // 검색된 영화 개수
Response: 'True' | 'False' // 요청 성공 여부
}
interface Movie {
Title: string // 영화 제목
Year: string // 영화 개봉연도
imdbID: string // 영화 고유 ID
Type: string // 영화 타입
Poster: string // 영화 포스터 이미지 URL
}
```

```json
{
"Search": [
{
"Title": "Frozen",
"Year": "2013",
"imdbID": "tt2294629",
"Type": "movie",
"Poster": "https://m.media-amazon.com/images/M/MV5BMTQ1MjQwMTE5OF5BMl5BanBnXkFtZTgwNjk3MTcyMDE@._V1_SX300.jpg"
},
{
"Title": "Frozen II",
"Year": "2019",
"imdbID": "tt4520988",
"Type": "movie",
"Poster": "https://m.media-amazon.com/images/M/MV5BMjA0YjYyZGMtN2U0Ni00YmY4LWJkZTItYTMyMjY3NGYyMTJkXkEyXkFqcGdeQXVyNDg4NjY5OTQ@._V1_SX300.jpg"
}
],
"totalResults": "338",
"Response": "True"
}
```
## 과제 수행 내용

## 영화 상제정보 검색
### 컴포넌트 구조

단일 영화의 상제정보를 검색합니다.
- App

파라미터 | 설명 | 기본값
---|---|---
`i` | 검색할 영화 ID(필수!) |
`plot` | 줄거리 길이 | `short`
- AppTop
- Logo
- Icon
- NavigationBar
- MovieSearch
- Loading
- MovieList

요청 코드 예시:
- MovieInfo

```js
async function getMovie(id) {
const res = await fetch(`https://omdbapi.com/?apikey=7035c60c&i=${id}&plot=full`)
const json = await res.json()
if (json.Response === 'True') {
return json
}
return json.Error
}
```
- MovieInfoTop
- Logo
- Icon
- NavigationBar
- Loading

응답 데이터 타입 및 예시:
- About
- AboutTop
- Logo
- Icon
- NevigationBar

```ts
interface ResponseValue {
Title: string // 영화 제목
Year: string // 영화 개봉연도
Rated: string // 영화 등급
Released: string // 영화 개봉일
Runtime: string // 영화 상영시간
Genre: string // 영화 장르
Director: string // 영화 감독
Writer: string // 영화 작가
Actors: string // 영화 출연진
Plot: string // 영화 줄거리
Language: string // 영화 언어
Country: string // 영화 제작 국가
Awards: string // 영화 수상 내역
Poster: string // 영화 포스터 이미지 URL
Ratings: Rating[] // 영화 평점 정보
Metascore: string // 영화 메타스코어
imdbRating: string // 영화 IMDB 평점
imdbVotes: string // 영화 IMDB 투표 수
imdbID: string // 영화 고유 ID
Type: string // 영화 타입
DVD: string // 영화 DVD 출시일
BoxOffice: string // 영화 박스오피스
Production: string // 영화 제작사
Website: string // 영화 공식 웹사이트
Response: string // 요청 성공 여부
}
interface Rating { // 영화 평점 정보
Source: string // 평점 제공 사이트
Value: string // 평점
}
```
### 부족했던 점

```json
{
"Title": "Frozen",
"Year": "2013",
"Rated": "PG",
"Released": "27 Nov 2013",
"Runtime": "102 min",
"Genre": "Animation, Adventure, Comedy",
"Director": "Chris Buck, Jennifer Lee",
"Writer": "Jennifer Lee, Hans Christian Andersen, Chris Buck",
"Actors": "Kristen Bell, Idina Menzel, Jonathan Groff",
"Plot": "When the newly crowned Queen Elsa accidentally uses her power to turn things into ice to curse her home in infinite winter, her sister Anna teams up with a mountain man, his playful reindeer, and a snowman to change the weather co...",
"Language": "English, Norwegian",
"Country": "United States",
"Awards": "Won 2 Oscars. 82 wins & 60 nominations total",
"Poster": "https://m.media-amazon.com/images/M/MV5BMTQ1MjQwMTE5OF5BMl5BanBnXkFtZTgwNjk3MTcyMDE@._V1_SX300.jpg",
"Ratings": [
{ "Source": "Internet Movie Database", "Value": "7.4/10" },
{ "Source": "Rotten Tomatoes", "Value": "90%" },
{ "Source": "Metacritic", "Value": "75/100" }
],
"Metascore": "75",
"imdbRating": "7.4",
"imdbVotes": "620,489",
"imdbID": "tt2294629",
"Type": "movie",
"DVD": "18 Mar 2014",
"BoxOffice": "$400,953,009",
"Production": "N/A",
"Website": "N/A",
"Response": "True"
}
```
1. webpack 구성에 미숙하여 viteJS로 구성한 점 (현업에서 webpack을 더 많이 사용하게 됨에도 불구)
1. MovieList를 App의 하위 경로로 설정하는 과정에서 `Outlet` 컴포넌트와 props를 동시에 사용했는데 오류가 발생해 하위경로로 설정하지 못한 점
1. 상기 문제로 인해 MovieList가 렌더링 된 화면도 루트 경로인게 되므로 처음 화면으로 돌아가려면 새로고침을 해야하는 점
1. App 내에 fetch 함수가 있음에도 MovieInfo 내에도 별도의 fetch 함수를 중복 작성한 점
1. MovieSearch의 select를 분리하려 했으나 Props Drilling으로 인해 데이터 관리가 복잡해지는 문제로 못한 점
1. Top 컴포넌트들이 대부분 비슷하게 생겼음에도 여러개로 나누어 관리하는 점
19 changes: 19 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/reset.min.css" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0" />
<title>React OMDbAPI Project</title>
</head>
<body>
<div id="root"></div>
<script
type="module"
src="/src/main.jsx"></script>
</body>
</html>
4 changes: 4 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Loading