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

[2주차] 김철흥 미션 제출합니다. #3

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

Conversation

DefineXX
Copy link

@DefineXX DefineXX commented Mar 18, 2025

🔗 Deploy URL

To Do List

👨‍🍳 Design
Design

🫥 느낀 점

🤷🏼‍♂️

KQ 1. Virtual-DOM과 사용시의 이점

Virtual-DOM 이란?

실제 DOM(Document Object Model)을 바로 업데이트하지 않고 메모리에 가상으로 DOM 트리를 생성하여 관리하는 DOM 형식

상태가 변경될 때마다 이전 Virtual-DOM과 새 Virtual-DOM을 비교(diffing)하여 실제 DOM에서 변경된 부분만 업데이트
(얕은 비교)

사용 시의 이점

  • 성능 향상 - 변경된 부분만 실제 DOM에 반영하기 때문에 렌더링 속도와 성능이 크게 향상됨
  • 효율적인 UI 업데이트 - 최소한의 연산만으로 DOM 변경을 처리할 수 있음
  • 개발 생산성 증가 - 개발자는 상태(state)의 변화에만 집중할 수 있으며, DOM 조작을 직접 하지 않아 코드가 간결해짐

KQ 2. React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 렌더링 최적화

✅ React.memo()

함수형 컴포넌트를 memoization(메모이제이션)하여, props가 변경되지 않으면 재렌더링하지 않음

일반적인 PureComponent의 함수형 컴포넌트 버전이라고 볼 수 있음

const MyComponent = React.memo(function MyComponent(props) {
  /* render */
});

컴포넌트가 불필요하게 렌더링되지 않아 성능이 좋아집니디만, props가 많거나 복잡한 경우에 주의 깊게 사용해야 합니다.

✅ useMemo()

값(value)을 메모이제이션하기 위한 Hook으로, 특정 값이 변경될 때만 값이 다시 계산됨

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

연산 비용이 큰 값이나 객체가 불필요하게 재생성되지 않도록 하여 성능을 최적화할 수 있음

✅ useCallback()

함수를 메모이제이션하기 위한 Hook으로, 특정 의존성 배열(dependency array)의 값이 변경되지 않으면 이전에 저장된 동일한 함수 인스턴스를 반환함

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b]
);

📌 자식 컴포넌트에 콜백 함수를 전달할 때 불필요한 재렌더링을 방지하는데 특히 유용함

KQ 3. React 컴포넌트 생명주기

React 컴포넌트는 생성 → 업데이트 → 소멸 단계를 거침

1. 컴포넌트 마운트(Mount)

: 컴포넌트가 처음 화면에 나타날 때 실행

useEffect(() => {
  console.log('컴포넌트가 마운트됨!');
}, []);

빈 배열 []을 의존성 배열로 넘기면 처음 한 번만 실행됨

ex.) API 요청, 이벤트 리스너 등록

2. 컴포넌트 업데이트(Update)

: 상태(state)나 props가 변경될 때마다 실행됨

useEffect(() => {
  console.log('업데이트됨!');
}, [someValue]);

someValue가 바뀔 때만 실행됨
(여러 상태를 넣으면 각각의 변화에 따라 실행됨)

3. 컴포넌트 언마운트(Unmount)

: 컴포넌트가 사라질 때(clean-up) 실행

useEffect(() => {
  return () => {
    console.log('컴포넌트가 언마운트됨!');
  };
}, []);

주로 타이머 제거, 이벤트 리스너 해제, 구독 해제 등에 사용

🔁 전체 구조 예시

useEffect(() => {
  console.log('마운트됨 or 업데이트됨');

  return () => {
    console.log('언마운트되거나, 업데이트되기 전에 정리');
  };
}, [의존성]);

Copy link

@seoyeon5117 seoyeon5117 left a comment

Choose a reason for hiding this comment

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

캘린더도 직접 구현하시고 타입스크립트로 과제 하시느라 수고하셨습니다! 디자인도 열심히 구상하신 것 같아요 2주차 과제 고생 많으셨습니다!

Comment on lines +3 to +14
import leftArrow from '@/assets/left-arrow.svg?react';
import rightArrow from '@/assets/right-arrow.svg?react';

export const LeftArrowIcon = styled(leftArrow)`
width: 1.8rem;
height: fit-content;
`;

export const RightArrowIcon = styled(rightArrow)`
width: 1.8rem;
height: fit-content;
`;

Choose a reason for hiding this comment

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

왼쪽 화살표와 오른쪽 화살표에 두 개의 이미지를 사용하는 것보다 rotate(180deg)를 해서 하나의 이미지만 사용해도 좋을 것 같습니다!

<S.DayListSection>
<S.DayList>
{DAY_LIST.map((day, index) => (
<S.DayListItem key={index}>{day}</S.DayListItem>

Choose a reason for hiding this comment

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

key에 index값을 넣는 것은 권장되지 않습니다. 아래 문서 참고하시면 좋을 것 같아요!

key에 index를 넣으면 안되는 이유

e.preventDefault();

if (task.trim() === '') {
alert('할 일을 입력해주세요!');

Choose a reason for hiding this comment

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

alert는 확인 버튼을 누르기 전까지 사용자의 다른 입력을 막아 사용성을 저해하기 때문에 modal을 사용하는 것을 추천드립니다!

Comment on lines +18 to +28
<Postit paperColor="#DDEBF1">
<S.DoneHeader>
<S.DoneTitleSection>
<S.DoneTitle>Done</S.DoneTitle>
<DoneIcon />
</S.DoneTitleSection>
<TaskCount taskCount={doneList.length} isDone={true} />
</S.DoneHeader>

<TaskList tasks={doneList} />
</Postit>

Choose a reason for hiding this comment

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

글씨가 포스트잇 밖으로 넘어가는데 Postit 높이 수정하고 포지션의 top을 0px보다 크게 수정하면 해결될 것 같습니다!
image

Comment on lines +60 to +66
<S.TaskEditInput
type="text"
value={editedContent}
onChange={handleContentChange}
$isEditing={isEditing}
autoFocus
/>

Choose a reason for hiding this comment

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

수정 가능하게 만들어두신 거 좋은 것 같아요 👍👍

Comment on lines +12 to +19
@media (max-width: 1440px) {
align-items: center;
}

@media (max-width: 1024px) {
flex-direction: column;
padding: 6rem 3.2rem;
}

Choose a reason for hiding this comment

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

반응형 구현하신거 좋습니다 👍👍

const Postit = ({ children, paperColor }: PostItProps): JSX.Element => {
return (
<S.PostitWrapper>
<PostitPaper $paperColor={paperColor} />

Choose a reason for hiding this comment

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

이미지가 깨질때나 스크린 리더를 사용하는 사용자를 고려하여 이미지 태그 사용하실 때는 alt 속성을 추가하는 것이 좋습니다!
https://www.tcpschool.com/html-tag-attrs/img-alt

Choose a reason for hiding this comment

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

캘린더 직접 구현하신거 대단합니다,,

Copy link

@BeanMouse BeanMouse left a comment

Choose a reason for hiding this comment

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

캘린더가 디자인 적이에요 이걸 직접 구현하셧다니 엄지 두개 드릴게요 👍👍

저랑 코드 스타일이 엄청 다른거 같아서 훨씬 배울점이 많은 것 같아요!!

import { generateCalendar } from '@/utils/generateCalender';
import { formatDate } from '@/utils/formatDate';

import * as S from './Calendar.styled';

Choose a reason for hiding this comment

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

이렇게 스타일 구현할 수 있다는 걸 처음 알았습니다... 신기하네용

Comment on lines +21 to +23
year: new Date().getFullYear(),
month: new Date().getMonth() + 1,
day: new Date().getDate(),

Choose a reason for hiding this comment

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

Date 객체를 새로 계속 생성하기보다 어디에 today 값을 설정해서 한번만 불러오는게 어떨까용?

Comment on lines +75 to +77
const handleDaySelect = (day: string) => {
setSelectedDate(day);
};

Choose a reason for hiding this comment

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

이 정도의 함수는 onClick 안에서 처리할 수 있으면 좋을 것 같습니당

onClick={()=>setSelectedDate(day.FullDate)} 이런 느낌??

Comment on lines +35 to +41
const handleEditClick = () => {
setIsEditing(true);
};

const handleCancelClick = () => {
setIsEditing(false);
};

Choose a reason for hiding this comment

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

마찬가지로 함수를 따로 빼는 것 보다 인라인으로 적는게 코드 수나 가독성 쪽에서 좋을 것 같습니당

=> 함수가 여러번 재사용 되거나 useMemo, CallBack등을 사용해야할 때는 따로 빼는 것이 좋습니다!

undefined
);

export const useTasks = () => {

Choose a reason for hiding this comment

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

개인적으로 Context를 쓰는 부분은 파일명이나 함수명을 useTaskContext로 써봐도 좋을 것 같아요

Comment on lines +18 to +30
const selectedDateTask = useMemo(
() => tasksByDate[selectedDate] ?? [],
[tasksByDate, selectedDate]
);

const toDoList = useMemo(
() => selectedDateTask.filter((task) => !task.completed),
[selectedDateTask]
);
const doneList = useMemo(
() => selectedDateTask.filter((task) => task.completed),
[selectedDateTask]
);
Copy link

@BeanMouse BeanMouse Mar 24, 2025

Choose a reason for hiding this comment

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

이정도의 계산은 그냥 일반 변수로 해도 될 것 같다는 생각이 있습니당

오히려 불필요한 메모지에이션으로 복잡성만 늘릴 수도 있어요

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.

3 participants