Skip to content

Conversation

codus02
Copy link

@codus02 codus02 commented Sep 19, 2025

배포 링크
https://react-todo-22nd-git-codus02-chaeyeons-projects-9268a0f8.vercel.app

후기: 리액트를 실제 사용해보는것은 처음이라 리액트 설치하는 방법부터 공부하느라 약간 시간이 빠듯했다. 저번주에 피드백받은 부분들을 수정해서 구현 결과는 같지만 코드를 발전시키고 싶었지만 그러지 못한것이 아쉽다. 확실히 html 파일이 간결해진게 보기는 좋지만 리액트를 왜 쓰는건지는 아직 명확히 이해는 덜됐다. 그리고 리액트를 사용했지만 .jsx 파일을 하나밖에 생성 사용하지 않아 제대로 그 기능을 완전히 아직 사용하지 못한것같다. 얼른 열심히 공부해야할것같다...
그리고 주완님 배포하는것도 도와주셔서 너무 감사하다.. 다음주에도 도와주시겠지

  • Virtual-DOM은 무엇이고, 이를 사용함으로서 얻는 이점은 무엇인가요?

    리액트에서는 가상돔 (Virtual Dom)을 사용하는데, 이는 실제 DOM을 모방해 만들어낸것이다. 가상돔은 메모리에 저장된 자바스크립트 객체 형태로 존재한다. DOM을 변경하는 것은 무겁기 때문에 빠른 화면전환을 위해 가상돔을 사용한다. 가상돔은 렌더링 전의 화면과 렌더링 후의 화면 두개의 가상 돔 객체를 유지하며, 이 둘을 비교하며 변경된 부분만 실제 DOM에 반영한다. 이 방법을 통해 변경사항만을 빠르게 파악하고 리렌더링이 가능해졌다.

  • React.memo(), useMemo(), useCallback() 함수로 진행할 수 있는 리액트 렌더링 최적화에 대해 설명해주세요. 다른 방식이 있다면 이에 대한 소개도 좋습니다.

    React.memo()는 props가 변경되지 않으면 이전 렌더링 결과를 재사용해 불필요한 렌더링을 막는다. state, context 가 변경되면 리렌더링이 된다.

useMemo()는 복잡한 계산 결과를 메모이제이션해 의존성 배열 값이 변경될때만 다시 계산한다. 불필요한 계산을 줄인다.

useCallback()는 함수를 메모이제이션해 불필요하게 새로 정의되는 것을 방지한다. 하위 컴포넌트에 함수 props를 전달할때 불필요한 리렌더링을 막는다.



  • React 컴포넌트 생명주기에 대해서 설명해주세요.

    생명주기는 컴포넌트가 생성되고 없어질때까지를 말한다. 생성 (mounting)- 업데이트(updating)- 제거(unmounting) 단계로 이루어져있으며, 각 단계마다 특정한 이벤트가 발생한다. 이러한 생명주기는 클래스형 컴포넌트에서만 사용할 수 있고 함수형 컴포넌트에서는 사용하지 못했으나 Hooks를 이용해 사용이 가능해졌다.

mount는 돔이 웹 브라우저상에 나타나는 단계로 한번만 실행된다. updating은 속성이나 상태가 변경되어 엘리먼트를 업데이트할때 발생하며 여러번 발생한다. unmounting은 엘리먼트를 DOM에서 제거할때 발생하며 한번만 실행된다.



Copy link

@jungyungee jungyungee left a comment

Choose a reason for hiding this comment

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

과제 수고 많으셨습니다..! ☺️ 부족하지만,, 과제한 것 살펴보면서 코드리뷰 남겨보았습니당
도움이 되었으면 좋겠습니다 ㅎㅎ
특별히 언급하지 않은 부분은 잘 되어있는 거 같아요..!
다만 현재 배포 링크가 공개가 안 되어있는 것 같아서 설정 바꿔주셔야 할 것 같아요!


.hidden {
display: none;
}

Choose a reason for hiding this comment

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

먼저, 이번 과제에서는 Styled Component를 사용하면 좋았을 거 같습니다! 특정 스타일, 기능을 가진 컴포넌트를 만들 수 있습니당

Choose a reason for hiding this comment

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

그래도 현재 css에서 보기 편한 구조와 명확한 네이밍이 좋은 것 같습니다!

const prefix = dateStr === todayStr ? '오늘' : dateStr;
const progressText = `${prefix} 할일 ${totalCount}개 중 ${completedCount}개 완료`;

// ==== UI ====

Choose a reason for hiding this comment

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

모든 코드를 App.jsx에 박기보다는 컴포넌트 단위로 분리하여서 파일을 나누면 가독성, 재사용성이 더 좋을 것 같습니다..!
Header, Input, Progress, List 등 화면 구성 별로 나누어 두면 좋을 거 같아요..!

}`;

export default function App() {
// ==== state ====

Choose a reason for hiding this comment

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

상태관리 훅이나 로직 등이 모두 한 파일에 있어서 커스텀 훅을 사용해봐도 좋을 것 같아요..!

Comment on lines +147 to +153
<button
className="dateNavBtn"
id="nextDay"
onClick={() => moveToDate(1)}
>
</button>

Choose a reason for hiding this comment

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

날짜 변경 버튼을 앞뒤를 같은 class 를 활용한 것 좋은 것 같습니다!

Comment on lines +46 to +50
const dateStr = useMemo(() => dateToStr(currentDate), [currentDate]);
const todos = useMemo(
() => todosByDate[dateStr] || [],
[todosByDate, dateStr]
);

Choose a reason for hiding this comment

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

useMemo를 사용한 것 좋은 것 같습니다!
다만 컴포넌트가 분리되어 있다면 useMemo를 사용하는 의미가 훨씬 클 것 같습니다

Copy link
Member

@lemoncurdyogurt lemoncurdyogurt 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에 대해서 익혀보시고, 리팩토링해보셨으면 좋겠습니다!

Copy link
Member

Choose a reason for hiding this comment

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

컴포넌트화가 되어있지않고, vanilla.js처럼 모든 로직이 한 파일에 들어있어서 재사용성 면이나, 가독성면에서 떨어지는 것같은 특징이 존재합니다. 첨부링크는 토스에서 컴포넌트화하면 좋은 이유에 대해서 만든 강연이니 참고해서 봐보시면 좋을 듯 합니다

https://www.youtube.com/watch?v=fR8tsJ2r7Eg

Comment on lines +36 to +40
const [nextId, setNextId] = useState(() => {
const savedId = localStorage.getItem('nextId');
const n = parseInt(savedId || '1', 10);
return Number.isNaN(n) ? 1 : n;
});
Copy link
Member

Choose a reason for hiding this comment

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

nextId초기값을 1로 설정하면서, 나중 addTodo함수에서 setNextId((n) => n + 1);이렇게 계속 증가만 시키는데 이렇게 관리하게 되면 id키값이 불필요하게 커지게 되는 이슈가 존재합니다.

https://yozm.wishket.com/magazine/detail/2634/
주완님 PR에 있는 내용인데, 이렇게 key를 index로 관리할 때의 안되는 이유에 대해서 잘 설명이 되어있으니까 한 번 참고해보세요!

const totalCount = todos.length;
const completedCount = todos.filter((t) => t.completed).length;
const todayStr = dateToStr(new Date());
const prefix = dateStr === todayStr ? '오늘' : dateStr;
Copy link
Member

Choose a reason for hiding this comment

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

prefix라는 변수명보다는 날짜를 담는다는 의미의 변수명이 좋을 듯합니다!

Copy link
Member

Choose a reason for hiding this comment

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

color 속성 지정의 종류에는 색상명그대로 사용하거나, 16진수, RGB등이 있는데 이 방식을 둘 중에 하나로 통일해줘도 코드의 가독성 면에서 좋은 코드가 될 수 있어요

Copy link
Member

Choose a reason for hiding this comment

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

styled-component를 사용하지 않은점에서 굉장히 아쉬웠지만, 커스텀태그와 함께 스타일링을 하다보면 구조화가 잘된다는 장점이 존재하는 것 같습니다. 코드리뷰 리팩토링과 함께 사용해보시면 좋을 듯 합니다.
https://opencollective.com/styled-components/updates/thank-you
https://theinnovators.zone/archives/4218

추가적으로 styled-component의 경우 이제는 유지 관리 모드로의 전환이 된다고합니다. tailwind.css도 같이 익혀보는 걸 추천드립니다! (+개인적으로 코드 스타일 작성하는 속도가 비약적으로 빨라서 저는 선호하는 편)

</header>

<section className="todoInputSection">
<form className="todoForm" id="todoForm" onSubmit={addTodo}>
Copy link
Member

Choose a reason for hiding this comment

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

현재 form 태그를 통해 데이터를 전송하는 방식으로 택하고 있는데, 이것은 버튼 클릭시 브라우저가 새로고침되는데, SPA방식에서는 불필요한 동작이라 form태그 사용안하는 것을 추천드립니다.

추가적으로 input만 사용하게 된다면 엔터키를 통한 데이터 전송이 어려워서 addEventListener keydown을 통해서 등록되도록 처리도 해야합니다.

  • 한글은 조합문자라서 enter키를 통해 이벤트 발생 시 이벤트가 두 번 발생되니, isComposing으로 해결하면 좋습니다!

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