-
Notifications
You must be signed in to change notification settings - Fork 0
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
[ 3주차 기본/공유 과제 ] 카드뒤집기 #4
base: main
Are you sure you want to change the base?
Conversation
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.
전체적으로 함수이름, 변수명등이 명확해서 각 역할에 대해서 잘 이해할 수 있었습니다! 긱 로직이 잘 구현되어 있는 만큼 역할에 따라서 잘 분리하면 더욱 좋은 코드가 될 것 같습니다!! 과제 내용을 잘 구현하심에 대해서 확인했고 제가 남긴 의견은 저의 의견일 뿐이니 필요하다고 생각하시는 부분만 반영하시면 될 것 같습니다. 과제 하시느라 고생 많으셨습니다 👍 👍
three session/test/src/App.jsx
Outdated
import { createGlobalStyle, ThemeProvider, styled } from 'styled-components'; | ||
import cardImages from './card'; | ||
|
||
console.log(cardImages); |
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.
console.log같이 디버깅을 위해서 넣어둔 코드는 지워주는 것도 좋을 것 같아요!
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.
옙 감사합니다.
margin-bottom: 20px; | ||
`; | ||
|
||
const Modal = styled.div` |
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.
modal에 해당하는 컴포넌트는 따로 만들어서 가져오는 방식으로 구현하는 건 어떨까요? 현재 app 컴포넌트가 길고, 여러 기능을 담당하고 있습니다. 코드의 가독성과 유지보수성을 높이기 위해, 컴포넌트를 더 작은 단위로 분리하고 해당 기능에 맞게 역할을 분배하는 것은 어떨까요?
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.
저도 성희님 말에 동의합니다! modal, card, header, button 등등.. 컴포넌트를 작은 단위로 분리하고 사용하면 훨씬 더 가독성있는 코드가 될 거 같아요!
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
gap: 16px; | ||
`; | ||
|
||
function Card({ card, handleChoice, flipped }) { |
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.
모달 컴포넌트 분리때와 마찬가지로 카드라는 컴포넌트도 따로 분리해서 구현하는 방식이라면 유지 보수 측면에서 더욱 좋을 것 같습니다!!
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
|
||
useEffect(() => { | ||
if (choiceOne && choiceTwo) { | ||
if (choiceOne.src === choiceTwo.src) { |
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.
카드가 일치하는지의 여부를 이미지의 주소로 확인하고 있는데 이것도 좋지만 카드의 데이터에 이미지와 함께 id를 부여해서 카드의 일치를 확인하면 더욱 좋을 것 같아요!
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
}, [choiceOne, choiceTwo]); | ||
|
||
useEffect(() => { | ||
if (matchedPairs ===5) { |
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.
매직 넘버보다는 상수를 이용해서 수를 관리하면 나중에 숫자를 바꿀때도 상수의 내용만 바꾸면 되니 더욱 유용할 것 같아요!
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.
옙 다음에 상수 한번 이용하겠습니다~ 감사합니다.
three session/test/src/App.jsx
Outdated
.map((card, index) => ({ ...card, id: index, flipped: false })); | ||
|
||
// 게임 상태를 초기화합니다. | ||
setChoiceOne(null); |
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.
게임 상태를 초기화 하는 코드를 따로 함수로 빼서 initCards와 같이 만들어서 호출하는 건 어떨까요? 따로 관리하면 나중에 여기가 아닌 다른 곳에서 초기화를 하는 경우에도 잘 사용할 수 있을 것 같아요!
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.
옙 감사합니다.
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.
컴포넌트와 스타일 파일을 만들어서 적용시키면 더더 좋은 코드가 될 거 같아요! 과제하느라 고생하셨습니다!!
three session/test/src/App.jsx
Outdated
const CardFront = styled(CardFace)` | ||
background: ${props => props.theme.colors.secondary}; | ||
display: flex; | ||
align-items: center; | ||
justify-content: center; | ||
font-size: 0; | ||
color: white; | ||
transform: rotateY(180deg); | ||
`; |
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.
pr에서 질문주신 카드 css 에 관한 답변입니다..!
background-size: cover; // 이미지가 카드 크기에 맞게 조절 background-position: center; // 이미지가 카드 중앙에 위치
이 두가지 속성 넣으면 이미지가 카드 크기에 맞게 나올 겁니다..!
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
`; | ||
|
||
const CardFront = styled(CardFace)` | ||
background: ${props => props.theme.colors.secondary}; |
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.
이 부분은 카드 색상 지정하는 거 같은데, 카드에 이미지가 표시되니 지워도 되지 않을까요?!
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.
옙 감사합니다.
margin-bottom: 20px; | ||
`; | ||
|
||
const Modal = styled.div` |
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.
저도 성희님 말에 동의합니다! modal, card, header, button 등등.. 컴포넌트를 작은 단위로 분리하고 사용하면 훨씬 더 가독성있는 코드가 될 거 같아요!
three session/test/src/App.jsx
Outdated
const GlobalStyle = createGlobalStyle` | ||
body, html { | ||
height: 100%; | ||
margin: 0; | ||
font-family: 'Comic Sans MS', 'Arial', sans-serif; | ||
background: #EED1D1; | ||
display: flex; | ||
justify-content: center; | ||
align-items: center; | ||
} | ||
`; | ||
|
||
const theme = { | ||
colors: { | ||
primary: '#FFC1C1', | ||
secondary: '#FFF3F3', | ||
text: '#333', | ||
modalBackground: 'rgba(0, 0, 0, 0.5)', | ||
white: 'white', | ||
shadow: 'rgba(0,0,0,0.1)' | ||
}, | ||
fonts: { | ||
main: 'Comic Sans MS, Arial, sans-serif' | ||
} | ||
}; |
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.
global style 부분과 theme 부분도 따로 파일로 빼서 적용하면 좋을 거 같아요! 관련자료 첨부해요!
https://oliviakim.tistory.com/120
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.
옙 감사합니다.
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.
옙 감사합니다.
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.
성희랑 채원이가 너무 잘 달아주어서 추가적으로 말할 부분들만 달아두었어요!
성희랑 채원이가 단 부분들은 저도 다 동의하는 부분들이니 한 번 잘 찾아보고 적용해보면 좋을 것 같아요!
로직 짜는 건 너무너무 잘 해주었는데, 컴포넌트를 별도의 파일로 분리해서 관리해야하는 상태들을 prop으로 내려주는 부분을 더 공부해보면 좋을 것 같아요
컴포넌트를 어떻게 분리해야할지 감이 잘 잡히지 않을 때는
- 뷰에서 담당하는 부분이 확실하게 존재하는지 (Header, GameMain, Modal 등)
- 해당 부분에서 관리하는 상태, 데이터값이 얼마나 겹치는지 ! (GameMain과 Header의 경우에는 공통으로 사용되는 데이터값이 많죠 ? 예를 들면 전체 카드 배열 길이라던가, 매칭된 카드 배열 길이라든가 .. )
- 이러한 컴포넌트들을 공통으로 감쌀 수 있는 부모가 있는지, (현재는 App이 되겠죠?) 있다면 그 부모 컴포넌트에서 관련된 데이터들을 다루고, 필요한 컴포넌트들에 prop으로 내려주어 사용하면 되겠죠?
이런식으로 컴포넌트를 분리해나가는 과정을 공부해보면 좋을 것 같아요!
과제하느라 너무너무 수고 많았습니다~
three session/test/src/App.jsx
Outdated
const CardFace = styled.div` | ||
backface-visibility: hidden; | ||
position: absolute; | ||
width: 150px; |
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.
px말고 rem 사용하기!
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
const [choiceOne, setChoiceOne] = useState(null); | ||
const [choiceTwo, setChoiceTwo] = useState(null); |
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.
이 부분을 하나의 배열 state로 만들어서 사용해도 좋을 것 같아요!
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.
옙 감사합니다.
/* 게임 상태 바 */ | ||
.game-status-bar { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
padding: 20px; | ||
background-color: #FFF3F3; | ||
border-radius: 10px; | ||
box-shadow: 0 5px 10px rgba(0,0,0,0.1); | ||
margin-bottom: 20px; | ||
} |
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.
이 파일에 있는 css는 안쓰이고 있는 것 같은데 맞나요 ? 안쓰인다면 지워줘도 될 것 같아요!
그리고 styled-component를 사용하는 만큼, 스타일 관련 코드는 컴포넌트화해서 사용하는게 좋을 것 같습니다~
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.
옙 감사합니다.
three session/test/src/App.jsx
Outdated
Card.propTypes = { | ||
card: PropTypes.shape({ | ||
src: PropTypes.string.isRequired, | ||
matched: PropTypes.bool.isRequired, | ||
id: PropTypes.number.isRequired | ||
}), | ||
handleChoice: PropTypes.func.isRequired, | ||
flipped: PropTypes.bool.isRequired | ||
}; |
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.
이 부분은 타입스크립트를 사용하게되면 사용하지 않아도 되는 부분이랍니다 ! 참고!
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.
옙 감사합니다~
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.
민준이는 제가 디코에서 직접 리뷰하러 오겠습니다~
three session/test/index.html
Outdated
@@ -0,0 +1,13 @@ | |||
<!doctype html> | |||
<html lang="en"> |
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.
ko로 변경해주세요!
three session/test/index.html
Outdated
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + React</title> |
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.
title역시 SEO에 굉장히 중요합니다! page에 알맞은 title로 변경해주세요!
.game-status-bar h1 { | ||
margin: 0; | ||
font-size: 1.5em; | ||
color: #333; | ||
} | ||
|
||
.game-status-bar button { |
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.
이렇게 사용하면 game-status-bar 내부에 버튼이 여러개 존재할 경우 예기치 않은 오류가 발생할 수 있습니다!
button역시 className을 부여해서 사용해주세요
✨ 구현 기능 명세
🧩 기본 과제
header 구현
card section 구현
카드가 선택되었을 때 카드를 open합니다.
두 번째 카드가 클릭될 때 까지 카드는 open상태여야합니다.
두 번째 카드를 클릭하였을 때
정답일 경우 카드 두개를 open 상태로 고정하고 score를 올립니다.
오답일 경우 카드 두개를 다시 close합니다.
게임에 성공하였을 때
🔥 심화 과제
난이도 설정
게임 reset
카드 뒤집기 애니메이션
모달
공유과제
링크 첨부(팀 블로그 링크) : https://forweber.palms.blog/nowsopt-react-minjune
📌 내가 새로 알게 된 부분
import { createGlobalStyle, ThemeProvider, styled } from 'styled-components'; const GlobalStyle = createGlobalStyle
body, html {
height: 100%;
margin: 0;
font-family: 'Comic Sans MS', 'Arial', sans-serif;
background: #EED1D1;
display: flex;
justify-content: center;
align-items: center;
}`
스타일 컴포넌트를 통해 코드의 css를 유지보수하게 쉽게 구현하는 방법을 배웠습니다.
Card.propTypes = { card: PropTypes.shape({ src: PropTypes.string.isRequired, matched: PropTypes.bool.isRequired, id: PropTypes.number.isRequired }), handleChoice: PropTypes.func.isRequired, flipped: PropTypes.bool.isRequired };
React에서 컴포넌트에 전달되는 props(속성)의 유효성을 알아보는 proptypes에 대해 알게 되었습니다. 이를 통해 개발자는 컴포넌트가 예상대로 올바른 데이터 타입의 props를 받고 있는지 확인할 수 있었으며, propTypes를 사용하는 것은 컴포넌트가 기대하는 props의 종류와 타입을 명시적으로 선언하고, 개발 과정에서 타입 오류를 조기에 발견하는 데 도움이 됩니다.
src: 문자열(PropTypes.string.isRequired)로, 카드 이미지의 URL을 나타냅니다.
isRequired는 이 프로퍼티가 반드시 제공되어야 함을 의미합니다.
matched: 불리언(PropTypes.bool.isRequired)으로, 카드가 매치되었는지 여부를 나타냅니다.
id: 숫자(PropTypes.number.isRequired)로, 카드의 고유 식별자를 나타냅니다.
💎 구현과정에서의 고민과정(어려웠던 부분) 공유!
`useEffect(() => {
if (choiceOne && choiceTwo) {
if (choiceOne.src === choiceTwo.src) {
setCards(prevCards => prevCards.map(card => card.src === choiceOne.src ? { ...card, matched: true } : card));
setMatchedPairs(prev => prev + 1);
setTimeout(() => resetTurn(), 1000);
} else {
setTimeout(() => resetTurn(), 1000);
}
}
}, [choiceOne, choiceTwo]);
useEffect(() => {
if (matchedPairs ===5) {
setShowModal(true);
console.log('matchedPairs', matchedPairs);
}
console.log('cardImages.length', cardImages.length);
}, [matchedPairs]);`
카드를 맞추는 로직이 생각이 도저히 떠올리기 힘들어서 관련 레퍼런스(이전 상태값을 이용!!)를 참고했습니다. 그리고 카드의 쌍을 모달이 인식을 해야 하는데 인식을 해결할 수 없어 임의로 숫자를 부여해서 만들었습니다.
혹시 다른 분들은 어떻게 하셨는지 궁금합니다. ㅠㅠ
파일 구조를 분리를 할려 했으니 계속 실패?!하여 결국 app.jsx에 다 집어넣는 현상이 일어났는데
이것도 역시 다른분들은 어떻게 하셨는지 궁금합니다.
const CardFace = styled.div
backface-visibility: hidden;
position: absolute;
width: 150px;
height: 150px;
border-radius: 20px;
box-shadow: 0 5px 10px ${props => props.theme.colors.shadow};
`;
const CardBack = styled(CardFace)
background: ${props => props.theme.colors.primary};
;const CardFront = styled(CardFace)
background: ${props => props.theme.colors.secondary}; display: flex; align-items: center; justify-content: center; font-size: 0; color: white; transform: rotateY(180deg);
;`css아직 활발하게 활용하지 못하는데 각 카드의 이미지가 모두 나오게 할려했는데 부분적으로 나왔습니다... 다른 분들은 어떻게 하셨는지 궁금합니다.
🥺 소요 시간
-7일
🌈 구현 결과물