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

KDT5_송홍빈_2차과제(re-open) #76

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

hbsongk
Copy link

@hbsongk hbsongk commented May 12, 2023

프로젝트 개요

  • 목표 : 영화 검색 사이트 구축하기 with OMDb API
  • 개발 기간 : 2주
  • 사용 스택 : Vite, React, Styled Components, Netlify

배포 주소

이미지

  • Movie Search
    1

  • Movie Detail
    2

구현 내용 (과제 요구사항)

❗ 필수

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

❔ 선택

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

아쉬운 점

  • input 요소에 "avengers"를 집어넣었을 시, "avengers"라는 영화가 출력이 되지 않고
    "avenger" 타이틀을 가지고 있는 영화가 출력 됩니다. useState의 비동기적 특성 때문이라고 추측하고 있습니다. 혹시 어떻게 해결해야 할까요?
  • github branch issue로 commit을 다 날려버린 것이 아쉽습니다.
  • 더 많은 기능들을 추가해보지 못한 점이 아쉽습니다.

@hbsongk hbsongk requested a review from ParkYoungWoong May 12, 2023 01:30
@hbsongk hbsongk self-assigned this May 12, 2023
@happyhermann
Copy link

홍빈님 첫 번째 리액트 프로젝트 하시느라 고생 많으셨습니다.
제가 보기로는 깃 사용중 문제가 생겨 기존의 프로젝트를 날려먹으신 것처럼 보이는데 저도 경험해봐서 시정을 이해할 수 있습니다...
하지만 급하게 하신 것중에서도 발전하신 모습을 볼 수 있었습니다.
일단은 비동기에 대한 이해와 styled-components로 태그를 직접 만들어보는 것, 그리고 router를 다뤄보는 것, map 함수와 같은 자바스크립트 배열 메서드를 경험해보는 것은 차후 남은 리액트 프로젝트에 도움이 될 거같네요!

만약에 조금더 공부해야할 시간이 있으시다면

BrowserRouter, Routes, Route 다루는 법
컴포넌트를 props로 재활용 하는 법 (atomic한 컴포넌트부터 '버튼' '인풋' '타이틀')
props-drilling
styled-components에서 theme.js와 globalStyles를 사용하여 전역적인 스타일링 관리를 하는 방법

등을 공부하시면 다음 프로젝트때 더욱 효율적인 코딩을 하시는데 도움을 줄거 같네요

정말 고생 많으셨습니다!

}
return (
<>
<TheHeader />

Choose a reason for hiding this comment

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

라우터 지금도 잘 써주셨는데요! 라우터를 더 간결하게 쓰려면

Header나 Footer같이 페이지 구분없이 고정되는 컴포넌트는 최상위 폴더 (라우터 렌더링되는 곳 밖에) 구현하면 한번 선언으로
다시 선언하지 않아도 됩니다.
직관적이고 간편하게 구현하려면 router-dom-v6 버전의 BrowserRouter, Routes, Route를 이용하면 간편하게 구현 가능합니다.

영상 참고 : https://www.youtube.com/watch?v=oDJMHEcKiL0

Comment on lines +114 to +129
{blankArray.map(movie => (
<Movie key={movie.imdbID}>
<div className="flip">
<div className="card">
<BlankFront>{movie}</BlankFront>
<Back>
<MovieYear>{movie.Year}</MovieYear>
<MovieTitle>{movie.Title}</MovieTitle>
</Back>
</div>
</div>
</Movie>
))}
</MovieContainer>
)}
</>

Choose a reason for hiding this comment

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

독특한 UI 신박했습니다!

그런데 UI 측면에서 봤을 때 검색하기전에 '검색결과가 없습니다'라는 UI가 보이면 좀 어색할 수 있을거 같네요
초기화면, 검색결과 없는 화면, 검색 결과 화면 이렇게 세 개로 조건부 렌더링하면 더 좋은 Ui를 경험하게 해줄 수 있을거같습니다!

Comment on lines +12 to +30
const Movie = styled.div`
display: grid;
justify-content: center;
align-items: center;
`
const Front = styled.img`
&:hover {
color: red;
}
cursor: pointer;
border: solid;
border-radius: 10px;
position: absolute;
width: 100%;
height: 100%;
border-radius: 10px;
backface-visibility: hidden;
background: red;
`

Choose a reason for hiding this comment

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

styled-components를 이용해 스타일링을 프로젝트에 적용/시도 해보는 모습이 정말 좋았습니다!
아마 시간상 CSS에 시간을 쓰지 못한 부분이 있으셨을거 같습니다 첫 프로젝트이고 하니

그래도 팁을 하나 드리자면
styled-components에서 태그를 만들어 쓸 때 재사용성이 많은 것들은 태그를 직접 만드는 것이 더 효율적이나
하위에 속할만한 간단한 것들은 중첩 코드안에 태그 그 자체로 쓰고 스타일링 해주는게 좀더 좋을 수 있습니다!

font-size: 50px;
`
export default function Movie() {
const [movie, setMovie] = useState({})

Choose a reason for hiding this comment

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

api를 불러올때 통상적으로 받아오는 데이터 형태는 여러 객체를 가진 배열이므로
useState의 초기값은 빈 객체 '[]'로 설정하는 것이 좀더 명확해질것 같습니다!

Comment on lines +28 to +32
useEffect(() => {
;(async () => {
setMovie(await fetchDetailMovie())
})()
}, [])

Choose a reason for hiding this comment

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

리액트 생명주기를 사용해해서 렌더링시 한 번만 호출되는 비동기 api 함수는 굉장히 아름답고 리액트스러운 것 같습니다

Comment on lines +27 to +34
const [inputText, setInputText] = useState('')
async function getMovie(e) {
setInputText(e.target.value)

if (inputText.trim() === '') return
const movieList = await fetchMovies(inputText)
handleMovieState(movieList)
}

Choose a reason for hiding this comment

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

영화 검색 결과를 받아오는 데이터는 context API나 redux와 같은 전역적 state 관리 라이브러리가 없으면 api 호출 중복을 막기 위해 또는
다른 컴포넌트와 데이터를 주고 받기 용이하게 하기위해 되도록 상단 컴포넌트에서 구현해서 props로 넘겨줄 수 있게 구현하는 것이 좀더 효율적일 수 있습니다!

Comment on lines +43 to +48
onFocus={e => {
e.target.placeholder = ''
}}
onBlur={e => {
e.target.placeholder = '영화를 검색하세요'
}}

Choose a reason for hiding this comment

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

onFocus와 onBlur을 사용하신 것은 꽤나 인상적입니다!

Comment on lines +16 to +18
<Container>
<Title>About Something..</Title>
</Container>

Choose a reason for hiding this comment

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

이렇게 중복되는 스타일은 스타일드 컴포넌트로만 만들기보다
아토믹한 컴포넌트로 만들어보는 것도 좋은 시도입니다!
Container 컴포넌트를 함수형 jsx로 구현후 그 컴포넌트에 지금의 Container 스타일링을 주고
props로 뚫어놓고 재사용이 용이하게 만드는게 정말 편하더라고요!
스타일드 컴포넌트로 시도해보신거는 정말 좋은 모습이신거 같아요 대부분 SCSS를 쓰셨거든요!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants