데브코스-TIL-day13-todolist와 컴포넌트적 접근

조주영·2021년 8월 18일
0

데브코스-TIL

목록 보기
13/34

간단한 todo list app만들면서 컴포넌트 방식으로 처음 접근 해보았다. 나는 컴포넌트의 정의도 잘 몰랐고, 장점은 당연히 몰라서 오늘은 정말 새로웠다!

feat.(client side에서 데이터 저장하기)

컴포넌트?


출처

컴포넌트(Component)란 프로그래밍에 있어 재사용이 가능한 각각의 독립된 모듈을 뜻한다.

그림에서 확인 할 수 있듯이 컴포넌트 기반 프로그래밍을 하면 마치 레고 블록처럼 이미 만들어진 컴포넌들을 조합하여 화면을 구성할 수 있다.

웹 컴포넌트는 이러한 컴포넌트 기반 프로그래밍을 웹에서도 적용할 수 있도록 W3C에서 새로 정한 규격이다. 웹 표준을 기반으로 구축되었으며, 최신 부라우저 및 모든 JavaScript 라이브러리, 프레임워크에서도 사용할 수 있다.

따라서 웹 컴포넌트를 이용하여 코드를 작성하면 Vue.js 나 React.js 와 같은 라이브러리, 프레임워크에 의존하지 않고 상호 운용이 가능하게끔 작성할 수 있다.

하면 뭐가좋을까?

동작이 독립적으로 돌아가기 위한 생각을 한다
->
컴포넌트가 잘 나눠져있으면, 유지보수하기가 쉬워진다

js로 구현한 todo list를 통해 알아보자!

todo list를 화면에 띄우기 위하여, todolist.html을 기준으로, todolist.js,과 이를 띄워주기 위한 todoform.js을 이용하여

다음과 같은 화면을 만들어 보겠다!

그냥구현

화면을 만들때,
todolist.js과 이를 띄워주기 위한 todoform.js을 이용하여 todolist가 todoform안에서 조작되고(서로가 영향을 받는다), main.js에서 헤더와 같이 객체를 만들어 만든다면, 이는 컴포넌트 방식이라고 할수 없다.!
물론 구현이 되었다면 제대로 동작 하겠지만, 기능 확장 및 추가, 등 유지보수가 쉽지 않을 것이다.

그렇다면 컴포넌트 방식은?

밑에와 같은 그림이 컴포넌트식 접근!

이렇게 todo list 들을 화면에 띄우기 위해
todolist.js과 todoform.js, header.js, main.js, 마지막으로 app에 필요한 구성을 모아놓은 app.js 를따로 이용하여, 서로가 영향을 주지 않도록 독립적으로 구현하는 것이다,

구간을 나누어 독립적으로! ex)코드

main.js

const data=[{
  text='블로그 작성하기'
},
 {
  text='프로그래머스 문제풀기'
}]
const $app = document.querySelector('.app')
//app컴포넌트들이 어디에 들어갈지 
new App({
    $target: $app,
    initialState:data
})

app.js

function App({$target,initialState}){
    new Header({
        $target,
    text:'Simple Todo list'
})
    new TodoForm({
        $target,
        onSubmit:(text)=>{
            const nextState = [...todoList.state,{
                text
            }];
            todoList.setState(nextState)
            //로컬스토리지에 추가
            storage.setItem('todos',JSON.stringify(nextState))
        }
    })

    const todoList=new TodoList({
        $target,
        initialState
    })
}

header.js

function Header({ $target, text}){
    const $header = document.createElement('h1')

    $target.appendChild($header)

    this.render=()=>{
        $header.textContent=text
    }

    this.render()
}

todoform.js

function TodoForm({$target,onSubmit}){
    const $form = document.createElement('form')

    $target.appendChild($form)
    let isInit =false

    this.render = ()=>{
        $form.innerHTML = `
        <input type="text" name="todo"/>
        <button>Add</button>
        `
        //이벤트를 해야한다.
        if(!isInit){
        $form.addEventListener('submit',e=>{
            e.preventDefault()//태그의 기본동작을 끈다
            const $todo=$form.querySelector('input[name=todo]')
            const text=$todo.value
            if(text.length>1){
                $todo.value=''
                onSubmit(text);
            }
            $todo.value=''

        
        
        })
        isInit=true
    }
    }

    this.render()

}

todolist.js

// params.$target - 해당 컴포넌트가 추가가 도리 dom 엘리먼트
// params.initialState - 해당 컴토넌트 초기상태

function TodoList({$target, initialState}){
        //$는 돔객체를 포함하고있는 변수다.
        //todoListElement로 대체가능

    const $todoList=document.createElement('div');//일종의 컨테이너?컴포넌트의 돔.
    this.state = initialState;

    this.setState=nextState=>{
        this.state=nextState
        this.render()
    }//현재의 상태를 nextstate로바꾸고 render를 다시 호출한다
    

    //const $target = params.$target;//타켓에 돔에 잘 넘겨준다.
    $target.appendChild($todoList);
    

    this.render=()=>{//컴포넌트를 그린다.
        //this.state =[{text: '자바스크립트 공부하기'}.{text:'....'}]
        // map을 돈 이후에는 아래처럼 만들어진다.
        //['<li>자바스크립트 공부하기</li>', '<li>....</li>']
        //join('')을 하면 
        //'<li>자바스크립트 공부하기</li><li>....</li>'
        $todoList.innerHTML = `
        <ul>
            ${this.state.map(({text}) =>`<li>${text}</li>`).join('')}
        <ul>` 
           
    }
    this.render();//컴포넌트를 생성한거를 실행
}

앞서 구현한 방법으로는, 새로고침을 하면 add했던 데이터들이 다 날아 간다. 따라서 기억을 해 놓는 방법이 필요하다. 여기선 두가지 방식을 소개 하겠다.

쿠키

쿠키는 브라우정 저장되는 작은 문자열로
rfc 6265 명세에서 정의한 http프로토콜의 일부
다른 저장 방법에 비해 오래된 방식

cookie추가하기

document.cookie=language=javascript

덮어쓰지않고 새로추가함

쿠키 읽어 오기

const cookies = document.cookie

각 쿠키는 ;로 구분되어 있어 불러온 후 split 등으로 쪼개서 써야 한다.

cookie 유효기간 넣기
ex)오늘하루 보지않기, 1주일간 보지 않기 등

document.cookie - 'user=cho; expire=fri, 18 Aug 2021 16:19:38 GMT'

우리 나라 시간 기준이 아니라서, 시간을 받아와야 한다.

new Date().toGMTString()

cookie 사용시 주의사항

  • http 요청시 헤더에 쿠키가 같이 나가기 떄문에 쿠키 사이즈가 커지면 http 요청 크기도 커집니다.
  • 사이즈에 제한이 있습니다.
  • 여러가지 보안 취약점을 조심해야 합니다.

로컬스토리지

local storage

  • key value 기반으로 local에 데이터를 저장 할 수 있다.
  • 도메인 기반으로 storage가 생성이 된다.
    도메인만 같다면, 여러탭 내에서 같은 storage가 공유된다.
  • 삭제하거나 storage를 날리지 않는 한 삭제되지 않는다.

local storage값을 저장하는 방법 세가지

window.localStroage.name='cho'
window.localStroage['name']='cho'
window.localStroage.setItem('name','cho') // key value값
string이기 때문에 숫자를 넣어도 string이고 
배열도 string으로 바꿔서 넣어야 한다

이 있지만, setItem을 이용해 사용하는것이 권장된다.
왜? property를 수정하는 식으로 하면 length, toString 같은 내장 함수들을 덮어 씌울 수 있기 때문이다.

const user ={
	name:'cho;,
    position:'centerforward'
    team:['fc seoul ']
    }
localStrorage.setItem('user', JSON.stringfy(user))//제작

//불러오기
const stordName=JSON.parse(localStrorage.getItem('name'))

localstroge에는 string만 넣을 수 있기 때문에
json.strignfy로 넣고 json.parse로 꺼내야 한다.
안하면 object라고 뜬다!!

Session Storage

전체적으로 local Storage와 같다.
딱하나 다른건,
브라우저를 닫으면 저장된 내용이 날라간다.
ex)임시값들이 필요할때, api 세싱같은것이 있다!!
상황에 따라 로컬 세션을 골라라!

로컬스토리지 방식으로 구현

const initialState=JSON.parse(localStorage.getItem('todos')|| '[]')
storage.js

일반적으로 main.js에 localStorage를 이용해서 사용해도 되지만, 직접적으로 구현을 하는것이 더 안전하다.
이는 여러가지 이유가있는데,
외부 툴 등을 이용해 todos json string을 올바르지 않은 형태로 바뀌면 어떻게될까??
=>실행이 안된다.
storage.js를 만들고 여기서만 local에 접근하도록 만드는것이 안전하다.!

storage.js

const storage =(function(storage){
    const setItem =(key, value)=>{
        try{
            storage.setItem(key,value)
        }
        catch(e){
            console.log(e) 
        }
    }
    const getItem = (key, defaultvalue)=>{
        try{
            const storedValue=storage.getItem(key)

            if(storedValue){
                return JSON.parse(storedValue)
            }
            return defaultvalue

        }catch(e){
            console.log(e)
            return defaultvalue
        }
    }
    return{
        setItem,
        getItem
    }
})(window.localStorage)

이렇게 되면, main.js와 app.js가 아래와 같이 된다.

app.js

function App({$target,initialState}){
    new Header({
        $target,
    text:'Simple Todo list'
})
    new TodoForm({
        $target,
        onSubmit:(text)=>{
            const nextState = [...todoList.state,{
                text
            }];
            todoList.setState(nextState)
            //로컬스토리지에 추가
            storage.setItem('todos',JSON.stringify(nextState))
        }
    })

    const todoList=new TodoList({
        $target,
        initialState
    })
}

main.js

//const initialState=JSON.parse(localStorage.getItem('todos')|| '[]')
const initialState=storage.getItem('todos',[])
//새로고침하면 삭제되므로, local storage에서 꺼내게 합시다!
//일단은 잘동작하지만 위험하다. 
//외부 툴 등을 이용해 todos json string을 올바르지 않은 형태로 바뀌면 어떻게될까용?
//실행이 안된다.  
//storage.js를 만들고 여기서만 local에 접근하도록 만든다.
const $app = document.querySelector('.app')
//app컴포넌트들이 어디에 들어갈지 
new App({
    $target: $app,
    initialState//:data
})


// setTimeout(()=>{
//     todoList.setState([{
//         text:'happy',
        
//     }])
// },5000)
//todolist라는 변수로 받고 이걸 테스트함

결과


local storage에 잘들어간 것을 볼수 있다.!

느낀점

새로배운것:

  • 설계 할때 컴포넌트를 잘 이용, 및 장점

  • 로컬스토리지의 실 사용

느낀것:

  • 코어근육(기본기)를 다지는게 얼마나 중요함
    물론 아직 프레임 워크를 써보진 않아서 크게 와닿는것은 아니지만, 강의내용중 프레임워크에 영향을 받지 않을 정도라니 기본기를 더욱더 잘 쌓아 유연한 개발자가 되어야 겠다.

  • 이론으로만 배웠던 스토리지를 써본 후..
    확 와닿았다. 쿠키와 세션도 직접 한번 구현해서 써봐야겠다는 생각과
    함께... 끝!

profile
꾸준히 성장하기

0개의 댓글