-
Notifications
You must be signed in to change notification settings - Fork 8
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
MISSION4/박건규 #34
base: main
Are you sure you want to change the base?
MISSION4/박건규 #34
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
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.
건규님 안녕하세요~ 항상 열심히 하시는 모습이 멋있으십니다!
styled-component에 대한 경험이 많이 있진 않아서 이 부분에 대해서 어느정도 피드백을 받아보고 싶습니다!
- 저도 딱 "쓰는" 정도로만 사용해서, 유용함을 느끼셨다면 잘 사용하셨다고 생각합니다. 다음에는 라이브러리에서 제공하는 다양한 기능을 사용해보면서(상속, props, theme provider 등등..) "리액트 컴포넌트" 처럼 사용해보신다면 더 유용하시지 않을까 생각해요.
[질문] 이번에 fetch를 사용해보면서 들었던 궁금증은, 프론트엔드 개발자가 알아야 하는 백엔드 지식은 어느정도 일지 궁금합니다!!
- 어떤 부분에서 백엔드 지식을 공부해야겠다고 느끼셨나요? 질문의 요지를 제 마음대로 해석해보자면 기본적인 네트워크 지식은 있어야 된다고 생각합니다!! 그리고 어느정도의 리눅스 지식과 웹 서버가 어떻게 구성되는지 정도는 알면 좋을 듯 하네요. 프론트엔드 개발자도 서버를 통해 문서(html)를 배포할 줄은 알아야 한다고 생각하기 때문입니다!
저는 이 부분에서 학교 수업이 꽤나 도움이 되었습니다~! (도움이 된 과목: 운영체제, 네트워크, 리눅스시스템) 비단 학교 수업 뿐만 아니라 경험으로 얻은 지식도 있지만,,, 이왕 공부하시는 김에 익혀둔다면 cs가 단단한 개발자가 될 수 있지 않을까 생각이 드네요 (저는 물러 터졌지만요 ㅠ)
useEffect(() => { | ||
fetch(url) | ||
.then((response) => response.json()) | ||
.then((data) => setItems(data)); | ||
}, [isSale]); |
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.
로딩 상태와 에러상태도 고민해서 custom hook으로 만들어보는건 어떨까요 ?
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.
추가로 데이터를 패칭하는 곳과 상태를 ShoppingList로 내려보는 건 어떨까요??
.then((data) => setItems(data)); | ||
}, [isSale]); | ||
|
||
const buttonHandler = () => setIsSale(!isSale); |
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.
setIsSale((prev) => !prev)
으로 쓰는 것과 어떤 차이가 있을까요?
return ( | ||
<Main> | ||
<Intro /> | ||
<ToggleBtn buttonText={buttonText} buttonHandler={buttonHandler} /> |
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.
(개인적인 생각입니다)
button이면 buttonHandler라는 onClick으로 바꿔도 될 것 같다는..? 생각이 드네요! 조금더 일반적인 네이밍이면 어떨까 싶어요
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.
추가로 button이니까 안에 들어가는 buttonText를 children으로 받아도 좋을듯하네요 ! 버튼 안에 icon을 담을수도 있으니까요~!
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.
styled component의 GlobalStyle 에 대해 알아보세용
<App /> | ||
</React.StrictMode>, | ||
) | ||
ReactDOM.createRoot(document.getElementById("root")).render(<Shop />); |
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.
StrictMode가 다들 빠져있네욥??
padding-top: 0.5rem; | ||
padding-bottom: 0.5rem; | ||
padding-left: 1rem; | ||
padding-right: 1rem; | ||
margin-top: 1.25rem; | ||
margin-right: 5rem; | ||
align-self: flex-end; | ||
border-radius: 0.5rem; | ||
background-color: #ffffff; |
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.
단축 속성을 이용해보시는건 어떤가요?
img { | ||
width: 100%; | ||
border-radius: 0.75rem; | ||
} | ||
div { | ||
display: flex; | ||
flex-direction: column; | ||
} |
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.
별도의 styled component 로 분리해보는건 어떨까요? 이정도의 deps는 상관없겠지만, 깊어지면 하위 컴포넌트에 영향이 갈지도..?
); | ||
} | ||
|
||
const StyledList = styled.li` |
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.
li인데 네이밍이 List 군요! 컴포넌트명만 본다면 리터럴 그대로 List라고 예측될 것 같습니다
const StyledUl = styled.ul` | ||
display: grid; | ||
padding-left: 5rem; | ||
padding-right: 5rem; | ||
margin-top: 1rem; | ||
grid-template-columns: repeat(3, minmax(0, 1fr)); | ||
gap: 6rem; | ||
width: 100vw; | ||
`; |
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.
ul 접미사가 있는데 위에 StyledList에는 li라는 접미사가 없네요! 일관되지 않은 스타일 같다는 생각이 듭니다!
font-size: 8rem; | ||
color: rgb(2, 6, 23); | ||
background-color: white; | ||
--tw-bg-opacity: 0.35; |
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.
To 리뷰이에게
styled-component에 대한 경험이 많이 있진 않아서 이 부분에 대해서 어느정도 피드백을 받아보고 싶습니다!
사실 저도 잘 모르겠어요… 제가 이 경험을 하지 않아서 피드백을 못드려 죄송합니다. 다만 styled-component는 이름을 짓기가 어렵고, 개인적으론 sementic하지 않아 어려운 감이 있어요.
이번에 fetch를 사용해보면서 들었던 궁금증은, 프론트엔드 개발자가 알아야 하는 백엔드 지식은 어느정도 일지 궁금합니다!!
허허…. 감히 말하기 어렵지만, 상당한 수준의 백엔드 지식은 아닐지라도 백엔드 개발자와 서로 이야기를 하거나 간단한 백엔드는 작성할 줄 알아야 한다고 생각합니다. 예를 들어 어떤 문제가 있을 때 이 문제를 프론트에서 풀어나가야 하는지 아니면, 백엔드에서 풀어나가야 하는지 알려면 백엔드에 대한 인사이트도 알아야 한다고 생각합니다.
그래서 저는 최소한으로 CRUD와 sql 조금은 할줄 알아야 한다고 생각합니다.
추가적으로 말하고 싶은 것
react에서 fetch를 다루는 일은 매우 어렵습니다. 간단하게 데이터를 받으면 다 해결이 되지 않습니다.
먼저 react에서 side effect란 무엇일까요?
저는 react의 생명주기에 벗어나는 것을 side effect라고 생각합니다. react에서 element를 생성하고, state를 생성하며, useEffect로 내부를 동기화 하고, clean up하는 등 모든 일련의 과정에서 벗어난다면 side effect라고 생각합니다. 그렇기 때문에 web에서 돌아가더라도, alert 등 모든 이벤트는 side effect라고 생각합니다.
마찬가지로 fetch는 react와 다른 생명주기를 가지고 있기 때문에 react입장에서는 side effect라고 생각합니다.
그렇다면 react는 side effect를 어떻게 처리할 까?
아시다싶이 react의 FC에서는 useEffect에서 처리합니다. useEffect안에 있는 함수로 side effect를 처리하고, 그에 상응하여 clean up 함수를 이용하여 제거합니다.
react에서 fetch를 처리하는 방법
fetch는 react의 생명주기와 전혀 다르게 처리가 됩니다. 그래서 react와 fetch의 생명주기를 맞추어야 합니다. 예를 들어 fetch에서 데이터가 오지 않았다면(timeout)? fetch에서 에러가 나왔다면? fetch가 데이터를 다 받았지만, 그 데이터를 처리하지 못했다면? react의 컴포넌트가 내려갔지만, fetch는 진행이 되고 있다면? 같은 데이터를 받고 있어 낭비가 되어 cache 처리를 해야한다면? 수많은 고려사항이 있죠.
이 예시 중에 react컴포넌트는 제거가 되었지만, fetch가 진행이 되고 있는 경우 어떻게 해야하는지 예시를 들어볼게요.
useEffect(() => {
fetch('fake/url')
.then((body) => body.json())
.catch((error) => console.error(error))
}, []);
기초적으로 위와 같이 이루어졌다고 가정할게요. 나머지는 무시하고 저 예시만을 들어보겠습니다. 좀 더 극적인 상황을 만들기 위해 fetch를 하는데 약 1초가 걸린다고 가정하고 useEffect를 실행하는데 0.1초가 걸린다고 가정하겠습니다. useEffect가 실행될 때마다 fetch함수가 실행된다면 1초 뒤에는 모든 컴포넌트는 fetch가 10개가 실행되고 있을 것입니다. 컴포넌트가 제거 되었지만 fetch는 실행되는 이유는 v8의 동작 원리에 대해 공부하면 해답이 될 것이라 생각됩니다.
그렇다면 컴포넌트가 제거될 때 fetch를 중단해야할 것입니다. 여기에서 fetch를 중단하게 도와주는 AbortController와 AbortSignal를 사용해봅시다.
useEffect(() => {
const controller = new AbortContoler();
const signal = controller.signal;
fetch('fake/url', {signal})
.then((body) => body.json())
.catch((error) => console.error(error))
return () => {
controller.abort();
}
}, []);
컴포넌트가 제거될 때 useEffect의 cleanup함수가 실행 될 것임으로 contoller.abort()의 함수가 실행 될 것임을 기대됩니다. 이와 같이 한가지 예시만 들어도 6줄의 코드가 늘어났습니다. 위의 내용들을 Dry법칙을 통해 처리하게 만든다면 얼마나 긴 코드가 될지 상상도 하기 싫습니다… 그래서 저희는 훌륭한 오픈소스를 활용해야합니다.
추가적인 방식들
FP(functional programming)로 바뀜에 따라 side effect를 다루는 방식을 FP에서 가지고 올 수 있습니다. 대표적으로 redux가 있겠군요. 이 아티클은 리디북스에서 redux를 통해 데이터를 다루는 방식을 소개합니다. 더 나아가 모던한 방식으로 카카오에서는 react-query를 이용해 처리하는 방식을 소개합니다.
마치며
단순히 useEffect를 다루어 보는 것이 이번 미션의 목표였겠지만, 매우 좋은 주제가 있어 주저리주저리 떠들었습니다. 너무 늦게 작성하여 죄송하네요 ㅠㅠ. 먼가 위 글에서 이상한 점이나, 궁금한 점들이 있으시면 언제든지 댓글 날려주시면 감사하겠습니다. 파이팅!!
Reference
https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch
ReactDOM.createRoot(document.getElementById('root')).render( | ||
<React.StrictMode> | ||
<App /> | ||
</React.StrictMode>, | ||
) | ||
ReactDOM.createRoot(document.getElementById("root")).render(<Shop />); |
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.
혹시... 외람된 말이지만 React StrictMode를 쓰지 않는 이유는 무엇인가요?
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 reset은 좋은거 같아요!! 저도 자주 애용하는 편이에요
padding-top: 0.5rem; | ||
padding-bottom: 0.5rem; | ||
padding-left: 1rem; | ||
padding-right: 1rem; |
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.
padding-top: 0.5rem; | |
padding-bottom: 0.5rem; | |
padding-left: 1rem; | |
padding-right: 1rem; | |
padding: 0.5rem 1rem; |
으로 단축으로 줄일 수도 있을 것 같아요!(이건 선택의 차이이겠네요)
return ( | ||
<StyledUl> | ||
{items.map((item) => ( | ||
<ItemFeed key={item.id} {...item} /> |
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.
오...상당히 센스있는 코드라고 생각해요!
다만 jsx라서 저는 조금 두려운 점이 ItemFeed의 내용이나 items에 대한 내용이 바뀌게 된다면 어떻게 될까? 라는 생각을 해보게 되네요. 이를 어떻게하면 극복할 수 있을까요?
margin-top: 1rem; | ||
grid-template-columns: repeat(3, minmax(0, 1fr)); | ||
gap: 6rem; | ||
width: 100vw; |
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.
const StyledList = styled.li` | ||
width: 100%; | ||
img { | ||
width: 100%; | ||
border-radius: 0.75rem; | ||
} | ||
div { | ||
display: flex; | ||
flex-direction: column; | ||
} | ||
`; |
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.
저는 styled component에 대해서 잘 알지 못해서 궁금한게 있어요!!
이렇게 styled안에서 img, div를 다루게 된다면, 하위 컴포넌트의 div와 img에 영향이 가나요?
font-size: 8rem; | ||
color: rgb(2, 6, 23); | ||
background-color: white; | ||
--tw-bg-opacity: 0.35; |
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.
어... --tw로 시작하는 것은 일반적으로 tailwind에서 사용하는 css variable이에요!!
참고하실때 들어간 것 같네요. ㅠㅠ
background: url("https://cdn.pixabay.com/photo/2016/04/03/11/36/berlin-1304370_1280.jpg"); | ||
background-repeat: no-repeat; | ||
background-size: cover; |
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.
위에 보시면 backgorund-color와 같이 쓰셧는데, 영향이 안가지 않을까 싶네요.
- img태그와
- css에서 background의 차이점이 무엇이 있을까요?(개인적으론 여기서 background를 써도 괜찮겠다라는 생각이긴 하네요)
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.
감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.
useEffect(() => { | ||
fetch(url) | ||
.then((response) => response.json()) | ||
.then((data) => setItems(data)); | ||
}, [isSale]); |
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.
어... 어...단순히 useEffect를 사용한다면 이게 맞지만, fetch를 이용해서 side effect를 다루고 싶다면 조금 더 개선하면 좋을 것 같습니다. 이에 대한 내용은 위 comment에 추가하도록 하겠습니다.
1. 구현 모습
구현 사이트
2. 해결 과정
[styled-component 사용 경험 공유]
[느낀점]
3. To 리뷰어에게
제출이 늦어져서 죄송합니다. 추가적으로 바쁜 시간을 내어 리뷰를 해주시는 리뷰어분들께 감사의 말씀 올립니다