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

MISSION4/박건규 #34

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

MISSION4/박건규 #34

wants to merge 11 commits into from

Conversation

geongyu09
Copy link
Collaborator

1. 구현 모습

구현 사이트

image
Apr-10-2024 20-34-51


2. 해결 과정

  • 이번 미션은 styled-component를 사용하였습니다. 아주 예전에 아주 잠깐 써봤던 기억이 있는데, 이번에 도전해보았습니다.
  • useEffect와 fetch를 사용하여 mount시 fetch되도록 하였습니다.
  • fetch의 결과값을 state에 담아, fetch 완료시 결과값이 보이도록 하였습니다.
  • sale중인 상품만 볼 수 있는 버튼을 추가하였고, 해당 버튼의 상태를 가지는 state를 만들었습니다. 이는 의존성 배열에 들어가 버튼을 클릭해 state 변경시 다시 fetch문이 실행되도록 구현해보았습니다.

[styled-component 사용 경험 공유]

  • 예전에 아무것도 모르던 시절에 styled-components를 사용해보았었습니다. 그때 당시 모든 컴포넌트를 styled를 통해서 만들었었고, 디버깅 및 코드 정리 지옥에 빠졌던 기억이 있어 좋지 않은 경험으로 남아있었습니다..
  • 이번에 다시 styled-compoenents를 사용하면서 이전의 기억을 떠올리며, 하나의 컴포넌트에는 하나의 styled-component를 만들도록 하였고, 그 결과 작성된 코드가 생각외로 꽤 깔끔하게 느껴졌습니다. (올바른 방법인지는 잘 모르겠습니다..)
  • 이번에 사용하면서 느낀 styled-componenets의 장점은 아래와 같습니다.
    • 기존 css 사용시 결국 하나의 파일로 합쳐지므로 컴포넌트 이름을 고려해야 하지만, styled-component는 큰 우려사항이 아님
    • 하나의 파일에서 style을 관리할 수 있음 (이는 s-dot과 같은 방법은 적용되지 않음)
      • 작업 속도의 향상
      • 디버깅이 쉬움(개인적인 생각!)
  • 반면에 단점은 아래와 같습니다.
    • 엘리먼트의 이름이 커스텀 되어 html 구조를 바로 파악하기 힘들어 디버깅이 어려움
  • 이번 미션이 크지 않아서 상속과 같은 styled-compoenet의 기능을 사용하지 못해 온전히 styled-compoenet의 장점을 느끼진 못하였지만, 나름 괜찮은 느낌을 받았습니다. ( 공식문서도 정말 잘 설명되어있더라고요! )
  • 또한 미션이 간단해서 그럴수도 있지만, css-in-js의 고질적인 단점인 성능 문제에 대해서도 와닿지 않은 것 같습니다.

[느낀점]

  • 급하게 미션을 수행해서 완성도가 조금은 떨어지는 감이 있는 것 같습니다.(특히 이름 짓는 부분..) 많은 지적을 받을 수 있을 것 같습니다..

3. To 리뷰어에게

  • styled-component에 대한 경험이 많이 있진 않아서 이 부분에 대해서 어느정도 피드백을 받아보고 싶습니다!
  • [질문] 이번에 fetch를 사용해보면서 들었던 궁금증은, 프론트엔드 개발자가 알아야 하는 백엔드 지식은 어느정도 일지 궁금합니다!!

제출이 늦어져서 죄송합니다. 추가적으로 바쁜 시간을 내어 리뷰를 해주시는 리뷰어분들께 감사의 말씀 올립니다

@geongyu09 geongyu09 self-assigned this Apr 10, 2024
Copy link

vercel bot commented Apr 10, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Updated (UTC)
donut-study ✅ Ready (Inspect) Visit Preview Apr 10, 2024 11:35am

Copy link
Collaborator

@2yunseong 2yunseong left a 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가 단단한 개발자가 될 수 있지 않을까 생각이 드네요 (저는 물러 터졌지만요 ㅠ)

Comment on lines +13 to +17
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setItems(data));
}, [isSale]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

로딩 상태와 에러상태도 고민해서 custom hook으로 만들어보는건 어떨까요 ?

Copy link
Collaborator

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);
Copy link
Collaborator

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} />
Copy link
Collaborator

Choose a reason for hiding this comment

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

(개인적인 생각입니다)
button이면 buttonHandler라는 onClick으로 바꿔도 될 것 같다는..? 생각이 드네요! 조금더 일반적인 네이밍이면 어떨까 싶어요

Copy link
Collaborator

Choose a reason for hiding this comment

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

추가로 button이니까 안에 들어가는 buttonText를 children으로 받아도 좋을듯하네요 ! 버튼 안에 icon을 담을수도 있으니까요~!

Copy link
Collaborator

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 />);
Copy link
Collaborator

Choose a reason for hiding this comment

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

StrictMode가 다들 빠져있네욥??

Comment on lines +8 to +16
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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

단축 속성을 이용해보시는건 어떤가요?

Comment on lines +17 to +24
img {
width: 100%;
border-radius: 0.75rem;
}
div {
display: flex;
flex-direction: column;
}
Copy link
Collaborator

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`
Copy link
Collaborator

Choose a reason for hiding this comment

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

li인데 네이밍이 List 군요! 컴포넌트명만 본다면 리터럴 그대로 List라고 예측될 것 같습니다

Comment on lines +14 to +22
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;
`;
Copy link
Collaborator

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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

오호? 이건 무엇인가요

Copy link
Collaborator

@loopy-lim loopy-lim left a 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

https://ridicorp.com/story/how-to-use-redux-in-ridi/

https://tech.kakaopay.com/post/react-query-1/

Comment on lines -6 to +5
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
ReactDOM.createRoot(document.getElementById("root")).render(<Shop />);
Copy link
Collaborator

Choose a reason for hiding this comment

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

혹시... 외람된 말이지만 React StrictMode를 쓰지 않는 이유는 무엇인가요?

Copy link
Collaborator

Choose a reason for hiding this comment

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

오 css reset은 좋은거 같아요!! 저도 자주 애용하는 편이에요

Comment on lines +8 to +11
padding-top: 0.5rem;
padding-bottom: 0.5rem;
padding-left: 1rem;
padding-right: 1rem;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
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} />
Copy link
Collaborator

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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

저는.... 높이나 넓이 부분에서 100vw를 잘 쓰지 않아요. (absolute에서는 조금 생각이 다를지도...?)
스크린샷 2024-04-15 오후 4 07 05
그 이유는 위처럼 알지 못하는 스크롤이 생기는 경우가 있어서 그래요.

Comment on lines +15 to +25
const StyledList = styled.li`
width: 100%;
img {
width: 100%;
border-radius: 0.75rem;
}
div {
display: flex;
flex-direction: column;
}
`;
Copy link
Collaborator

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;
Copy link
Collaborator

Choose a reason for hiding this comment

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

어... --tw로 시작하는 것은 일반적으로 tailwind에서 사용하는 css variable이에요!!
참고하실때 들어간 것 같네요. ㅠㅠ

Comment on lines +24 to +26
background: url("https://cdn.pixabay.com/photo/2016/04/03/11/36/berlin-1304370_1280.jpg");
background-repeat: no-repeat;
background-size: cover;
Copy link
Collaborator

Choose a reason for hiding this comment

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

위에 보시면 backgorund-color와 같이 쓰셧는데, 영향이 안가지 않을까 싶네요.

  1. img태그와
  2. css에서 background의 차이점이 무엇이 있을까요?(개인적으론 여기서 background를 써도 괜찮겠다라는 생각이긴 하네요)

Copy link
Collaborator

Choose a reason for hiding this comment

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

감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.감사합니다.

Comment on lines +13 to +17
useEffect(() => {
fetch(url)
.then((response) => response.json())
.then((data) => setItems(data));
}, [isSale]);
Copy link
Collaborator

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에 추가하도록 하겠습니다.

@geongyu09 geongyu09 added the mission 미션 입니다! label May 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mission 미션 입니다!
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants