프로그래밍 지식/Develop Knowledge

프론트엔드가 가지고 있어야 할 지식

홍수성찬 2021. 4. 14. 19:44

FrontEnd

브라우저의 동작 원리

  1. HTML 마크업을 처리하고 DOM 트리를 빌드 ("무엇을" 그릴지 결정)
  2. CSS 마크업을 처리하고 CSSOM 트리를 빌드 ("어떻게" 그릴지 결정)
  3. DOM 및 CSSOM을 결합하여 렌더링 트리를 형성 ("화면에 그려질 것만" 결정)
  4. 렌더링 트리에서 레이 아웃을 실행하여 각 노드의 기하학적 형태를 계산 ("Box-Model"을 생성)
  5. 개별 노드를 화면에 페인트 혹은 래스터화

Document Object Model (DOM)

웹에서 수많은 이벤트(Event)가 발생하고 흐른다.

  • 브라우저(User Agent)로부터 발생하는 이벤트
  • 사용자의 행동(Interaction)에 의해 발생하는 이벤트
  • DOM의 '변화'로 인해 발생하는 이벤트

발생하는 이벤트는 단지 자바스크립트 객체일 뿐이다. 브라우저의 Event Interface에 맞춰 구현된 객체이다.

 

여러 DOM Element로 구성된 하나의 웹 페이지는 Window를 최상위로 하는 트리를 생성한다. 결론적으로 이벤트는 이벤트 각각 갖게 되는 전파 경로(Propagation Path)를 따라 전파된다. 그리고 이 전파 경로는 DOM Tree 구조에서 Element의 위상(Hierarchy)에 의해 결정된다.

 

CORS (Cross-Origin Resource Sharing)

다른 도메인으로부터 리소스가 요청될 경우 해당 리소스는 Cross-Origin HTTP 요청에 의해 요청된다. 하지만 대부분 브라우저는 보안 상의 이유로 스크립트에서의 Cross-Origin HTTP 요청을 제한한다. 이것을 "Same-Origin-Policy(동일 근원 정책)" 이라고 한다.

 

요청을 보내기 위해서는 요청을 보내고자 하는 대상과 프로토콜이 같아야 하며, 포트도 같아야 한다는 것을 의미한다. (서브 도메인 네임은 상관 없다)

 

이러한 문제를 해결하기 위해 과거에서는 Flash를 Proxy로 두고 타 도메인 간 통신을 했다. 그러나 모바일 운영체제 이후 Flash로 해결하기 힘들어졌다. 그래서 대체제로 나온 기술이 JSONP(JSON-Padding)이다. jQuery 1.2 버전 이상부터 JSONP 형태가 지원되어 AJAX를 호출할 때, 타 도메인 간 호출이 가능해졌다. JSONP에는 타 도메인 간 자원을 공유할 수 있는 태그가 있다.

  • img
  • iframe
  • anchor
  • script
  • link
  • 등등

여기서 CORS는 타 도메인 간 자원을 공유할 수 있게 해준다. Cross-Origin Resource Sharing 표준은 웹 브라우저가 사용하는 정보를 읽을 수 있도록 허가된 출처 집합을 서버에게 알려주도록 허용하는 특정 HTTP 헤더를 추가함으로써 동작한다.

 

HTTP Header Description
Access-Control-Allow-Origin 접근 가능한 url 설정
Access-Control-Allow-Credentials 접근 가능한 쿠키 설정
Access-Control-Allow-Headers 접근 가능한 헤더 설정
Access-Control-Allow-Methods 접근 가능한 http method 설정

Preflight Request

실제 요청을 보내도 안전한지 판단하기 위해서 Preflight 요청을 먼저 보내는 방법이다. 즉, Preflight Request는 실제 요청 전에 인증 헤더를 전송하여 서버의 허용 여부를 미리 체크하는 테스트 요청이다. 이 요청으로 트래픽이 증가할 수 있는데 서버의 헤더 설정으로 캐시가 가능하다. 서버 측에서 브라우저가 해당 도메인에서 CORS를 허용하는지 알아보기 위해 Preflight 요청을 보내는데 이에 대한 처리가 필요하다. Preflight 요청은 HTTP의 OPTIONS 메서드를 사용하며 Access-Control-Request-* 형태의 헤더로 전송한다.

 

이는 브라우저가 강제하며 HTTP OPTIONS 요청 메서드를 이용해 서버로부터 지원중인 메서드들을 내려 받은 후에 서버에서 Approval(승인)시에 실제 HTTP 요청 메서드를 이용해 실제 요청을 전송하는 것이다.

 

Cross-Browsing (크로스 브라우징)

웹 표준에 따라 개발을 하여 서로 다른 운영체제 또는 플랫폼에 대응하는 것이다. 즉, 브라우저의 렌더링 엔진이 다른 경우에 인터넷이 문제 없이 구현되도록 하는 기술이다. 웹 사이트를 서로 비슷하게 만들어 어떤 환경에서도 이상없이 작동되게 하는데에 목적이 있다. 즉, 어느 한 쪽에 최적회되어 치우치지 않도록 공통 요소를 사용하여 웹 페이지를 제작하는 방법을 말한다.

 

웹 성능과 관련된 Issue

 

1. 네트워크 요쳥에 빠르게 응답하자

- 3.xx리다이렉트를 피할 것
- meta-refresh사용 금지
- CDN (Content Delivery Network)을 사용할 것
- 동시 커넥션 수를 최소화할 것
- 커넥션을 재활용할 것

 

2. 자원을 최소한의 크기로 내려 받자

- 777K
- Gzip압축을 사용할 것
- HTML5 App Cache를 활용할 것
- 자원을 캐시 가능하게 할 것
- 조건 요청을 보낼 것

 

3. 효율적인 마크업 구조를 구축하자

- 레거시 IE 모드는 HTTP 헤더를 사용할 것
- @import의 사용을 피할 것
- Inline 스타일과 embedded 스타일은 피할 것
- 사용하는 스타일만 CSS에 포함할 것
- 중복되는 코드를 최소화 할 것
- 단일 프레임워크를 사용할 것
- Third Party 스크립트를 삽입하지 말 것

 

4. 이미지 사용을 개선하자

- 이미지 프라이트를 사용할 것 (하나의 이미지로 편집해서 요청을 한 번만 보낸다)
- 실제 이미지 해상도를 사용할 것
- CSS3을 제대로 활용할 것
- 하나의 작은 크기의 이미지는 DataURL을 사용할 것
- 비디오의 미리보기 이미지를 만들 것

 

5. 빠른 자바스크립트 코드를 작성하자

- 코드를 최소화 할 것
- 필요할 때만 스크립트를 가져올 것 = flag 사용
- DOM에 대한 접근을 최소화 할 것 = DOM Manipulate는 느림
- 다수의 엘리먼트를 찾을 때는 Selector API를 사용
- 마크업의 변경은 한 번에 할 것 = Temp 변수를 활용
- DOM의 크기를 작게 유지할 것
- 내장 JSON 메서드를 사용할 것

 

6. 애플리케이션의 작동 원리를 알고 있자

- Timer 사용에 유의할 것
- RequestAnimationFrame을 사용할 것
- 활성화될 때를 알고 있을 것

 

서버 사이드 렌더링 vs 클라이언트 사이드 렌더링

서버 사이드 렌더링은 요청 시 마다 새로고침이 일어나며 페이지를 로딩할 때마다 서버로부터 리소스를 전달받아 해석하고 화면에 렌더링 하는 방식
클러이언트 사이드 렌더링은 서버에서는 JSON 파일만 보내주는 역할을 하고 HTML을 그리는 역할은 클라이언트 측에서 자바스크립트가 수행하도록 하는 방식

 

모바일 시대가 도래하면서, 모바일 웹에 대한 요구가 증가했고 그에 따른 성능 이슈가 발생하였다. 컴퓨터에 비해 낮은 성능과 스마트폰을 통해 웹 페이지를 출력하기 위해서는 기존 방식과 다른 접근이 필요했고 그에 따라서 Single Page Web Application (SPA) 기법이 등장하게 되었다.

 

SPA는 브라우저에 로드되고 난 뒤에 페이지 전체를 서버에 요청하는 것이 아닌 최초 한 번 페이지 전체를 로딩한 이후부터는 데이터만 변경하여 사용할 수 있는 웹 애플리케이션이다. 전통적인 웹 방식(서버 사이드 렌더링)은 SPA 방식에 비해 성능 문제를 보였다.

 

SPA는 트래픽을 감소시키고 사용자에게 더욱 나은 경험을 제공했다. 이후 나온 것이 클라이언트 사이드 렌더링이다. Angular JS와 Backbone JS와 같은 Single Page를 생성하기 쉬운 JS 프레임워크들이 등장했고 특히 Angular JS는 러닝 커브를 제외한 많은 장점들 때문에 개발자들에게 큰 호응을 얻었다. (그러나 느리다)

 

클라이언트 쪽이 조금씩 무거워지면서 이와 반대로 View만 관리하는 React가 등장하였다. 이렇게 클라이언트 사이드 렌더링과 서버 사이드 렌더링의 다툼이 시작되었다.

 

아래 표는 단계를 보여준다. (위부터 아래로 순서가 단계)

Client-side Rendering Server-side Rendering
Download HTML Download HTML
Download JavaScript -
Evaluate JavaScript -
Fetch Data from API -
User see Content User see Content

각 렌더링의 장단점 비교

  • 클라이언트 사이드 렌더링 사용자의 행동에 따라 필요한 부분만 다시 읽어들이기 때문에 서버 측에서 렌더링하여 전체 페이지를 읽는 것보다 빠른 인터랙션을 기대할 수 있다. 서버 사이드 렌더링을 하더라도 AJAX 기능을 위해 클라이언트 렌더링 요소가 포함될 수 밖에 없다. 그러므로 클라이언트 측에서 렌더링을 하게 되면 서버 사이드 렌더링이 따로 필요하지 않기 때문에 일관성있는 코드를 작성할 수 있다.

그러나 페이지를 읽어들이는 시간, 자바스크립트를 읽어들이는 시간, 자바스크립트가 화면을 그리는 시간까지 마쳐야 내용이 사용자에게 보여진다. 여기에 웹 서버에서 콘텐츠 데이터라도 가져와야 한다면 그 시간은 더욱 길어진다.
즉, 초기 구동 속도가 느리다는 단점이 존재한다. (초기 구동 속도를 제외하면 그 다음부터는 빠른 인터랙션 성능을 보인다)

 

그리고 치명적이라고 할 수 있는 검색 엔진 최적화의 문제가 있다.
대부분 웹 크롤러, 봇들이 자바스크립트 파일을 실행시키지 못한다는 것이다. 그렇기 때문에 HTML에서만 콘텐츠를 수집하게 되고 클라이언트 사이드 렌더링이 되는 페이지를 빈 페이지로 인식하게 된다. 그리고 보안 문제가 발생한다. 기존의 서버 사이드 렌더링에서는 사용자에 대한 정보를 서버 측에서 세션으로 관리를 했는데 클라이언트 측에는 쿠키 말고는 사용자에 대한 정보를 저장할 공간이 마땅치 않다.

  • 서버 사이드 렌더링 서버 사이드의 렌더링의 장점은 클라이언트 사이드 렌더링의 반대 경우를 생각하면 쉽다.
    유저가 처음으로 콘텐츠를 접하게 되는 시점을 당길 수 있고, 서버와 클라이언트를 따로 작성하던 코드를 하나로 합쳐진다. 물론 SEO 적용도 문제가 없다. 문제점은 사용자와 인터랙션하는 부분이다. 매번 서버에 Request 요청을 통해서 해결해야 하기 때문이다. DOM 조작에 있어서도 요청하는 과정과 엄청난 탐색 비용의 문제가 있다. React가 이 부분에 있어서 많은 해결책을 제시했지만 아직 더 지켜봐야 한다.

CSS Methodology

 

SMACSS (Scalable and Modular Architecture for CSS)

SMACSS의 핵심은 범주화이며(Categorization) 스타일을 다섯 가지 유형으로 분류하고, 각 유형에 맞는 선택자(Selector)와 작명법(Naming Convention)을 제시한다.

 

  • 기초(Base)
    • Element 스타일의 Default 값을 지정해준다. 선택자로 요소 선택자를 사용한다.
  • 레이아웃(Layout)
    • 구성하고자 하는 페이지를 컴포넌트로 나누고 어떻게 위치하는지 결정한다. id는 CSS에서 클래스와 성능 차이가 없으며, CSS에서 사용하게 되면 재사용성이 떨어져 클래스를 주로 사용한다.
  • 모듈(Module)
    • 레이아웃 요소 안에 들어가는 더 작은 부분들에 대한 스타일을 정의한다. 클래스 선택자를 사용하며, 모든 선택자는 가급적으로 피한다. 클래스 이름은 적용되는 스타일의 내용을 담는다.
  • 상태(States)
    • 다른 스타일에 덧붙이거나 덮어씌어서 상태를 나타낸다. 그러므로 자바스크립트에 의존하는 스타일이 된다. is- prefix를 붙여 상태를 제어하는 스타일임을 보인다. 특정 모듈에 한정된 상태는 모듈 이름도 이름에 포함시킨다.
  • 테마(Theme)
    • 테마는 프로젝트에서 잘 사용되지 않는 카테고리다. 사용자의 설정에 따라 CSS를 변경할 수 있는데 CSS를 설정할 때 사용하게 되며 접두어로 theme-를 붙여 표시한다.

OOCSS (Object Oriented CSS)

객체 지향 CSS 방법론이며, 2가지 기본 원칙을 가지고 있다.

  • 첫 번째 원칙, 구조와 모양을 분리한다.
    • 반복적인 시각적 기능을 별도의 스킨으로 정의하여 다양한 객체와 혼합해 중복 코드를 제거한다.
  • 두 번째 원칙, 컨테이너와 컨텐츠를 분리한다.
    • 스타일을 정의할 때 위치에 의존적인 스타일을 사용하지 않는다. 사물의 모양은 어디에 위치하든 동일하게 보여야 한다.

BEM (Block Element Modifier)

웨 페이지를 각 컴포넌트의 조합으로 보고 접근하는 방법론이자 규칙이다. SMACSS가 가이드 라인이라는 것에 비해 조금 더 범위가 좁은 반면에 강제성 측면에서 강하다. BEM은 CSS로 스타일을 입힐 때 id를 사용하는 것을 막는다. 요소 셀렉터를 통해서 직접 스타일을 적용하는 것을 허락하지 않는다. 또한 자손 선택자 사용을 허락하지 않는다. 이유는 재사용성을 높이기 위함이다.

  • Naming Convention
    • 소문자와 숫자만을 사용하여 작명하고 여러 단어의 조합은 하이픈(-), 언더바(_)를 사용하여 연결한다.
  • BEM의 B는 'Block'
    • 블록(Block)은 재사용할 수 있는 독립적인 페이지 구성 요소이며, HTML에서 블록은 class로 표시된다. 블록은 주변 환경에 영향을 받지 않아야 하며, 여백이나 위치를 설정하면 안된다.
  • BEM의 E는 'Element'
    • 블록 안에서 특정 기능을 담당하는 부분이며, Block_element 형태로 사용한다. 요소는 중첩해서 작성될 수 있다.
  • BEM의 M는 'Modifier'
    • 블록이나 요소의 모양, 상태를 정의한다. block_element-modifier, block-modifier 형태로 사용한다. 수식어에는 Boolean 타입과 Key-Value 타입이 있다.

Normalize vs Reset

브라우저마다 기본적으로 제공하는 Element의 Style을 통일시키기 위해 작성하는 CSS를 알아본다.

 

reset.css

기본적으로 제공되는 브라우저 스타일을 전부 제거하기 위해 사용된다. reset.css가 적용이 되면 <H1> ~ <H6>, <P>, <string>, <em>등과 같은 표준 요소는 완전히 똑같이 보이며 브라우저가 제공하는 기본적인 스타일링이 전혀 없다.

 

normalize.css

브라우저 간 일관된 스타일링을 목표로 한다. <H1> ~ <H6>과 같은 요소는 브라우저 간에 일관된 방식으로 굵게 표시된다. 추가적인 디자인에 필요한 Style만 CSS로 작성하면 된다.

 

즉, normalize.css는 모든 것을 '해제'하기보다 유용한 기본값을 보존한다. 예로 SUP 또는 SUB와 같은 요소는 normalize.css가 적용이 된 후에 바로 기대하는 스타일을 보여준다. 반면 reset.css을 포함하면 시각적으로 일반 텍스트와 구별할 수 없다. 또한 normalize.css는 reset.css보다 넓은 범위를 가지고 있으며 HTML 5 요소의 표시 설정과 양식 요소의 글꼴 상속 부족, Pre-font 크기 렌더링 수정, IE9의 SVG 오버플로우 및 IOS의 버튼 스타일링 버그 등에 대한 이슈를 해결해준다.