Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 4 additions & 0 deletions .babelrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module.exports = {
presets: ['@babel/preset-env'],
plugins: [['@babel/plugin-transform-runtime', { corejs: 3 }]],
}
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:import/recommended",
"plugin:prettier/recommended"
],
"plugins": [
"import",
"prettier"
]
}
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
node_modules
.vscode
dist

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"
}
281 changes: 62 additions & 219 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,219 +1,62 @@
# 🎬 영화 검색

주어진 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]`로 표시하세요.

### ❗ 필수

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

### ❔ 선택

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

## 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"
}
```

## 영화 상제정보 검색

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

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

요청 코드 예시:

```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
}
```

응답 데이터 타입 및 예시:

```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"
}
```
## 🎬 2차과제 : API를 활용한 영화검색 사이트 만들기

> 작성자 : KDT5 김다슬 - 4조

### [결과물](https://ephemeral-pastelito-792562.netlify.app/#/)
> HTML, SCSS, JS, Webpack 활용

<br>

## 필수 요구사항

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

<br>

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

<br>

## 화면 & 구현한 부분

1. 시작페이지
![image](https://github.com/7581058/omdb-app/blob/main/assets/screenshots/page_start.png?raw=true)
처음 접속하면 보여지는 페이지이며,
영화와 관련된 기타 기능으로
목록 중 추천 받길 원하는 장르를 선택하면 세션스토리지에 저장해 다음 화면에서 선택한 장르의 영화목록들이 보여지게 됩니다.

2. 메인페이지
![image](https://github.com/7581058/omdb-app/blob/main/assets/screenshots/page_home.png?raw=true)
![image](https://github.com/7581058/omdb-app/blob/main/assets/screenshots/page_home_search.png?raw=true)
시작 페이지에서 버튼을 누르면 나오는 페이지로 상단에는 새로 개봉한 영화에 대한 예고편과 정보를 보여주고 중앙에는 선택한 장르에 대한 추천 목록을 보여주고 하단에는 검색할 수 있는 검색창이 나타납니다.
영화를 검색할 수 있고, 포스터가 없는 영화는 대체 이미지가 출력됩니다. 무한 스크롤을 통해 검색한 영화에 대한 모든 목록을 조회할 수 있습니다.

3. 상세 정보 출력
![image](https://github.com/7581058/omdb-app/blob/main/assets/screenshots/modal.png?raw=true)
상단에 출력된 영상의 more 버튼이나, 추천된 영화 목록을 클릭하거나 검색된 영화를 클릭하면 나타나는 영화에 대한 상세 정보를 모달창으로 보여줍니다.

4. NotFound 페이지
![image](https://github.com/7581058/omdb-app/blob/main/assets/screenshots/page_notfound.png?raw=true)
등록된 페이지 외의 주소로 접근하면 보여주는 페이지 입니다.

<br>

## 아쉬운 부분

1. 처음에는 메인 페이지 상단에 영상이 들어간 슬라이드를 구현했었으나, 비디오와 슬라이드에 관련된 지식 부족으로 기존에 구현하려고 했던 각 슬라이드의 영상이 재생완료 되면 다음 슬라이드로 넘어가는 기능을 구현하지 못했고, 슬라이드 또한 영상은 출력되나 자동 슬라이드가 잘 되지 않는 일이 발생했고, 슬라이드가 생성될 때마다 정보를 불러왔었기 때문에 성능 문제가 생겨 슬라이드를 삭제하고 단일 영상으로 대체하게 되었습니다.

2. 기능 구현에만 급해 정보를 받아온 후 슬라이드들이 생성되고 출력될 때의 속도, 성능 등에 대해 생각하지 못했던 점이 아쉬웠고, 최대한 수정했으나 api요청, 비동기에 대한 이해가 아직 많이 부족하다는 것을 알게되었습니다.

3. 영화를 검색한 후 스크롤을 내리면 무한스크롤로 검색한 모든 정보를 볼 수 있는데 스크롤을 로딩을 기다리지 않고 급하게 내리거나 하면 검색 목록이 온전하지 않은 부분이 생기는 경우에대해 해결을 하지 못했습니다.
Binary file added assets/resource/Internet Movie Database.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/resource/Metacritic.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/resource/Rotten Tomatoes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/resource/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/resource/noimage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
24 changes: 24 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OMDbAPI.COM</title>

<!-- favicon -->
<link rel="icon" href="./resource/favicon.png">

<!-- google fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Nanum+Gothic&family=Poppins:wght@500&family=Space+Mono:wght@400;700&display=swap" rel="stylesheet">

<!-- google materal icon -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@48,400,0,0" />

</head>
<body>
<div id="root"></div>
</body>
</html>
Loading