DOM API
🧐웹 어플리케이션에 있어서 가장 많은 문제를 일으키는 요소는
DOM
이라고 하는 API
라고 할 수 있다.
DOM API
라고 하는 것은
html
문서를 브라우저가 rendering
하기 위해서,
그리고 그 안의 많은 것들을 작동 시키기 위해서 가공 시켜놓은 객체를 통칭한 것으로 DOM API
혹은 DOM
이라고 부르기도 한다.
DOM API
은 Javascript
를 이용해서 웹 앱에 UI
를 핸들링할 수 있는 유일한 방법이므로 매우 중요하다.
그래서 실제로 모든 웹 앱이 DOM API
를 다 사용하게 된다.
그런데, 문제는 DOM API
를 다루기가 많이 까다롭다는 것이다.
DOM API
많은 기능을 제공해주고, 모든 것을 다 할 수 있게 해주지만,
웹 앱을 만드는데 최적화된 형태로 되어 있지는 않다.
왜냐면 애초의 목적이 웹 앱을 만들게 설계된 것이 아니였기 때문!
SPA(Single-page application)
html
은 원래 문서이다.
링크를 통해 다른 html
로 이동하면 기존 html
문서는 사라지고 새로운 html
이 로딩되는 형태가 바로! WWW(world wide web)
이라고 하는 형식이다.
그런데, html
문서와 html
문서를 이동할 때 화면이 깜빡이게 된다. 왜냐하면 기존 문서를 없애고 새로운 문서를 로딩해야 하기 때문!
또한, 그 안에서 Context(맥락)이 있다거나, 맥락이 사라지고 등등 여러가지 이슈들이 있다.
이 상황들을 애플리케이션이라는 관점에서 보게 된다면?
애플리케이션의 특성상 화면을 여러개 가지게 되는데,
이 화면 단위가 페이지였다면 화면이 매번 깜빡거리며 넘어가게 된다.
리로딩되기 때문에 이런 문제가 생기게 된다.
여러가지 화면으로 구성되어 있는 웹 페이지가,
페이지가 아닌 애플리케이션으로 접근하게 된다고 하면
깜박인다는 것은 앱을 사용할 때의 사용성은 나오지 않는다는 문제가 있다.
그래서 10여년 전 쯤!
AJAX
를 이용해 동적으로 html
을 Javascript
를 통해 읽어 들여서
화면 페이지 전환없이 UI
를 갱신하겠다 (깜빡임 없이, 일반적인 웹 페이지가 아니라 마치 애플리케이션을 사용하는 사용성을 제공하겠다)는 시도가 성공적으로 안착된다.
그래서 현재 웬만한 웹 페이지들은 SAP(Single-page application)
이다! 라고 할 수 있을 만큼 SAP
가 광범위하게 사용되고 있다.
-> React
,Vue
같은 라이브러리, 프레임워크를 이용해서 애플리케이션을 만드는 것들이 모두 SAP
를 만들고 있는 것!
여기서 잠깐~! SAP
의 많은 특징들 중, 복잡도에 대해 살펴 보자!
SAP
복잡도관리해야 하는 상태도 많고, 화면도 점점 많아져서 애플리케이션의 규모가 커질 수록 그 안에서 다뤄야 하는 UI
요소들이 굉장히 많아지게 된다.
복잡해지고 규모가 커질수록 DOM API
를 가지고 UI
를 만들면
여러 가지 문제들이 생길 수 있는 구성을 DOM API
가 제공해준다는 것이
가장 큰 문제라고 할 수 있다.
DOM API
문제점실제 애플리케이션을 만드는 관점에서 DOM API
가 갖고 있는 단점들은 정말 많을 것이다.
일단 간단한 코드로 문제점을 이해해보자!_!
(예시 코드들이 이어져 있다고 이해하고 보기)
[ 예시 1 ]
const h1 = document.getElementsByTagName('h1');
h1.length // 0
document.body.appendChild(document.createElement('h1'));
// <h1></h1>
h1.length // 1
document.body.appendChild(document.createElement('h1'));
// <h1></h1>
h1.length // 2
DOM API
가 반환하는 값이 라이브 오브젝트라는 컨셉을 갖고 있어서 위 예시 코드와 현상이 발생한다. 참조를 그대로 유지하고 있다.
이것을 코드상에서 핸들링한다면? 까다롭다...
[ 예시 2 ]
// `h2`를 먼저 만들어 본 다음
document.body.appendChild(document.createElement('h2'));
// <h2></h2>
// `h2`태그를 다시 query해보기
const h2 = document.getElementsByTagName('h2');
h2.length // 1
[ 예시 1 ]과 마찬가지로 참조를 갖고 있기에,
라이브 오브젝트기 때문에 이런 현상이 발생한다.
모든 상황이 위의 예시와 같다면 DOM API
의 return
값은 다 참조형이구나?
라고 이해하고 주의하면 된다지만, 이건 큰 오산!!
아래의 예시를 보게 되면,,,
[ 예시 3 ]
document.body.appendChild(document.createElement('h2'));
// <h2></h2>
h2.length // 2
// h1을 query
const H1 = document.querySelectorAll('h1');
H1.length // 2
h1.length // 2
document.body.appendChild(document.createElement('h1'));
// <h1></h1>
h1.length // 3
H1.length // 2
h1
을query
하는데,getElementsByTagName
으로 가져오는 것이 아니라,querySelectorAll
로 가져오면,H1.length
는 2다.
또한,getElementsByTagName
로 가져온h1.length
는 2다.그리고, 다시
h1
을 추가하게 되면h1.length
는 3이 되지만,H1.length
는 2가 된다. 두개가 다르다...!똑같이
DOM API
를 이용해서query
해 왔는데, 어떤 것은 참조를 계속 갖고 있고, 어떤 것은 참조를 갖지 않고 있고...일관성이 없음을 볼 수 있다..😂
예시들의 내용을 정리해보자.
콘솔에서 보면
h1
은 HTMLCollection
이고, H1
은 NodeList
인 것을 알 수 있다.
다시 봐도 일관성이 없다...!
어떤 Query API
(querySelectorAll
)는 NodeList
를 부여하고,
또 어떤 Query API
(getElementsByTagName
)는 HTMLCollection
이라는 객체를 부여하고.. HTMLCollection
는 라이브 오브젝트이고, 어떤 것은 라이브 오브젝트가 아니라 참조가 끊기고..
이런 일관되지 않는 동작들이 DOM API
는 굉장히 많이 있다.
이런 것들을 하나하나 신경쓰며 사용해야하고,
또 나아가서 보면 많은 브라우저들의 환경이 다를 것이고..
(표준을 따르는 브라우저도 많지만, 그 안에서도 다른 동작들을 가지고 있다.. Can I use (브라우저의 작동 범위, 지원 알아보기) )
개발자들이 웹 앱 하나를 만들면서 이런 많은 사항들을 모두 체크하고 확인하고...,
변경하려는 것이 어느 범위까지 서포트되는지, 만들고 있는 제품이 어떤 브라우저에서 실행 될 건지를 모두 점검한다는 것은 아주 고통스러운 일이 될것이다..😵
이런 Cross browsing
이슈뿐만 아니라, DOM API
문제점은 더 있다.
서두에서 얘기했듯이 SPA
라는 것은 하나의 어플리케이션이므로 규모가 커지면 커질수록 복잡도가 굉장히 증가하게 된다. 웹 페이지처럼 화면이 바뀌면 모든 게 다 reload
되어 새로 갱신되고, 해당 화면에서만 다루는 상태를 다루는 코드만 격리되어 있지 않다.
즉, 모든 화면에 들어가 있는 다양한 데이터(상태)들을 모두 애플리케이션 단위에서 유지 관리해야하므로, 위의 예시코드에서 봤듯이 참조 무결성의 원칙들이 위배되거나, 혼란미묘하게 작동되는 것들은 다양한 버그를 일으킬 수 있는 가능성을 가지고 있다고 할 수 있다.
애플리케이션을 개발할 때 이런 문제들을 마주하다보면,
규모가 커져도 복잡도를 낮출 수 프로그래밍 패턴은 뭐가 있을까를 고민하게 된다.
좀 살펴보자면,
성격이 다른 것들( UI
요소, 비즈니스 로직, 데이터...)이 뒤섞여 있으면 복잡도가 높아지니,
이것들을 분리해서 복잡도를 낮춰보자는 패턴이다.
(비슷한 것들 끼리 모아 놓으면 복잡도가 낮아지니까!)
어떤 형태로 분리할 것인가?
UI
각각 성격이 다른 것들을 분리해서,
규모가 커지게 되더라도 이런 패턴 안에서 규모가 커지기에 복잡도가 더 증가하지 않도록!
요즘 들어서는 클라이언트 애플리케이션들의 로직들이 훨씬 더 많아지고 뷰들도 많다 보니,
MVC
패턴 같은 경우에는, 모델이 서버 모델과 종속성을 많이 갖고 있게 된다.
-> 서버가 바뀌면 클라이언트도 많은 영향을 받게 되는 단점을 가지게 된다.
이러한 이유로 클라이언트에 더 알맞는 패턴이 있었으면 좋겠다!고 해서 나온 패턴이 바로! MVVM
패턴이다.
MVVM
의 경우는 클라이이언트 쪽에서 상태를 독립적으로 가지고 있고,
독립적 상태를 잘 유지 관리 할 수 있는 컨셉들이 들어 있는 패턴이다.
이 모델은 2005년에 제안된 모델이라고 한다!
MVVM
는 현재 많이 사용되고 있는 Framework(React
, Vue.js
, Angular
..)
같은 것들에 많은 영향을 미친 패턴이라고 할 수 있다.
React
가 제시한 모델??간략하게 알아본 이런 소프트웨어 패턴들은 결국!
클라이언트 애플리케이션들이 규모가 커지지만, 복잡도는 일정 수준으로 유지하기 위한 여러가지 방법의 하나이다.
이 패턴들이 말하는 뷰는 DOM
을 이용한 UI
요소를 다루는 것에 많은 부분 치중되어 있고, DOM API
자체 문제점을 개선해주지는 않는다.
그렇다면 DOM API
의 문제점을 개선시켜주는 모델은 무엇이 있을까??
현재까지 나온 것 중에서 가장 성공적인 것은 React
가 제시한 모델이라 할 수 있다고 한다~!~!
DOM
의 여러 가지 문제점들을 개선하기 위한 시도는 오래된 버전으로는 JQuery
가 있을 수 있다.
DOM
이 굉장히 까다로우며 Cross browsing
이슈도 많다 보니, 그런것들을 단순히 내가 만들어줄께! 라는 컨셉이 JQuery
의 모델인데, 이것도 기본적으로 DOM
을 쉽게 포장했을 뿐이지, 근본 적으로 DOM
이 가지는 문제점들을 해결하진 못 해준다. 규모가 커지면 복잡도도 따라 올라갈 수 밖에 없고...
그런데! React
는 DOM
자체를 쓰지 않는다는 컨셉을 냈다..!!
핵심만 보자면, DOM
이 문제니, DOM
을 쓰지 말자는 것이다.
이런 컨셉이 성공적으로 안착되며 웹 애플리케이션 개발 패러다임을 많이 바꿔 놓았다.
이 부분에 대해서 계속 공부해보자 👻👻