Skip to content

Conversation

@D5ng
Copy link
Contributor

@D5ng D5ng commented Nov 30, 2024

고민한 것.

  • 아티클에서는 setup이라는 함수로 기본 상태를 설정하는데, 리액트의 클래스형 컴포넌트처럼 state를 constructor에서 지정하고 싶었지만, 초기화 관련한 문제로 해결하지 못했음...
  • mounted라는 네이밍이 어색한 것 같아, 클래스형 컴포넌트의 생명주기 메서드인 componetDidMount로 변경
  • 타입스크립트를 사용하면서 타입 추론을 할 수 있도록, DOM 관련 타입들을 찾아봄, 조금 더 타입스크립트 답게 작성하려고 고민함. (Component 클래스 경우, 리액트의 클래스 컴포넌트의 타입과 유사하게 구현함)
  • this.state의 값을 언제든 변경할 수 있다는 문제가 확인되어, private 접근 제한자와 getter, setter를 사용해서 캡슐화 하였음. (React에서 상태를 읽기만하는것과 특정 메서드로 변경하는 것처럼 흉내냄)
  • 기존 아티클에서 사용하는 코드와 다르게 작성함. 최대한 선언적인 메서드를 활용하였음

배운 점.

  • 상태 관리 동작 원리를 이해할 수 있었다 (state -> setState -> render)
  • 상태 관리를 사용하지 않고 만들어 본 것과 상태 관리를 사용한 것에 대한 차이를 이해할 수 있었다. (상태 관리가 추후 유지보수에 더 좋다는걸 체감했음)
  • class 컴포넌트와 함수형 컴포넌트의 생명주기에 대해 추측할 수 있었음.

아티클의 코멘트를 보면 현재는 렌더링 성능이 안좋다고 나와있다. 그래서 개발자 도구를 활용해서 찾아보니, 모든 DOM들이 렌더링되는 문제를 발견했다. 현재 코드는 상태를 변경하면 모든 컴포넌트가 마운트되기 때문이였다. 추후에 Virtual DOM을 만드는 방법을 학습한다면 이 문제를 해결할 수 있을것 같다.

현재 코드의 문제점.

  • mounted로 인해 인스턴스가 새롭게 생성된다는 단점이 있음. 이를 어떻게 개선할 수 있을지 고민중.. [2024-12-06]

논의

  1. class형 컴포넌트의 생명주기와 함수형 생명주기는 왜 다를까 ?

내 생각: 클래스는 인스턴스를 생성하기 때문에 해당 컴포넌트의 실행 시점을 제어할 수 있다. 반면에 함수형은 함수가 호출되고 종료되면 소멸되기 때문에 클래스형 컴포넌트와 같이 다양한 생명주기를 갖는건 힘들지 않을까? 라는 추측을 한다.

  1. class에서 클로저와 비슷한 상태관리를 어떻게 만들 수 있을까 ?

[2024.12.02] 추후에 논의 더 추가될 수 있음.

@D5ng D5ng added the 진행중 label Nov 30, 2024
@D5ng D5ng self-assigned this Nov 30, 2024
@D5ng D5ng changed the base branch from main to donghyun November 30, 2024 16:00
@D5ng D5ng changed the title [동현] Web Component 진행중 [동현] Web Component Dec 1, 2024
@D5ng D5ng added ✨ Feat Feature and removed 진행중 labels Dec 1, 2024
@D5ng D5ng requested a review from Seoin02 December 1, 2024 14:38
@@ -0,0 +1,50 @@
interface ComponentOptions<TElement = HTMLElement, Props = any, State = any> {
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
Contributor Author

Choose a reason for hiding this comment

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

맞아요! 이건 수정되기 전 파일이라서 수정된 파일에는 조금 더 타입을 좁혔습니다!


export default class TodoList extends Component<HTMLUListElement, TodoListProps> {
template(): string {
const { todos } = this.props!
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
Contributor Author

Choose a reason for hiding this comment

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

이건 Non-null 단언 연산자 라고 해서 해당 값이 undefinednull이 아니라는 뜻입니다

this.componentDidMount()
}

componentDidMount() {}
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
Contributor Author

Choose a reason for hiding this comment

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

의미에 맞는진 아직 잘 모르겠네요,, 더 공부를 해봐야 정확하게 판단이 내려질것 같습니다


componentDidMount() {}

addEvent(eventType: keyof HTMLElementEventMap, selector: keyof HTMLElementTagNameMap | string, callback: EventListener) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

굿

import Component from "../core"

export default class TodoInput extends Component<HTMLDivElement> {
template(): string {
Copy link
Collaborator

Choose a reason for hiding this comment

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

여기도 타입을 지정했군요?? 근데 string 타입인가요??

Copy link
Contributor Author

Choose a reason for hiding this comment

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

template은 템플릿 리터럴을 사용하는 것이기 때문에 반환 값을 string 타입으로 한거였어요. 사실 일부러 작성한 것 보다는 기존 Component에 타입이 정의되어 있어서 자동완성할 때 저렇게 되네요!

export default class TodoInput extends Component<HTMLDivElement> {
template(): string {
return `
<form>
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
Contributor Author

Choose a reason for hiding this comment

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

수정하겠습니다!

}

setEvent(): void {
this.addEvent("click", "#toggle-button", (event) => {
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
Contributor Author

@D5ng D5ng Dec 7, 2024

Choose a reason for hiding this comment

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

클래스는 어디서든 사용할 수 있도록 하는 목표가 있지만, 여기에선 굳이? 싶어서 아이디로 사용했습니다. 그래도 확장성을 생각한다면 클래스로 가는것이 더 맞겠네요

@@ -0,0 +1,67 @@
type ComponentInternalRecord = Record<string, any>
Copy link
Collaborator

Choose a reason for hiding this comment

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

이렇게 아래 interface에 바로 선언하지 않고 타입을 선언해서 사용한 이유가 뭔가요?

동현님의 인터페이스와 타입을 사용하는 기준이 궁금합니다

Copy link
Contributor Author

@D5ng D5ng Dec 7, 2024

Choose a reason for hiding this comment

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

인터페이스를 사용하지 않은 이유는 확장을 할 필요가 없기 때문이였어요. 만약 인터페이스를 사용한다면 아래처럼 작성하게 되는데요.

interface ComponentInternalRecord extends Record<string,any>{}

이미 Record<string, any>이기 때문에 확장을 하는게 의미가 없다고 생각했어요. 따라서 type을 사용하는게 더 명확하지 않을까? 라는 생각을 했습니다

> {
target: TElement
props?: Props
private _state?: State
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
Contributor Author

Choose a reason for hiding this comment

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

불변성이라기 보다, 외부에서 값을 접근할 수 없도록 하기 위함입니다!


addTodo(title: string) {
const newTodo = {
id: Date.now(),
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
Contributor Author

Choose a reason for hiding this comment

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

사실 이거는 굉장히 안좋습니다 ㅋㅋㅋㅋㅋㅋ 왜냐하면 id는 유일해야하는데 겹칠 수 있어요. 이런 것도 더 고민을 해봐야겠네요

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ Feat Feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants