프로그래머스 자바스크립트 스터디 Mission2 리뷰

Bor·2021년 11월 5일
0

Mission2의 내용은 1주차에 했던 TodoList에 흔히 CRUD라고 우리가 부르는 리스트에 항목 추가하기, 완료처리, 삭제, 이에 따른 렌더링을 바닐라JS 구현해서 투두리스트의 기본 뼈대를 잡는 내용이었다. 아래의 구체적인 커피 비유는 제가 이해를 하면서 덧붙인 내용입니다.

그렇다. 과거의 보람은 투두리스트를 만들 때 하나의 JS에서 모든 처리를 다 해줬다. 그래서 코드가 보통,

function TodoList($target, data){
    const a  = document.createElement('input')
    this.이곳. appendChild('input')
    const b = document.createElement('div') 
    this.저곳. appendChild('div')

    이곳.addEventListener('keyup',e =>{	
	뭔가를 해줘! 
	}
}

이런 하나의 파일 안에 다양한 기능들이 존재했다. 그러나 이렇게 구현할 경우에는 TodoList가 할 일이 너무 많아진다. 이후에 만약 자동완성, 입력 변경 방식 등을 변경시켜줘야 할 때는 기능 별로 의존성이 너무 높아졌기 때문에 유지/보수하기가 까다롭다. 마치 에스프레소 머신이 옆에서는 탄산수가 나오기도 하고 아래에서는 또 얼음도 나온다면..? 기계도 엄청 커지고 탄산수를 만드는 곳이 고장이 났는데 커피가 안나오고, 얼음도 안 나올 수도 있다. 그래서 이 친구들에는 담당한 일만 부여해야 한다.

function TodoList({$target, initialState}){

    const도 div만 

     this.render = function(){
     innertHTML으로 가져오고 업데이트
     }

      이벤트 리스너는 삭제 

      this.render()

}

훨씬 간결해졌다. 그런데 이렇게 컴포넌트 단위로 작성을 할 때는 클론 코딩을 하며 내가 왜 그런 이름이 붙었는지도 몰랐던 App.js를 생성해줘야 한다. 지금까지는 App.js를 본디 의미를 살려서 써본 적이 없었음을 느꼈다. 앞서 말했던 에스프레소 머신, 탄산수, 제빙기는 서로 몰라야 하며 다만 서로가 필요해질 때 호출만 해주는 정도이며 자세하게 서로가 어떻게 얼음을 만들고 커피를 추출해주는지는 알 필요가 없다.

그래서 이들을 가운데서 물(데이터)의 흐름을 조율해주는 역할이 바로 App.js이다. 그렇기 때문에 구체적인 동작에 대한 코드는 App.js에 구현을 하고 추상화를 한 형태만 각각의 TodoList, TodoInput 등의 컴포넌트에 실행을 해주었다.

import storage from './localStorage.js'
import TodoInput from './TodoInput.js'
import TodoList from './TodoList.js'
import TodoCount from './TodoCount.js'

export default function App({ $target }){
  
  this.setState = nextState => {
    ✔️ 상태를 업데이트 해주는 메소드로 
    ✔️ TodoInput, TodoList 등의 컴포넌트의 setState역시 이곳에서 실행 
    })
  }

  const todoInput = new TodoInput({
   ✔️ onAddTodo의 함수의 구체적인 내용 역시 이곳에서 구체적으로 작성해준다. 
  })

  const todoList = new TodoList({
    $target,
    initialState: this.state,
    ✔️ onTodoClick 의 구체적인 내용 
    ✔️ onRemove의 구체적인 내용
    
  const todoCount = new TodoCount({ $target, initialState: {
    ✔️ removeAll 등의 메소드 구현 
}

이렇게 App에서 구체적인 실행코드를 받아주게 되면 위에서 서술했던 것처럼 에스프레소 머신, 탄산수, 제빙기는 서로의 원리를 몰라도 실행이 가능하다.

export default function TodoInput({ $target, onAddTodo }) {
  const $todoInput = document.createElement('form')
  $target.appendChild($todoInput)
  this.onAddTodo = onAddTodo

  this.render = () => {
   ✔️ innerHTML을 통해 내용을 render해주는 함수 
  }

  this.render()

  $todoInput.addEventListener('submit', (e) => {
   ✔️ e.preventDefault() 

	(중략)
      this.onAddTodo(value)
      // 이곳에서는 this.onAddTodo를 실행만 시켜주면 된다. 
  })
}

이 부분에서 가장 크게 배운 것은 컴포넌트를 요소별로 쪼개는 것도 있지만 form으로 감싸주는 부분이었다. 기존에 target으로 input을 가져오는 경우에는 이후에 엔터와 클릭 이벤트를 두 번 처리를 해줘야 했다. 하지만 form으로 감싸면 submit으로만 관리가 가능해지며 마크업 구조 역시 더 시멘틱해진다. 로토님의 디테일을 배울 수 있는 부분이었다!! 디테일과 관련해서는 이것 외에도 로컬스토리지에서 데이터를 처리할 때도 메모리 관리를 위해서 예외처리를 해주는 것도 인상 깊었다.


나의 코드 & 코드리뷰

스터디를 하면서 가장 좋은점 중 하나는 바로 코드 리뷰이다. 로토님, 루카스님, 에디님으로부터 받는 리뷰도 좋지만 함께 스터디하는 분들에게 받는 리뷰와 코멘트 역시 무척 소중하다. 직접 이번에 미션을 하면서 겪은 시행착오와 또한 이 부분을 공부를 하며 느꼈던 점들이 고스란히 담겨 있기 때문이다.

#index.html 

<html>

<head>
    <title>Mission 2</title>
    <meta charset="utf-8" />
</head>

<body>
    <h1>🚀 투두 리스트 🚀</h1>
    <div id="app"></div>
    <input id="input-box" type="text">
    <button id="btn-submit" type="submit">+</button>
    <ul id="todo-list"></ul>

이부분에서는

재사용가능한 컴포넌트 형식으로 코딩을 하기 위해선 해당 컴포넌트에 마크업 부분이 들어가야 될 것 같아요. 예를 들어 input 태그는 TodoInput.js 파일안에서 정의하면 좋을 것 같습니다 :) 그리고 하나의 app 태그안에 모든 컴포넌트가 위차하게 하시면 좋을 것 같습니다

와 같은 피드백을 받았다. 지금까지 html에 마크업을 하고 자바스크립트로 가져오는 경우가 많았다. 그러나 createElement로 작성을 해야 컴포넌트 형식으로 코딩도 가능했고 재사용하기도 용이했다. 실제로 코딩을 해보기 전까지는 "왜 저렇게 할까?" 궁금했지만 실제로 코드를 짜고 돌려보니 서서히 이해를 할 수 있었다.

   this.savingLocal = (newUserInput) => {
        localStorage.setItem('localstorage', JSON.stringify(newUserInput));
    }

지금은 상관없지만 이 부분은 유틸함수로 외부함수로 빼주셔도 좋지 않을까 생각됩니다 :) 좀 더 큰 범위에서 사용될 수 있을 것 같아요.

key 이름이 localstorage인데, getItem으로 꺼내 사용되는 부분이 없어서 어떤의도인지 모르겠으나, 다른 키값이 들어가야하지 않을까요?
이름이 newUserInput이라 string이 input text가 들어올 것 같았는데, todo가 들어오는 것 같군요. 지금 구조에서 파라메타로 newUserInput을 안받고 this.data를 직접 넘겨도 될 것 같군요.

가장 많은 코멘트를 받은 부분이었다. 이 부분은 유틸함수로 분리하고 또한 key값으로 받아오는 부분 역시 공부를 더 해보고 또 다른 분들의 코드를 보면서도 배워봐야겠다.

이외에도 변수명에 대한 코멘트도 많았다. 변수명을 정하는 규칙도 그렇지만 이 컴포넌트가 정확히 어떤 역할 하는지 몰라서 이름을 잘못 짓는 경우가 많았다. 조금 더 컴포넌트 분리와 역할에 대한 이해를 쌓아야겠다고 반성하는 계기가 되었다.

0개의 댓글