Javascript 의 클로저는 보통 Scope 와 같이 기술되는 특징적인 개념이다.

그 이유는 Closure 라는 개념이 Javascript 의 특징적인 Nested Scope 개념을 이용하기 때문이다.

 

다음 예제를 확인해보자.

 

위의 예제에서 함수 foo 는 innerFoo 의 실행 결과를 반환한다. outerFoo() 함수가 nestedFunction 을 return 해주고 있기 때문이다. 

이런 방식의 호출을 클로저(Closure) 라고 하며, 클로저로 정의된 innerFoo 함수는 외부 함수인 outerFoo 의 변수에 접근할 수 있기 때문에 Side effect 관리가 용이하며 정보 은닉(Private) 의 특성을 지닌다.

 

아울러 이렇게 정의된 outerFoo 는 innerFoo 를 위한 언어적 환경(Lexical environment) 를 제공하게 되기 때문에, 디자인 패턴적으로 높은 유연도를 가질 수 있게 된다. 

 

가령, outerFoo 를 innerFoo 를 위한 Factory 처럼 사용하거나 outerFoo 에 Parameter 를 받아 "독립적인 객체" 와 같은 환경을 만들거나 Singleton 처럼 사용할 수도 있다.

 

클로저의 중요한 특징 중 하나는 Scope Chain 을 이해하는 것이다.

근본적으로 Nested Scope 로 정의되는 Closure 는 3가지 종류의 Scope 를 가질 수 있으며 이를 순차적으로(Chaining) 접근하게 된다.

 

코드를 위와 같이 조금 변경해보았다.

 

(1) Local scope

 

(2) Outer function scope

 

(3) Global scope

 

위의 코드에서 Closure 는 위와 같은 3가지의 Scope 를 전부 가질 수 있으며,

동일한 이름의 변수에 대해서는 우선순위에 따라 다른 Scope 의 변수를 가리는(Hide) 모습을 볼 수 있다.

 

위와 같이 Closure 함수의 실행은 Scope 에서 Scope 로 전이되며 Scope 내에서 Scope 를 다시 선언하는 Scope chain 을 생성하는 과정이라 할 수 있다.

 

클로저를 이해하는 건 어렵지않으며, 중요한 것은 Scope chaining 을 이해하는 것이다.

 

주로 Javascript 의 유사한 동작을 패턴화 시키고, 그에 따른 독립적인 환경의 격리(private)가 필요할 때 사용하곤 한다.

 

 

다른 언어들과 마찬가지로 Javascript 역시 Scope 를 갖고 있으며, 이를 기본적으로 이해하는 것이 아주 중요하다.

 

Javascript 의 Scope 에는 다음 2가지가 있다.

 

(1) Local scope

지역 스코프를 말하며, Braclet({}) 안에서 정의되는 항목으로 정의된 해당 범위 내에서만 변수의 사용을 허용한다.

다른 범위에서 참조가 불가능하다.

 

(2) Global scope

전역 스코프를 말하며, 바닐라 자바스크립트에서 일반적으로 Braclet({}) 에 포함되지 않도록 정의된다.

전역으로 선언된 변수는 Window 객체로 포함되어 웹페이지 내에서 어디서든 참조가 가능하다.

 

그리고 응용된 Scope 로 Javascript 에서는 Nested Scope 라는 개념을 가질 수 있다.

 

(3) Nested Scope

Scope 내에서 별도의 Scope 를 정의한 경우 바깥쪽 Scope 에서 안쪽 Scope 에 접근이 불가능하지만 안쪽 Scope 에서는 바깥쪽 Scope 의 변수에 접근이 가능하다. 가령 다음과 같은 경우를 보자.

 

outerFoo() 함수의 출력 결과는 함수 내에서 innerFoo를 호출하기 때문에 70이 된다. innerFoo 함수에서 outerFoo 의 변수에 접근해서 곱하고 있는 모습이다. Nested Scope 에 의해 그 역은 성립되지 않는다.

이를 Lexical Scope 라고 하는데, 이는 변수나 함수가 문맥적으로 정의된 곳(Callee) 의 Context 를 참조한다는 일종의 원칙이다.

(이에 대한 대칭점으로 오래된 언어들에는 Dynamic Scope 라는 개념이 있고, 이는 변수나 함수가 불려진 곳(Caller) 의 Context 를 참조하는 개념이다.)

 

 

Javascript 의 Scope 는 기본적인 개념이라 익숙하면서도 자바스크립트의 특징적인 개념 중 하나이며, 중요한 개념인 Closure 를 이해하는 데 필수적이므로 잘 익혀두도록 하자.

 

 

Frontend 에 익숙하지않은 많은 개발자들이 과제 이상의 어느정도 규모있는 Frontend 를 작업하게 되면 HTML 과 CSS 의 구조에 대해 놀라는 경향이 있다.

 

HTML 과 CSS 는 생각보다 정교한 구조를 이루고 있고, 초보 수준 이상의 Frontend 실력을 갖기 위해서는 필수적으로 구조에 대해 이해하고 어떻게 브라우저가 웹(Web)을 스타일링하는 지 알아야 한다.

 

이해해야할 잘 갖춰진 Frontend 의 특징 중 하나로, "HTML 문서의 모든 프로퍼티(properties) 들은 상속가능하다" 는 점이 있다.

 

계층적으로 구조화된 DOM 모델에서 한 Element 는 Parent Element 의 속성을 지니며, 모든 element 들의 root parent 는 <html> 이 된다.

HTML 태그의 DOM 모델들 간 상속은 다른 포스팅에서 다루도록 하고, 본 포스팅에서는 CSS 의 상속에 대해 다루기로 한다.

 

복잡한 종류의 UI 를 구조할 때, 비슷한 CSS 스타일링을 중복해서 사용하게 되는 경우가 많이 있다.

가령, 웹페이지 전체의 UI 는 어느정도 일관성이 있어야 하기 때문에, 검색을 위한 검색바(Bar)와 검색 추천을 위한 표시바(Bar) 가 있는데 이 둘의 스타일을 비슷하게 가져가되 하이라이트 컬러 정도만 바꾸고자 한다고 해보자.

 

이 때, 세세하게 작업된 모든 디자인 스타일을 복사해서 사용하는 것은 비효율적인 일이다.

 

이럴 때에는 다음과 같이 CSS 상속을 이용해 쉽게 해결할 수 있다.

 

위의 코드에서 bar-focus 라는 CSS 스타일은 bar 스타일을 차용하되 background-color 에 특징을 입힌다.

위의 마크업은 다음과 같은 페이지를 나타내게 된다.

 

색배합이 끔찍하지만, 스타일을 재활용할 수 있다는 점정도는 쉽게 알 수 있다.

 

쉽지않은가? 이런식으로 스타일의 재활용을 통해 노가다로 여겨질 수 있는 Frontend 의 디자인 코드를 확연하게 정리할 수 있다.

 

하지만 CSS 의 상속과 관련되어 알아야할 성질들은 조금 더 있다.

 

먼저 브라우저가 상속을 처리하는 순서이다.

브라우저는 CSS 상속을 Inline > Internal > External 순서로 처리한다.

 

여기서 Inline, Internal, External 은 CSS를 정의하는 방법에 대한 분류를 말하며, 다음과 같다.

 - Inline : 해당 태그 안에 style=”” 속성을 통해 정의

 - Internal : 해당 파일 안에 <css> </css> 태그를 작성하고 해당 Scope 내에 정의

 - External : 별도의 파일로 CSS 를 분리하고 해당 파일을 HTML 에서 import

 

즉, CSS를 적용할 때에 위의 순서를 유의해야 해당 스타일이 반영될 수 있다.

 

또 당신이 프론트엔드 개발자라면 주의해야할 사항으로 태그의 속성 관리 부분이 있다.

 

만약, CSS 가 적용된 태그의 속성이 "float" 을 가지고 있는 경우 해당 DOM 은 상속관계 및 레이아웃에 영향을 받지않는 붕-뜬 상태가 된다. 

해당 요소에 상속성을 적용시키기 위해서는 overflow 속성의 적용이 필요하다.

 




웹 페이지를 구성하는 DOM Element 노드들은 트리 모양의 계층 구조를 갖고 있으며 DOM Element 와 연결된 Javascript 내부 동작 역시 이 구조에 대한 로직이 고려되어 있다.


이벤트 버블링과 캡쳐링은 Javascript 에서 주로 사용되는 Event Delegation Pattern 을 이해하는 기본적인 개념이다.


- 이벤트 버블링(Event Bubbling) 


웹페이지 내의 한 엘리먼트에서 이벤트가 감지되었을 때, 해당 엘리먼트의 계층구조를 따라 올라가면서 Root Element 까지 이벤트가 전달되는 것을 Event Bubbling 이라 한다.


이해를 돕기 위해 다음 코드를 확인해보자.


<div class="col-sm-1" onclick="alert('c')">
<div onclick="alert('b')">
<div onclick="alert('a')">
HELLO
</div>
</div>
</div>


위의 코드를 웹 페이지에서 확인해보면, HELLO 를 감싸고 있는 DOM 엘리먼트를 클릭하면 a - b - c 순서대로 3개의 Alert 창을 확인해볼 수 있다.


이처럼 이벤트 버블링(Bubbling)이란, 이벤트가 발생하는 가장 안쪽부터 바깥쪽, 하위 노드에서 상위노드로 이벤트가 전파(Propagation)되는 과정인 것이다.


하위 DOM Element 부터 전파되는 이벤트는 최종적으로 Document 객체까지 전달되며, 상위 Element 에서 이벤트 핸들러를 재정의해서 전파를 제어할 수 있다.


가령, 다음과 같은 코드에서 이벤트는 두번째 div 이상으로 전파되지 않는다.



<div class="col-sm-1" onclick="alert('c')">
<div onclick="event.stopPropagation()">
<div onclick="alert('a')">
HELLO
</div>
</div>
</div>


전파되지 않는 이유는 이벤트가 발생한 target Element 의 상위 Element 에서 onclick 메서드를 재구현하는데, event.stopPropagation() 함수를 이용해서 전파를 중단했기 때문이다.


이렇게 전파를 제어하는 것을 Stop Bubbling 이라고 한다.



- 이벤트 캡쳐링(Event Capturing)


이벤트 캡쳐링은 이벤트 버블링과 반대방향으로 이벤트가 전달된다.


다음 코드를 통해 이해해보자.


<div id="parent">
<div id="child">
HELLO
</div>
</div>
<script>
var parent = document.querySelector('#parent');
var child = document.querySelector('#child');
parent.addEventListener('click', function(){
alert("Parent clicked");
},true);
child.addEventListener('click', function(){
alert("Child clicked");
});
</script>


똑같이 계층 구조로 Element 들이 배치되어 있지만 이번에는 Parent 노드부터 이벤트가 전달된다.


이처럼 이벤트 캡쳐링(Event Capturing)이란, 상위노드부터 하위노드로 이벤트가 전달되는 형태를 말한다.


이 경우에 이벤트는 window 객체부터 차례로 아래 노드로 전파되며 addEventListener 의 3번째 인자로 capture 플래그를 두어 탐색 방향을 맞출 수 있다.


이벤트 캡쳐링의 경우 버블링보다는 덜 사용된다.



이벤트 버블링(Event Bubbling) 과 이벤트 캡쳐링(Event Capturing) 의 개념은 간단하지만, 이해하고 있지 않으면 은근히 프론트엔드 개발 시 삽질을 할 수 있는 부분이다.


잘 이해해두어 복잡한 UI 이벤트 처리 시에 헷갈리는 일이 없도록 하자.





본 포스팅에서는 현직 개발자에게도 생소하기 쉬운 쓰로틀링(Throttling)과 디바운싱(Debouncing) 테크닉에 대해 설명하고자 한다.


본래 Throttling 이란 주로 모바일 기기에서 많이 사용되는 용어로 성능을 위한 오버클럭(Overclock)이 디바이스에 무리를 주는 것을 방지하기 위해 고의로 성능을 낮추는 조절 방식을 말한다.


소프트웨어 적인 의미로도 Throttling 은 언급이 되곤 한다.


이 때에는 주로 트랜잭션을 처리하는 Middleware 나 네트워크 트래픽을 제어하는 ISP 에서 언급이 되며 UI 처리를 담당하는 프론트엔드(Frontend)에서도 사용된다.


프론트엔드(Frontend) 에서 쓰로틀링과 디바운싱은 어떤 경우에 사용될까?


가령 웹페이지를 구성하는데 해당 사이트는 다시 방문시 사용자가 읽던 포스트의 위치를 기억하고 그 페이지를 보여준다고 생각해보자.

페이지를 나눌 단위가 없으므로 스크롤 단위로 페이지 좌표를 서버에 기록하고자 한다면, 가장 단순한 방법은 Javascript 의 Scroll 이벤트를 이용해서 좌표를 저장하고 기록하는 방식이다.


이 경우 사용자의 스크롤링마다 이벤트를 발생시키면... 서버에도 클라이언트에도 매우 큰 부하가 발생되게 된다.

최악의 경우 페이지의 세로 좌표만큼 이벤트가 발생될 것이다.


예시는 최악의 구조와 최악의 경우를 가정한 것이지만, 중요한 점은 "이벤트의 오버클럭(Overclock)이 소프트웨어에 손상을 가져온다는 점" 이다.


이런 경우의 처리를 위해서도 쓰로틀링과 디바운싱 이라는 개념이 똑같이 적용되어 사용된다.


먼저 쓰로틀링(Throttling) 테크닉을 알아보자

쓰로틀링(Throttling) 을 이용하면 발생되는 이벤트 중간에 Delay 를 포함시킨다.


즉, Delay 이내로 연속적으로 발생된 이벤트에 대해서는 무시한다.


다음 코드를 보면 쉽게 이해될 것이다.




이런 종류의 테크닉은 특히 애니메이션을 구현하는 코드 등에서 많이 확인해볼 수 있다.


다음으로 디바운싱(Debouncing) 역시 쓰로틀링과 비슷하게 소프트웨어적인 오버클럭을 조절하는 테크닉이다.


하지만 쓰로틀링(Throttling) 과는 조금 다른 방법을 사용하는데, 쓰로틀링이 필터링(Filtering)의 방법을 사용한다면,


디바운싱(Debouncing)은 그루핑(Grouping)의 방법을 사용한다.


즉, 이벤트 핸들러가 주기적으로 여러 개의 발생한 이벤트를 하나로 묶어서 처리하는 방식이다.


이때, 먼저 발생한 이벤트가 처리를 대기하며, 대기하는 도중 새 이벤트가 발생하면 이전 이벤트의 대기를 취소(Cancel)하고, 해당 이벤트를 기준으로 다시 처리(Process)를 대기한다.

이렇게 특정 시간 동안 처리(Process)는 대기하게 되며 결과적으로는 일정한 시간 동안 연속적으로 발생한 이벤트는 마지막으로 발생한 이벤트 기준으로 처리된다.


여기서 Leading Edge 라는 디바운싱 테크닉을 이용하면 이 처리를 앞의 이벤트 기준으로 변경할 수 있으며 이 경우엔 쓰로틀링과 유사하게 동작하게 된다.

(나중에 발생하는 이벤트를 무시하는 방식은 같지만 첫 이벤트 처리가 딜레이 된다.)


다음 코드를 참조해보자.



쓰로틀링과 디바운싱은 생소하지만 알고보면 많은 이벤트 처리에 사용되고 있는 테크닉이다.

특히 UI를 처리하는 부분은 입력의 오버클럭을 감당하기 위해 없어서는 안되며 많은 라이브러리나 프레임워크에 이미 내장된 경우가 많으므로 잘 숙지해두는 것이 좋다.



좀 더 자세한 예시는 다음 링크가 가장 잘 되어 있는 듯 하다.

 : https://css-tricks.com/debouncing-throttling-explained-examples/


추가로 본 포스팅에선 이해를 돕기 위해 간단한 파이썬 코드로 예시를 작성했지만 실제 Javascript 에서 사용되는 코드의 예시는 다음을 참조해보자.

 : https://codeburst.io/throttling-and-debouncing-in-javascript-646d076d0a44



 AngularJS에서의 핵심 개념인 $scope란 양방향 데이터 바인딩의 핵심이자, 뷰와 컨트롤러를 연결하는 개념이다. 

$scope 는 HTML과 Javascript 를 연결해주는 구조로, 이는 단순한 Javascript 객체에 불과하지만, AngularJS 엔진에 의해 이 객체는 연결된 DOM 요소에서 Data와 Function이 사용되는 공간이라고 할 수 있다.

$scope 는 Javascript Object 이며 view 와 controller 사이를 연결할 수 있도록 몇가지 attribute 들을 포함하고 있다.


모든 AngularJS 로 제작된 Application 은 $rootScope 를 갖고 있으며 이는 ng-app 태그가 포함된 HTML 문서 최상단에 위치하는 $scope 가 된다.

따라서 다른 모든 $scope 들은 글로벌하게 정의되는 $rootScope를 상속하는 계층적인 구조를 이루고 있다. 즉, $rootScope 는 많은 child scope 들을 갖고 있다.

$rootScope 만이 AngularJS App 전체에서 유일한 Global Scope 로 처리가 되기 때문에 다른 AngularJS 의 Feature 들, 가령 Service 나 Factory 등이 $rootScope 를 이용하는 경우가 종종 있다.




위의 그림과 같이 하나의 HTML 에서 여러개의 ng-controller 를 정의할 경우 계층적으로 $scope 를 갖게 되고 이는 자연스럽게 계층 구조를 갖게 된다.


$scope는 뷰와 컨트롤러를 이어주는 다리이면서 연결된 DOM에서 양방향 데이터 바인딩을 처리해준다. 또한 이벤트를 처리할 수도 있다.

이 때, AngularJS 의 각 Controller는 하나의 컨트롤러에 하나의 $scope만을 갖게 된다.

그렇기 때문에 만약 독립된 $scope간 참조가 필요하다면 컨트롤러 간 데이터를 공유해야할 경우에는 Service를 이용한다.


AngularJS 의 실 구현은 대부분 ng-controller 로 명시되는 Controller 에서 수행되는 경우가 많기 때문에, 현재 다루고 있는 $scope 를 이해하고 있는건 매우 중요하다.


다음은 Scope 의 라이프사이클을 설명한다.


$scope 의 LifeCycle


1. 브라우저가 Javascript 를 로딩할 때, AngularJS 의 $injector 를 통해 정의된 Application(ng-app) 에 scope 를 할당한다.


2. 링킹 과정에서 $scope 하위에 $watch 오브젝트들이 등록된다.


3. 연결된 model 의 변화가 감지되면 $scope.$apply() 메서드가 AngularJS 내부에서 호출된다. 작업은 $http, $timeout, $interval 모듈을 이용해서 비동기적으로 이루어진다.


4. 변화가 감지되면 AngularJs 는 $digest cycle 을 rootScope 에서 수행한다. 변경 내용은 모든 child Scope 로 전파되며 당연히 각 $scope 에 정의된 $watch 가 이벤트를 전달받는다.


5. $scope 혹은 child Scope 가 더이상 필요가 없어지면 scope.$destroy 가 이루어지며 root Scope 에 의한 전파가 중단된다. 중단된 $scope 는 향후 가비지 컬렉팅된다.



참조 : https://docs.angularjs.org/guide/scope




최근에 AngularJS 를 이용해서 작업을 하던 도중 알게된 작은 버그이다.

(참고로 버전은 AngularJS 1 버전이고, 크롬에서 발생한 버그이다.)


문제가 된 HTML 은 다음과 같다.



<button class="button btn-danger" ng-click="deleteElement($index)">
<span class="glyphicon glyphicon-remove" aria-hidden="true">Delete</span></button>


위의 코드는 단순히 버튼을 클릭하면 해당 Element 에 대한 정보를 이용해서 ng-click 이벤트를 발생시키는 HTML 코드이다.


이 코드는 아주 잘 작동하지만, HTML 에서 엔터키 입력 시, 아주 사소한 버그를 발견할 수 있었다.


위의 코드에서 같은 scope 로 묶인 Text Box 에서 엔터를 입력하자마자 맨 위 레코드가 삭제되는 버그를 발견하였다.


정확히는 Enter Key 를 입력받아 ng-click 이벤트가 작동한 것이다. 다만, 명시적으로 ng-click 이 호출되지 않은 탓에 Parameter인 $index 는 전달되지 않은듯 하다.


문제의 원인은 <button> 태그에 있었는데, 기본적으로 button 태그의 type 은 "submit" 형이기 때문에, 엔터키 입력에 반응할 수 있다.

(이는 브라우저 별로도 다소 다른 듯 하다.)


문제 해결을 위해서는 다음과 같이 명시적으로 타입을 지정해주면 간단히 해결된다.



<button type="button" class="button btn-danger" ng-click="deleteElement($index)">
<span class="glyphicon glyphicon-remove" aria-hidden="true">Delete</span></button>


혹은 어느정도 규모의 AngularJS 프로젝트를 운용중이라면 directive 로 묶어서 처리하는 것도 좋은 방법이다.



(참고자료 : http://www.jomendez.com/2015/02/16/prevent-ng-click-action-hitting-enter/)



 Web Storage 는 HTML5 에서 새로 생겨난 신기술로, Cookie 를 대체할 목적으로 만들어진 Browser Storage 이다.


HTML5 이전에 Application data는 쿠키에 저장되었고 모든 Server 에 대한 Request 에 첨부되었다.

이에 반에 Web Storage 는 보다 안전하고 많은 데이터를 저장할 수 있으면서 웹 사이트 퍼포먼스 저하에 영향을 미치지 않는다.


4kb 까지 저장할 수 있는 쿠키와 다르게 5mb 까지 저장할 수 있으며 저장된 정보는 매요청마다 서버로 전달되지 않는다. 


또한 암호화가 가능하며, 쿠키에 비해 접근 및 내용확인이 어렵다.(보안 상 안전하다.)


실제로 오래 유지될 필요가 있을지는 의문이지만... 만료일자가 지정되어있는 쿠키와 다르게 반영구적 보존이 가능하다는 점도 장점이다.



HTML5 Web Storage 는 Local Storage & Session Storage 로 나뉘며 간단한 Key : Value 를 저장할 수 있는 점은 같다.


 - Local Storage : 로컬에 Origin 별로 지속되는 스토리지. Domain 마다 별도로 Local Storage 가 생성된다. Javascript 에서 Window 전역 객체의 localStorage 컬렉션으로 접근이 가능하다.


 - Session Storage : 현재 세션 동안만 유지되는 스토리지. Window 전역 객체의 sessionStorage 컬렉션을 통해 접근이 가능하다. Browser Context 내에서만 데이터가 유지되므로 브라우저 종료 시 데이터도 삭제된다.



HTML5 의 Web Storage 는 기존의 쿠키를 대체할 목적이 아닌 언어 레벨에서 제공해주는 훌륭한 Browser Storage 옵션에 가깝다. 

실제로 쿠키처럼 매 요청시 서버로 전송되지 않기 때문에 필요한 요청에 대해 명시적으로 Request 를 날려야할 필요가 있다.





DOM은 W3C 표준으로 정의되어있는 문서의 항목을 객체화하기 위한 방법으로, 다음과 같은 3가지 파트로 나뉘어 있다.


 - Core DOM : 대부분의 Document Type 에서의 Object 형태를 말한다.

 - XML DOM : XML 문서 타입에서의 객체형태를 말한다.

 - HTML DOM : 포스팅에서 다루고자 하는 내용이며, HTML 문서 내에서 객체들이 해석되기 위한 형태를 말한다.


즉, HTML 에서 DOM이라함은 W3C의 HTML DOM 표준을 말하는 것이다.


DOM 오브젝트란 Document Object Model 의 약어로 웹브라우저가 HTML 을 해석하는 방식이자, Document 및 내부 구성요소를 객체화한 형태의 집합이라 할 수 있다.


HTML 의 각 요소들은 HTML Tag 및 텍스트들로 구성되어 있고, 이 각각의 항목을 노드(Node) 라 하고, 각각의 항목들은 Tree 의 계층형 구조를 이루고 있다.


HTML DOM 은 프로그래밍적 인터페이스를 허용하게 되어있으며 그에 따라 인터프리터가 Object 형태로 관리하게 되어있다.

각 Element 들은 Property 나 methods, events 를 가질 수 있게 설계되어 있다.


HTML DOM 은 HTML 의 Element 들을 나타내는 방식이자 Web 에서 문서가 동작하기 위한 표준으로 이해하면 된다.


<참고 : https://www.w3schools.com/js/js_htmldom.asp>




먼저 <div> 태그와 <span> 태그의 차이점을 알아보자.


사용하는데 있어서 차이를 알아내긴 어렵지만 이는 생각보다 간단한데 단순히 div 는 block element 이고, span 은 inline element 라는 점이다.


좀더 설명하자면, div는 Document 의 부분들을 감쌀 수 있도록 설계되어 있지만, span 은 small portion(text, image 등)에 해당하는 작은 부분만 감싸게끔 설계되어 있다.


여기서 Block Level Element 와 Inline Level Element 라는 다소 생소한 분류가 등장한다.


* Block Level Element 와 Inline Level Element 의 차이점


 : Block Level Element 들은 <body> 요소 안에서만 표현되도록 정의되어 있다. 또한 Block Level element 들은 

 감싸고 있는 표현 전후를 분리시켜주는(개행) 특징을 가진다. 즉, 이 영역은 앞 뒤 영역과 구분된 독자적인 영역이 된다.

 또한 Block Level Element 들은 Inline Level Element 들을 포함할 수 있다.


 : Inline Element 는 Tag 가 시작된 라인에서 바로 시작하며 이전과 이후를 구분(개행)하지 않는다. HTML5 이전의 일반적인 Inline Element 는 Block Element 를 포함하지 못한다.



 HTML5가 되면서, 몇몇 Block Element 들이 Inline Element 안에 포함이 가능하게 되면서, 차이점이 조금 불분명해졌다.


그럼에도 Span 은 Phrasing content 만을 안에 포함시킬 수 있고, div 는 flow content 를 포함시킬 수 있다는 차이점이 있다.

여기서 flow content 와 phrasing content 는 부가적인 분류 카테고리이다. 

flow content 는 마크업으로써 표현되는 컨텐츠 자체를 의미하며, phrasing content 는 해당 요소가 강조 하거나 꾸며주는 역할을 하는 도구로써의 Element 일 경우를 말한다.


HTML이 모던해짐에 따라 element 들은 복수의 역할을 수행할 수 있도록 진화하고 있으나, 그건 HTML 초기 디자인이 의도한 바가 아니다.

가령 <p> 태그는 paragraph 를 위해 만들어진 태그이며, <li> 는 list item 을 위해 만들어진 태그이다.

HTML 은 모던해짐과 동시에 혼용될 수 있는 역할에 따른 사용을 방지하기 위해 의미없는 차이임에도 태그를 나누는 경우들이 있다.




+ Recent posts