-
Notifications
You must be signed in to change notification settings - Fork 10
[2주차] 조성아 과제 제출합니다. #10
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
base: master
Are you sure you want to change the base?
Conversation
성아님 배포 링크가 지금 권한 문제가 있는 거 같아요 ㅜ-ㅜ 확인 한 번만 부탁드려요 ! |
@@ -0,0 +1,66 @@ | |||
:root { | |||
font-family: system-ui, Avenir, Helvetica, 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.
이게 지금 사이트가 안보여서 잘은 모르겠는데... 안쓰는 폰트들이 들어가 있는 거 같아요
<link | ||
rel="stylesheet" | ||
href="https://cdn.jsdelivr.net/npm/pretendard/dist/web/static/pretendard.css" | ||
/> |
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.
링크로 하는 것도 괜찮은데, 다른 파일에 같이 넣어두면 보기 더 편할 거 같아요
@@ -0,0 +1,223 @@ | |||
import { useEffect, useState } from "react"; |
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.
주석이 상세하게 잘 작성되어 있어 코드 보기에 좋았습니다! 과제 고생하셨습니다
다만 app.jsx의 코드를 컴포넌트 별로 분리하면 더 좋은 코드가 될 것 같습니다!
.map((todo, index) => ({ ...todo, index })) | ||
.filter((todo) => todo.date === selectedDate) | ||
.map((todo) => ( | ||
<TodoItem | ||
key={todo.index} | ||
style={{ | ||
textDecoration: todo.isDone ? "line-through" : "none", | ||
color: todo.isDone ? "#aaa" : "inherit", | ||
}} | ||
> |
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.
index를 key로 사용하기보다 고유의 id를 부여해서 key로 사용해야 불필요한 리렌더링을 하지 않아서 더 좋은 코드가 될 것 같습니다!
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.
과제하시느라 수고 많으셨습니다!!
배포 링크가 열리지 않아 직접 동작은 확인하지는 못했지만, 코드 잘 봤습니당
다음번에는 타입스크립트 적용과 컴포넌트 분리에 조금 더 집중해보셔도 좋을 것 같습니다! 🙂
그리고 블로그도 잘 보았습니다 👍
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/favicon.png" /> |
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.
type="image/svg+xml"
은 SVG 전용 MIME 타입이라, png 형식의 이미지를 사용하실 경우에는 type="image/png"
로 변경해주시면 좋을 거 같아요!
@@ -0,0 +1,17 @@ | |||
<!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.
무헌님께도 리뷰 남겨드린 부분인데, lang="ko"로 지정하면 스크린 리더가 영어를 자동으로 올바르게 해석해줍니다!
따라서 한국어 콘텐츠가 많은 웹페이지라면 기본 언어를 lang="ko"로 지정하실 것을 추천드립니다. :D
https://developer.mozilla.org/ko/docs/Web/HTML/Reference/Global_attributes/lang
import { | ||
AppContainer, | ||
TodoList, | ||
Title, | ||
WeekCalendar, | ||
Day, | ||
AddArea, | ||
ListArea, | ||
TodoItem, | ||
} from "./App.styles"; |
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.
스타일 파일에서 스타일을 불러올 때는
import * as S from "./App.styles";
처럼 네임스페이스를 지정하고,
S.AppContainer
와 같이 접두어를 붙여 작성해주시면 좋습니다!
가독성도 높이고 스타일의 출처를 명확하게 해주는 장점이 있습니다:D
<div | ||
style={{ | ||
textAlign: "center", | ||
marginBottom: "1rem", | ||
fontWeight: 500, | ||
color: "black", | ||
}} |
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 TitleClick = () => { | ||
const today = new Date(); | ||
today.setHours(0, 0, 0, 0); | ||
const startOfThisWeek = getStartOfWeek(today); | ||
setCurrentWeekStart(startOfThisWeek); | ||
setSelectedDate(today.getTime()); | ||
}; |
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.
TitleClick 함수는 이벤트 핸들러 성격을 가지므로,
컴포넌트 네이밍과 혼동되지 않도록 camelCase (ex: handleTitleClick)로 작성해보시는 것도 좋을 것 같습니다 🙂
> | ||
◀ | ||
</button> | ||
{"일월화수목금토".split("").map((day, i) => ( |
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 DAYS = ["일", "월", "화", "수", "목", "금", "토"];
처럼 상수로 분리해두고, map을 활용해 렌더링해주셔도 좋을 것 같습니다!
setCurrentWeekStart(prev); | ||
setSelectedDate(prev.getTime()); | ||
}} | ||
aria-label="이전 주" |
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.
aria-label을 사용해주신 점 좋습니다! 👍
&:hover { | ||
} |
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.
&:hover {}가 현재는 비어 있어서 동작하지 않는데요, 필요 없다면 삭제하셔도 좋을 거 같네용
구현 기능
1. 투두 입력, 완료, 삭제 기능
2. 요일 별 조회 기능
Review Questions
✨1. Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요?
먼저, DOM은 요소들을 트리 형태로 표현한다. 흔히 우리가 아는 p태그 ,div태그 등이 여기에 속한다.

개발자들은 DOM이 제공하는 API를 이용해 이러한 DOM 구조에 접근하고, 내용이나 스타일을 변경할 수 있다. 이런 과정을 DOM 조작이라고 한다.
그렇다면, virtual-dom은 어떤 방식으로 작동할까?
virtual-dom은 실제 DOM의 가벼운 복사본으로 메모리 상에 존재한다. 렌더링 이전의 화면 구조와 렌더링 이후의 화면 구조를 가진 두 개의 가상 돔 객체를 유지하고 있고, 이 두 가상 돔을 비교하여 변경된 부분만 실제 DOM에 반영한다. virtual-dom은 이러한 방식으로 효율적인 방식으로 작동하여 이것을 사용하면 성능이 좋아진다. 이번 과제 때 사용한 React가 이 방식을 사용한다.
✨2. React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다.
리액트는 부모 컴포넌트가 리렌더링되면 자식 컴포넌트도 기본적으로 리렌더링된다. 그런데, 값이나 함수가 실제로 바뀌지 않았는데도 불필요하게 리렌더링되는 경우가 생긴다. 바로, 이를 줄여주는 도구들이 바로 React.memo, useMemo, useCallback이다.
✅ React.memo()
컴포넌트를 기억해서, props가 바뀌지 않으면 리렌더링을 막아줌.
클래스 컴포넌트의 PureComponent 같은 역할.
👉 버튼을 눌러도 Child는 props가 안 바뀌었으니 렌더링 안 됨.
✅ useMemo()
계산 결과를 기억 해서, 의존 값이 변하지 않으면 다시 계산하지 않음.
복잡한 계산 로직이 있을 때 유용.
👉 number가 바뀔 때만 다시 계산하고, 그렇지 않으면 저장된 값 재사용.
✅ useCallback()
함수를 기억해서, 의존 값이 변하지 않으면 같은 함수 객체를 재사용.
자식 컴포넌트에 콜백을 props로 넘길 때 불필요한 리렌더링 방지.
✨3. React 컴포넌트 생명주기에 대해서 설명해주세요.
생명주기 = 컴포넌트가 화면에 나타나고(마운트) → 상태가 바뀌며 다시 렌더링되고(업데이트) → 사라지는(언마운트) 전체 흐름
배포 링크
https://react-todo-22nd-810a6ofgl-chosungahs-projects.vercel.app/
느낀점 및 배운점은 velog에 작성하였습니다.
https://velog.io/@sungahchooo/CEOS-%ED%94%84%EB%A1%A0%ED%8A%B8-%EC%8A%A4%ED%84%B0%EB%94%94-2%EC%A3%BC%EC%B0%A8-%EA%B3%BC%EC%A0%9C