문제의 DOM API?

gyomni·2022년 6월 7일
2

Week I Learned

목록 보기
13/20
post-thumbnail

문제가 많은 DOM API 🧐

웹 어플리케이션에 있어서 가장 많은 문제를 일으키는 요소는
DOM이라고 하는 API라고 할 수 있다.

DOM API라고 하는 것은
html문서를 브라우저가 rendering하기 위해서,
그리고 그 안의 많은 것들을 작동 시키기 위해서 가공 시켜놓은 객체를 통칭한 것으로 DOM API 혹은 DOM이라고 부르기도 한다.

DOM APIJavascript를 이용해서 웹 앱에 UI를 핸들링할 수 있는 유일한 방법이므로 매우 중요하다.
그래서 실제로 모든 웹 앱이 DOM API를 다 사용하게 된다.
그런데, 문제는 DOM API를 다루기가 많이 까다롭다는 것이다.

DOM API 많은 기능을 제공해주고, 모든 것을 다 할 수 있게 해주지만,
웹 앱을 만드는데 최적화된 형태로 되어 있지는 않다.
왜냐면 애초의 목적이 웹 앱을 만들게 설계된 것이 아니였기 때문!


SPA(Single-page application)

html은 원래 문서이다.
링크를 통해 다른 html로 이동하면 기존 html문서는 사라지고 새로운 html이 로딩되는 형태가 바로! WWW(world wide web)이라고 하는 형식이다.

그런데, html문서와 html문서를 이동할 때 화면이 깜빡이게 된다. 왜냐하면 기존 문서를 없애고 새로운 문서를 로딩해야 하기 때문!
또한, 그 안에서 Context(맥락)이 있다거나, 맥락이 사라지고 등등 여러가지 이슈들이 있다.

이 상황들을 애플리케이션이라는 관점에서 보게 된다면?
애플리케이션의 특성상 화면을 여러개 가지게 되는데,
이 화면 단위가 페이지였다면 화면이 매번 깜빡거리며 넘어가게 된다.
리로딩되기 때문에 이런 문제가 생기게 된다.

여러가지 화면으로 구성되어 있는 웹 페이지가,
페이지가 아닌 애플리케이션으로 접근하게 된다고 하면
깜박인다는 것은 앱을 사용할 때의 사용성은 나오지 않는다는 문제가 있다.

그래서 10여년 전 쯤!
AJAX를 이용해 동적으로 htmlJavascript를 통해 읽어 들여서
화면 페이지 전환없이 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 APIreturn값은 다 참조형이구나?
라고 이해하고 주의하면 된다지만, 이건 큰 오산!!
아래의 예시를 보게 되면,,,


[ 예시 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

h1query하는데, getElementsByTagName으로 가져오는 것이 아니라, querySelectorAll로 가져오면, H1.length는 2다.
또한, getElementsByTagName로 가져온 h1.length는 2다.

그리고, 다시 h1을 추가하게 되면 h1.length는 3이 되지만, H1.length는 2가 된다. 두개가 다르다...!

똑같이 DOM API를 이용해서 query해 왔는데, 어떤 것은 참조를 계속 갖고 있고, 어떤 것은 참조를 갖지 않고 있고...일관성이 없음을 볼 수 있다..😂

예시들의 내용을 정리해보자.

콘솔에서 보면
h1HTMLCollection이고, H1NodeList인 것을 알 수 있다.

다시 봐도 일관성이 없다...!

어떤 Query API(querySelectorAll)는 NodeList를 부여하고,
또 어떤 Query API(getElementsByTagName)는 HTMLCollection이라는 객체를 부여하고.. HTMLCollection는 라이브 오브젝트이고, 어떤 것은 라이브 오브젝트가 아니라 참조가 끊기고..

이런 일관되지 않는 동작들이 DOM API는 굉장히 많이 있다.
이런 것들을 하나하나 신경쓰며 사용해야하고,
또 나아가서 보면 많은 브라우저들의 환경이 다를 것이고..
(표준을 따르는 브라우저도 많지만, 그 안에서도 다른 동작들을 가지고 있다.. Can I use (브라우저의 작동 범위, 지원 알아보기) )

개발자들이 웹 앱 하나를 만들면서 이런 많은 사항들을 모두 체크하고 확인하고...,
변경하려는 것이 어느 범위까지 서포트되는지, 만들고 있는 제품이 어떤 브라우저에서 실행 될 건지를 모두 점검한다는 것은 아주 고통스러운 일이 될것이다..😵

이런 Cross browsing이슈뿐만 아니라, DOM API문제점은 더 있다.
서두에서 얘기했듯이 SPA라는 것은 하나의 어플리케이션이므로 규모가 커지면 커질수록 복잡도가 굉장히 증가하게 된다. 웹 페이지처럼 화면이 바뀌면 모든 게 다 reload되어 새로 갱신되고, 해당 화면에서만 다루는 상태를 다루는 코드만 격리되어 있지 않다.

즉, 모든 화면에 들어가 있는 다양한 데이터(상태)들을 모두 애플리케이션 단위에서 유지 관리해야하므로, 위의 예시코드에서 봤듯이 참조 무결성의 원칙들이 위배되거나, 혼란미묘하게 작동되는 것들은 다양한 버그를 일으킬 수 있는 가능성을 가지고 있다고 할 수 있다.

애플리케이션을 개발할 때 이런 문제들을 마주하다보면,
규모가 커져도 복잡도를 낮출 수 프로그래밍 패턴은 뭐가 있을까를 고민하게 된다.
좀 살펴보자면,

소프트웨어 디자인 패턴

모델-뷰-컨트롤러 (model-view-controller, MVC)


성격이 다른 것들( UI요소, 비즈니스 로직, 데이터...)이 뒤섞여 있으면 복잡도가 높아지니,
이것들을 분리해서 복잡도를 낮춰보자는 패턴이다.
(비슷한 것들 끼리 모아 놓으면 복잡도가 낮아지니까!)
어떤 형태로 분리할 것인가?

  • 모델
  • 뷰 = UI
  • 컨트롤러 = 모델과 뷰 사이 간에 연결성 로직들을 갖고 있는 컨트롤러 로직 분리

각각 성격이 다른 것들을 분리해서,
규모가 커지게 되더라도 이런 패턴 안에서 규모가 커지기에 복잡도가 더 증가하지 않도록!

요즘 들어서는 클라이언트 애플리케이션들의 로직들이 훨씬 더 많아지고 뷰들도 많다 보니,
MVC 패턴 같은 경우에는, 모델이 서버 모델과 종속성을 많이 갖고 있게 된다.
-> 서버가 바뀌면 클라이언트도 많은 영향을 받게 되는 단점을 가지게 된다.

이러한 이유로 클라이언트에 더 알맞는 패턴이 있었으면 좋겠다!고 해서 나온 패턴이 바로! MVVM패턴이다.

모델-뷰-뷰모델 (Model-View-ViewModel, 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이 가지는 문제점들을 해결하진 못 해준다. 규모가 커지면 복잡도도 따라 올라갈 수 밖에 없고...

그런데! ReactDOM자체를 쓰지 않는다는 컨셉을 냈다..!!
핵심만 보자면, DOM이 문제니, DOM을 쓰지 말자는 것이다.
이런 컨셉이 성공적으로 안착되며 웹 애플리케이션 개발 패러다임을 많이 바꿔 놓았다.
이 부분에 대해서 계속 공부해보자 👻👻

profile
Front-end developer 👩‍💻✍

0개의 댓글