Chapter1. 브라우저
Chapter2. 브라우저 렌더링
Chapter3. 반응형 웹
과제 1 - 반응형 웹 만들기
Chapter4. CSS 애니메이션
Chapter5. Canvas(캔버스)
과제 2 - CSS 애니메이션 및 캔버스 활용하기
웹 페이지를 띄워주는 브라우저와 특징, 브라우저의 구조에 대해 이해한다.
프론트엔드 개발자라면 단순히 코드 개발을 하는 것을 뛰어넘어 브라우저가 어떻게 동작을 하는지, 어떻게 렌더링을 수행하는 지에 대해 아는 것이 굉장히 중요함
💡 결국 내가 친 코드는 브라우저라는 소프트웨어 프로그램 상에서 수행되기 때문
웹 브라우저라고도 하고, 웹 탐색기라고도 하는 브라우저는 웹 서버에서 양방향으로 통신을 하며 HTML 문서 및 그림, 멀티미디어(ex. 동영상) 등의 컨텐츠를 열람할 수 있게 해주는 GUI 기반의 소프트웨어 프로그램
브라우저는 페이지를 다운로드 하기 위해 응용 계층의 대표적인 프로토콜인 HTTP를 통해 송수신함
이런 브라우저 상에서 제공되는 웹(Web)은 월드 와이드 웹(World Wide Web)이 풀 네임이며, 인터넷 상에서 텍스트나 그림, 소리, 영상 등과 같은 멀티미디어 정보를 하이퍼텍스트(hypertext) 방식으로 연결해 제공함
브라우저는 현존하는 브라우저끼리 조금씩 그 특징이 다르지만 공통점이 하나 있음.
-> 그거슨 바로 동작 방식!
아래는 웹 브라우저가 웹 사이트에 접속하여 웹 페이지를 가져오는 과정을 도식화한 그림임
먼저, 사용자가 웹 브라우저를 통해 찾고 싶은 웹 페이지의 URL 주소를 입력한다
그러면 DNS 서버에서 사용자가 입력한 URL 주소 중 도메인 네임을 검색한다.그리고 해당 도메인 네임에 해당하는 IP 주소를 찾아 사용자가 입력한 URL 정보와 함께 전달한다.
웹 페이지 URL 정보와 전달받은 IP 주소는 HTTP 프로토콜을 사용해 HTTP 요청 메세지를 생성해 TCP 프로토콜을 사용해 인터넷을 거쳐 해당 IP 컴퓨터로 전송되고, 이 요청 메세지는 다시 HTTP 프로토콜을 통해 웹 페이지 URL 정보로 변환이 됨
웹 서버는 이 변환이 된 정보에 해당하는 데이터를 검색하여 찾아낸 뒤 HTTP 프로토콜을 통해 HTTP 응답 메세지를 생성하고, 이 메세지는 다시 TCP 프로토콜을 이용해 인터넷을 거쳐 사용자의 컴퓨터로 전송이 됨
사용자의 컴퓨터에 도착한 HTTP 응답 메세지는 HTTP 프로토콜을 사용해 웹 페이지 데이터로 변환이 되고, 변환된 데이터는 웹 브라우저 상에 출력되어 사용자가 볼 수 있게 됨
브라우저는 각기 그 모양이 조금씩 다르지만 모두 기본적인 구조를 가지고 있다.
[그림] 브라우저의 구조의 도식화
UI이라고도 부르며, 가장 유저와 밀접하게 맞닿아있는 부분으로 주소 표시줄, 이전/다음 버튼, 북마크 메뉴 등에 관련된 GUI 부분을 통칭한다.
[그림] 붉은 부위가 사용자 인터페이스(UI). 요청한 페이지(구글 홈 화면) 외의 나머지 모든 부분이라고 보면 됩니다.
사용자 인터페이스와 렌더링 엔진 사이의 동작을 제어한다.
브라우저 엔진의 주된 역할은 HTML 문서와 기타 자원의 웹페이지를 사용자의 장치에 시각 표현으로 변환시키며, 문서 객체 모델(DOM) 자료 구조를 구현한다.
레이아웃 엔진(Layout Engine)라고도 부르며, 렌더링 엔진(Rendering Engine)과 밀접한 연관이 있어 보통은 브라우저 엔진과 렌더링 엔진을 묶어 브라우저 엔진으로 부르나 여기서는 구분해서 표현한다.
이러한 브라우저 엔진은 웹 브라우저 마다 전용 엔진을 사용하고 있음
이름 | 설명 |
---|---|
게코(Gecko) | 모질라 재단에서 만든 브라우저 엔진. 파이어폭스가 해당 엔진을 탑재하고 있는 유명한 웹 브라우저 |
웹킷(Webkit) | KHTML에서 파생된 브라우저 엔진. 사파리가 해당 엔진을 탑재하고 있는 가장 유명한 웹 브라우저 |
블링크(Blink) | 웹킷(Webkit)에서 파생된 브라우저 엔진. 크롬, 오페라가 해당 엔진을 탑재하고 있는 유명한 웹 브라우저 |
트라이던트(Trident) | 마이크로소프트의 브라우저 엔진으로 인터넷 익스플로러, 아웃룩 익스프레스, 마이크로소프트 아웃룩 등이 이를 탑재하고 있음 |
EdgeHTML | 트라이던트(Trident)에서 파생된 브라우저 엔진으로 마이크로소프트 엣지 스파르탄 버전(~2019)까지 탑재됨 (현재는 블링크로 교체.) |
요청한 콘텐츠를 화면에 출력하는 역할을 합니다. HTML, CSS 등을 파싱해 최종적으로 화면에 그려주며, 렌더링 엔진은 HTML 및 XML 문서와 이미지를 표시할 수 있음 (플러그인이나 브라우저 확장 기능을 이용해 PDF와 같은 다른 유형도 표시할 수 있다.)
위에서 기술한 브라우저 엔진과 밀접하게 결합되어 있으므로 보통은 하나의 엔진으로 보는 시각이 많다. 렌더링 엔진 또한 웹 브라우저 마다 전용 엔진을 사용하고 있으나 엔진의 동작 원리는 공통된 부분이 많다.
HTTP 요청과 같은 네트워크 호출에 사용됨. 보통 플랫폼의 독립적인 인터페이스이고 각 플랫폼의 하부에서 실행됨
현대의 웹 페이지 대부분의 웹 인터랙션(Interaction)에 JavaScript가 사용되고 있음.
JavaScript는 코드를 위에서 아래로 한 줄씩 읽어내려가는 방식으로 파싱하는 언어(Interpreted Language). 따라서 JavaScript 코드를 해석하고 실행하는 자바스크립트 해석기(JavaScript Interpreter)가 필요에 의해 등장하게 됨
자바스크립트 엔진(JavaScript Engine)이라고도 부르는 자바스크립트 해석기는 여러 목적으로 사용이 되지만 대체적으로 웹 브라우저에서 이용이 되며, 브라우저마다 전용 엔진이 탑재돼 있음
이름 | 설명 |
---|---|
Rhino | 모질라 재단이 운영하는 오픈소스 엔진으로, 자바(Java)로 개발되었다는 특징이 있다. |
SpiderMonkey | 최초의 Javascript 엔진으로 넷스케이프 내비게이터를 지원하였으며, 현재는 파이어폭스를 지원하고 있다. |
V8 | 구글이 개발한 오픈 소스 엔진으로 구글 크롬의 Javascript 엔진. |
JavascriptCore | 애플에서 개발하였으며 처음에 WebKit 프레임워크를 위해 개발되었지만 현재는 사파리와 React Native App를 지원하고 있다. |
Chakra | 마이크로소프트가 개발한 엔진이며, Edge 브라우저를 지원하고 있다. |
V8 엔진의 메모리 구조를 간단히 나타낸 그림
V8엔진은 크게 Heap Memory와 Call Stack으로 구성되어 있다.
V8이 어떻게 메모리를 관리하는 지에 대한 칼럼
Heap Memory 내부에는 다양한 공간이 있지만, 여기서는 커다랗게 하나의 공간으로 되어있다고 이해하자.
힙은 동적 메모리 할당에 사용되는 자료구조이다. 이 자료구조를 이용하여 V8은 객체 또는 동적 데이터를 저장함. 이 메모리는 V8 엔진 내부에서 가장 큰 공간을 차지하고 있으며, 가비지 컬렉션 또한 발생하는 곳임
JavaScript는 기본적으로 싱글 스레드 기반의 언어다. 콜 스택이 하나라는 의미이며, 한 번에 한 작업만 사용할 수 있다. 콜 스택은 프로그램 상에서 우리가 어디에 있는지 기록하는 자료구조다.
만약 함수를 실행한다면, 해당 함수는 콜 스택의 가장 상단에 위치한다. 이는 스택이라는 자료구조가 후입선출이라는 구조를 가지고 있기 때문에 일어나는 일이다. 함수의 실행이 끝난다면 해당하는 함수는 콜 스택의 가장 상단에 위치하고 있기 때문에 바로 제거할 수 있게 된다.
실행하기 전에는 아직 스택에는 아무것도 들어가지 않은 상태
함수를 실행해보자
[그림] 스택이 쌓이는(push) 과정.
제일 먼저 printSquare(4)
가 호출이 될 것입니다.
호출이 되는 순간 해당하는 함수가 스택으로 “push” 됩니다.
함수 printSquare
내부에서는 다시 square(n)
을 호출하고 있으므로, 함수 square
를 이어 스택 안으로 push 합니다.
그 뒤, 함수 square
내부에서도 multiply(n, n)
을 호출하고 있으므로 함수 multiply
를 뒤이어 스택 안으로 push 합니다.
이 과정에서는 return문으로 함수 호출만 되고 return 되는 특정 값이 없어 쌓이기만 합니다.
함수 multiply
까지 도착해서야 드디어 return 되는 값을 얻습니다.
3.이제 스택 안에서 return 되는 순서대로 stack을 제거하자.
[그림] 스택이 제거되는(pop) 과정. return 되는 순서대로 후입선출 구조로 빠진다.
함수 multiply와 함수 square에서 차례대로 return문의 결과를 얻습니다. 따라서 스택 내부에서 차례대로 제거를 합니다.
4.함수 printSquare로 돌아오면, 함수 내부에서 실행시켜야 하는 메소드가 있음
console.log(squared);
해당 메소드를 실행시킨 뒤, 함수가 완전히 종료되는 순간까지 보자!
[그림] 스택이 모든 단계를 완료하는 과정.
호출 스택의 각 단계를 스택 프레임(Stack Frame)이라고 부릅니다. 스택 내에 쌓이는 printSquare(4) 하나가 프레임 하나임을 의미합니다. 콜 스택이 동작하는 방식을 안다면 스택의 추적 (Stack trace) 또한 가능해지게 됩니다.
이러한 콜 스택은 자료구조 자체가 크기에 제한이 있습니다. 따라서, 한정된 메모리 공간을 넘어버리게 되면 어떠한 에러를 발생시키는데, 그것을 바로 스택 오버플로(Stack Overflow)라고 부름
스택 오버플로는 콜 스택 내부의 동일한 스택 프레임이 예상치 못한 수로 쌓일 때 일어남.
[그림] 같은 함수를 무한하게 호출하면 스택 내부에 쌓이다 못해 터지게 된다.
함수 oops()를 계속해서 호출하게 되면 스택 내부에 함수 oops() 가 계속해서 쌓이게 됩니다. 스택 내부에 동일한 스택 프레임이 계속 쌓이고 있고, 그림에서처럼 프레임이 제한된 스택을 넘어버리게 됩니다. 콜 스택을 스택 프레임이 넘어버리게 되면 웹 브라우저는 멈춰버리게 됨
JavaScript를 다루다보면 종종 웹 브라우저의 콘솔에 출력되는 에러 로그를 본 적이 있을 것입니다.
해당 에러 로그를 자세히 살펴본다면 어디서 에러가 발생하고 있고, 발생한 이유가 무엇인지 아는 데에 매우 도움이 됨.
렌더링 엔진이 분석한 Render Tree를 브라우저에 그리는 역할을 담당함. Select, Input 창과 같은 기본적인 위젯을 그려줌. 플랫폼에서 명시하지 않은 일반적인 인터페이스로, OS 사용자 인터페이스 체계를 사용함
OS 사용자 인터페이스(user interface)는 앞서배운 UI/UX과는 조금 다르다.
유저 인터페이스(user interface, UI)는 사람(사용자)과 사물 또는 시스템, 특히 기계, 컴퓨터 프로그램 등 사이에서 의사소통을 할 수 있도록 일시적 또는 영구적인 접근을 목적으로 만들어진 물리적, 가상적 매개체를 뜻함.
그렇기 때문에 거의 모든 운영체제는 사용자 인터페이스를 가지고 있으며, 이 인터페이스는 여러 형태를 가지고 있다.
이 인터페이스를 다룰 때는 특정한 명령 체계를 사용해야 하는데, 그 중 하나가 명령어 라인 인터페이스(Command Line Interface, CLI)이며 또 하나는 일괄 처리 인터페이스(Batch Interface)이다.
가장 일반적으로 사용되는 것은 그래픽 사용자 인터페이스 (Graphic User Interface, GUI)
말 그대로 자료를 저장하는 계층
쿠키를 저장하는 것과 같이 모든 자원을 하드 디스크에 저장할 필요가 있기 때문에 존재한다.
HTML5 명세에는 브라우저가 지원하는 웹 저장소(Web Storage, 이하 웹 스토리지라고 지칭)스펙이 정의되어 있다.
영구적인 저장소인 로컬스토리지(localStorage)와 임시적인 저장소인 세션스토리지(sesseionStorage)를 따로 두어 데이터의 지속성을 구분할 수 있어 응용 환경에 맞는 선택이 가능하다.
HTML5 이전에는 응용 프로그램이 서버에 데이터를 요청할 때마다 매번 쿠키(Cookie)라는 곳에 그 정보를 저장해왔다.
그러나 쿠키 자체의 보안상 취약과 더불어 저장소의 절대적인 허용 용량의 적음으로 다른 대안을 찾게 되었고, 이윽고 웹 스토리지(Web Storage)가 나오게 됨.
웹 스토리지는 웹 브라우저가 직접 데이터를 저장할 수 있게 해줌. 또한 웹 스토리지는 사용자 측에서 좀 더 많은 양의 정보를 안전하게 저장할 수 있게 해줌. 이런 모든 정보는 절대 서버로 전송되지 않으므로 저장된 데이터가 클라이언트에만 존재하기 때문에 네트워크 트래픽 비용 또한 줄여준다는 특징 또한 가지고 있음
이러한 웹 스토리지는 오리진(origin)마다 단 하나씩만 존재함. 오리진(origin)은 도메인(domain)과 프로토콜(protocol) 한 쌍으로 이루어진 식별자로, 하나의 오리진에 속하는 모든 웹 페이지는 같은 데이터를 저장하기 때문에 같은 데이터에 접근할 수 있게 됨(이해안감)
웹 스토리지는 데이터의 지속성과 관련해 두 가지 용도의 저장소 객체를 제공함
로컬스토리지 객체는 보관 기한이 없는 데이터를 저장
따라서 브라우저 탭이 닫히거나, 컴퓨터를 재부팅해도 이 저장소에 저장된 데이터는 사라지지 않음
Windows 전역 객체의 localStorage라는 컬렉션을 통해 저장과 조회가 가능하며, 도메인 마다 별도의 localStorage가 생성됨. 따라서 도메인만 같으면 전역으로 데이터의 공유가 가능해짐
세션스토리지 객체는 하나의 세션만을 위한 데이터를 저장함
데이터를 지속적으로 보관하지 않고 브라우징되고 있는 브라우저 컨텍스트 내에서만 데이터가 유지되기 때문에, 사용자가 브라우저 탭이나 창을 닫으면 이 객체에 저장된 데이터는 사라짐
- 브라우징이란 브라우저 프로그램을 실행해서 인터넷에 들어가 필요한 정보를 찾는 행위를 말함
- 브라우저 컨텍스트란 브라우저가 문서를 표시하는 환경을 말함
각 브라우징 컨텍스트는 특정 출처 및 활성화되고 있는 문서의 출처, 표시했던 모든 문서의 방문기록을 가지고 있다.
저장과 조회는 Windows 전역 객체의 sessionStorage라는 컬렉션을 통해 이루어지며, 도메인 별로 별도로 생성되는데 브라우저가 다르면 서로 다른 영역이 된다는 특징이 있음
즉, 브라우저 두 개를 실행해 같은 페이지를 열었을 때, 브라우저의 컨텍스트가 서로 다르므로 이 두 페이지의 sessionStorage는 각 별개의 영역으로 인지되어 서로 데이터의 공유가 불가능해짐
웹 스토리지는 클라이언트에 데이터를 저장하기 위한 두 가지 객체를 제공함.
window.localStorage
: 만료 날짜가 없는 데이터를 저장할 때 쓰입니다.
window.sessionStorage
: 세션이 있는 데이터를 저장할 때 쓰입니다. (브라우저 탭을 닫으면 손실되는 것을 의도한 데이터를 저장할 때 쓰입니다.)
브라우저 컨텍스트 내에서 저장한 데이터를 가지고 활용할 수 있기 때문에 복구 및 백업에 관련된 기능에 주로 사용됨
블로그 글을 작성하다가 사용자가 창을 벗어난 경우 관련 작성 내용을 복구하거나 백업해주는 기능
사용자가 입력 form을 통해 정보를 입력하다 페이지에서 벗어난 경우 복구 및 백업해주는 기능
현재 읽은 글의 히스토리 저장(카운팅, 혹은 읽은 글 표시 등으로 활용)
브라우저 렌더링에서 렌더링(rendering)이란 HTML, CSS, JavaScript 등 개발자가 작성한 문서가 브라우저에서 출력되는 과정을 의미함.
현존하는 브라우저마다 다르지만, 브라우저는 기본적으로 렌더링을 수행하는 렌더링 엔진을 가지고 있다.
파싱이란 프로그래밍 언어로 작성된 파일을 실행시키기 위해 구문 분석(syntax analysis)을 하는 단계
이런 파싱을 파서(parser)가 진행하며, 일종의 인터프리터나 컴파일러 구성 요소 가운데 하나임
파서는 HTML 파일의 코드를 문법적 의미를 갖는 최소 단위인 토큰(token)으로 한 번 분해하고, 이 토큰들을 문법적 의미와 구조에 따라 노드(node)라는 요소로 바꾼다. 노드들은 상하관계에 따라 하나의 트리를 형성하는데 이를 파스 트리(parse tree), 혹은 문법 트리(syntax tree)라고 부른다.
문서 파싱(document parsing)은 브라우저가 코드를 이해하고 사용할 수 있는 구조로 변환하는 것을 의미
렌더링 과정에서는 HTML 파일을 바탕으로 DOM 트리를 구축하고 및 CSS 파일로 CSSOM 트리를 만드는 것을 파싱한다고 표현함
브라우저는 HTML 문서를 받아들자마자 DOM 트리로 파싱합니다. 파싱되며 HTML 토큰이 만들어지는데, 이 토큰에는 시작태그와 마침태그가 포함되고, 속성 이름과 값도 포함이 됩니다. 이런 토큰화된 입력값은 파서에 의해 노드가 되고, DOM 트리를 구성함
브라우저는 HTML 문서를 파싱하면서 CSS스타일을 만날 경우,
텍스트를 CSS 스타일링 레이아웃과 페인팅에 사용하는 데이터 구조인 CSSOM 트리로 파싱하고, 태그를 만날 경우 렌더링을 차단하면서 HTML 파싱 또한 중단합니다.
이어 script 파일을 다운 받아 파싱하고 실행시킨 뒤, 다시 HTML 파일을 파싱하기 시작합니다.
파싱은 문서에 작성된 언어 또는 형식의 규칙에 따르는데 파싱할 수 있는 모든 형식은 정해진 용어와 구문 규칙에 따라야 한다. 따라서 형식을 잘 갖춘 문서라면 파싱 과정은 직관적이고 빠르게 진행됨
DOM은 HTML문서의 요소들의 중첩 관계를 기반으로 노드들을 트리 구조로 구성한 것을 의미하며, Document Object Model의 줄임말이다.
브라우저는 JavaScript 언어만 알아듣기 때문에 HTML의 태그나 속성들을 이해하지 못합니다. 또한 응답으로 받아온 HTML 문서는 텍스트로만 이뤄져 있습니다. 그래서 이해할 수 있는 형태인 객체로 바꿔준 것이 바로 DOM 트리임
[그림] HTML 파일을 DOM 트리 구조로 변환하면 이렇게 나옵니다.
html 파일을 DOM 트리로 파싱하던 브라우저는 <link>
, <style>
태그를 만나게 되면 파싱을 잠시 멈추고 해당 리소스 파일을 서버로 요청한다. 이렇게 요청한 파일을 html 파일과 마찬가지로 파싱을 하는데, 파일을 파싱해 만든 트리를 CSSOM이라고 한다. CSS Object Model의 줄임말이며, 이 CSSOM 트리를 구축하고 나면 브라우저는 다시 html 파일의 파싱을 멈췄던 부분으로 돌아가서 마저 DOM 트리를 파싱한다.
[그림] CSS 파일을 CSSOM 트리 구조로 변환하면 이렇게 나옵니다.
하나 알아둬야 할 부분: CSS는 부모의 속성을 자식이 상속 받는다는 점.
예) body가 부모 요소이고 font-size가 16px인 속성을 가지고 있는데, 그 밑에 있는 p는 자식 요소이기 때문에 부모 요소인 body가 갖고 있던 속성을 상속 받으면서 동시에 자신이 가지고 있는 속성인 font-weight 속성까지 가지므로 2개의 속성을 갖게 된다.
DOM 트리와 CSSOM 트리는 트리 구조로 되어 있기 때문에 비슷하게 생겼지만, 애초에 리소스부터 틀린 서로 다른 속성을 가진 독립적인 트리이다. 그렇기 때문에 브라우저 위에 웹사이트를 표시하기 위해서는 이 둘을 합치는 작업이 반드시 필요
렌더 트리는 이름처럼 렌더링을 목적으로 만들어지는 트리이다. 렌더링은 사용자에게 브라우저가 보여주고자 하는 화면을 그리는 과정이므로, 보이지 않을 요소들은 이 트리에 포함시키지 않는다.
예를 들어, DOM 트리의 나 CSSOM 트리의 display:none과 같이 사용자에게 보여주지 않아도 되거나, 보여주지 말아야 할 태그나 요소는 렌더 트리에서 제외됨.
브라우저 렌더링에서 “레이아웃” 과정은 우리가 웹 개발에서 평소 말하는 웹 페이지 레이아웃 짜기, 디자이너들의 레이아웃과는 다른 개념임
여기서 말하는 레이아웃은 렌더트리를 기반으로 HTML 요소의 레이아웃(위치, 크기 등)을 계산하여 브라우저 화면 어디에 배치할 지 결정하는 과정임
위의 그림에서도 볼 수 있듯이 DOM, CSSOM에 있던 속성들이 합쳐서 렌더 트리를 구성하는 것을 볼 수 있음. 그러나 아직까지 렌더 트리는 텍스트로 구성된 객체로만 보임. 페인팅이라는 작업을 거쳐야지 브라우저 위의 화면으로 그려지게 됨
렌더 트리에는 CSSOM 트리에 있던 속성들이 합쳐져 있다. 따라서 렌더 트리에는 요소들의 크기, 혹은 위치에 관련된 정보들이 들어 있다. 하지만 아직까지 이 정보들은 그저 각 요소에 관련된 정보일 뿐, 전체 화면에서 정확히 어디에 위치하는가에 대해서는 알지 못한다.
이런 계산을 브라우저의 렌더링 엔진이 한다.
브라우저는 각 요소들이 전체 화면에서 어디에, 어떤 크기로, 어떻게 배치가 되어야 하는지 파악하기 위해 렌더트리를 위에서 아래로 읽어 내려간다. 그리고 모든 값은 절대적인 단위인 px 값으로 변환됨
위치에 대한 계산을 마치면 이제 화면에 보여주기 위해 브라우저는 화면 위에 레이아웃에서 결정된 대로 그림을 그리기 시작한다.
브라우저 화면은 픽셀이라고 하는 작은 점들로 구성되어 있다. 각 정보를 가진 픽셀들이 모여 하나의 화면을 구성하는 것.
페인팅은 이런 픽셀에 대한 정보들을 바탕으로 픽셀을 채워나가는 과정이며, 이 과정까지 해내야 텍스트에 불과했던 HTML 파일의 내용들이 이미지화된 모습으로 브라우저 화면에 띄워지는 것임
💡 프론트엔드 엔지니어로서 브라우저 렌더링 과정을 알아둔다면 렌더링 최적화 시 어떤 단계에서 최적화를 시켜야 할 지 알 수 있게 됨!
만약에 사용자가 브라우저 화면을 늘리거나 줄이는 등 크기를 조절하거나, 다른 사이트로 이동을 하는 등 화면에 요소가 추가 되거나 삭제, 혹은 아예 다른 요소들을 불러와야 하는 상황이 생기면 당연히 화면에 있던 요소들의 크기가 바뀌게 됨
사용자의 입장에서는 당연한 과정이지만, 이렇게 화면에 나타나는 모습을 바꾸기 위해서는 모든 요소의 위치와 크기를 다시 계산하고, 다시 그려 보여주어야 한다.
이런 식으로 어떤 웹 인터랙션으로 인해 렌더링 과정의 레이아웃을 반복해 수행하는 것을 리플로우, 페인트 과정을 반복해 수행하는 것을 리페인트라고 한다.
사용자의 눈에 일련의 과정이 부드럽게 처리 되려면 초당 60 프레임은 반드시 유지시켜야 함.(예시: 플립북)
사용자 눈에 한 화면을, 혹은 어떤 애니메이션을 끊김없이 부드럽고 연속적으로 보여주기 위해서 브라우저는 약 60장의 미세한 변화가 있는 그림들을 전부 준비 해놓고 그것을 1초 안에 빠르게 보여주는 것과 같음.
즉, 1초라는 짧은 시간 안에 브라우저는 60장 가량의 레이아웃과 페인트 과정을 동시에 처리해야만 하는 것인데 여기서 중요하게 알아야 하는 점은 DOM은 변경이 되면 렌더 트리를 다시 구축하기 때문에, 변경이 될 때마다 리플로우와 리페인트를 다시 해야 한다는 것임.
리플로우 하는 과정은 렌더링을 다시 하는 것이기 때문에 배치를 위한 연산을 해야 해 실제로 CPU를 많이 차지하고, 리페인트는 페인트를 다시 하는 것이라 픽셀을 다시 화면에 찍어 그려야 하기 때문에 GPU를 많이 차지한다.
이는 프레임 드랍(Frame Drop) 현상과 직접적인 연관이 있다.
이는 프레임 드랍의 극단적인 예이다.
프레임 드랍은 초당 60프레임으로 유지시키던 프레임의 수가 브라우저의 과부하로 인해 줄어드는 현상을 뜻한다.
즉 없어진 프레임은 렌더링 엔진이 인식할 수 없다. 플립북에서 뜯어져 사라진 장면은 아무리 플립북을 연속해서 넘겨도 찾아볼 수 없는 것과 마찬가지임.
그렇기 때문에 렌더링 엔진은 드랍된 프레임을 브라우저 화면에 그리지 못한다. 이렇게 되면 유저는 해당 현상을 "화면이 멈춘다, 버벅인다" 라고 느끼게 됩니다. 프레임 드랍 현상이 생기면 유저 경험(UX)에 좋지 않기 때문에, 최적화를 고려해야만 함.
어떻게 최적화를 시킬 수 있을까?
레이아웃 과정에서 불필요하게 계산해야 할 것이 많아지면 엔진도 결국 컴퓨팅 파워에 기대기 때문에 과부하가 불가피하게 생기게 됨
따라서 불필요한 레이아웃 하나만 줄여도 렌더링 퍼포먼스를 최적화할 수 있다.
CSSOM 트리의 CSS 속성 중에 레이아웃을 발생시키는 속성들이 존재하. 이 속성을 사용하게 되면 그때마다 변경이 되어 렌더 트리를 만들고, 레이아웃을 발생시키고, 페인트를 하는 과정이 연속적으로 발생하게 됨.
따라서 이런 레이아웃을 발생시키는 속성을 피하면 해당 과정이 발생하는 횟수를 줄일 수 있다
레이아웃과 페인트 과정은 별개의 과정처럼 보일 수 있으나 리플로우 시 리페인트는 필연적으로 일어나므로 가능하다면 리플로우가 발생하는 속성보다 리페인트만 발생하는 속성을 사용해주는 게 좋다.
프론트엔드 개발자가 되어 브라우저 렌더링의 최적화 과정을 수행하고자 한다면 레이아웃이 일어나는 상황을 최대한 피하는 것이 좋기에 해당 속성을 알아두는 것이 굉장히 중요.
다음은 각각 리플로우, 리페인트가 일어나는 CSS 속성들임
리플로우가 일어나는 대표적인 속성
위치, 혹은 너비와 관련된 속성이 많다.
예) left 속성 중 left-top, left-bottom 속성을 사용하면 위치가 변경이 됨. (position 속성과 같이 씁니다.) 이 left 속성은 레이아웃을 발생시키는 속성. 따라서 이 속성을 가지고 애니메이션을 만들 때는 프레임 유지를 보장하기 어려워짐
그래서 이 속성을 피해 transform이라는 속성을 사용합니다. transform에 있는 translate를 사용하면 좌표 값을 사용해 위치를 이동하지만, 레이아웃을 발생시키지 않기 때문에 페인트만 다시 발생시키는 쪽으로 렌더링 과정이 일어나기 때문에 유지하고자 하는 프레임 수를 기대할 수 있다.
리페인트가 일어나는 대표적인 속성
리페인트가 일어나지 않게 해주는 opacity라는 속성도 있다. visibility/display 보다 opacitiy를 사용하는 것이 성능 개선에 도움이 됨
JavaScript + CSS를 조합한 애니메이션이 많거나, 레이아웃 변화가 많은 요소의 경우 position을 absolute 또는 fixed를 사용해주면 영향을 받는 주변 노드들을 줄여줄 수 있다.
fixed와 같이 영향을 받는 노드가 전혀 없는 경우 리플로우 과정이 필요 없기 때문에 리페인트 연산 비용만 들일 수 있다.
프론트엔드 개발을 하다보면 다양하고 복잡한 요구 사항에 대응해야 하는 경우도 많아지고, 화면이 라이브 데이터에 따라 실시간으로, 빠르게 수많은 변경을 일으켜야 하는 경우도 생기게 됨!
기기들의 디스플레이의 종류에 반응해 그에 맞도록 적절히 UI 요소들이 배치되도록 설계하는 능력 또한 프론트엔드 엔지니어에게 요구되고 있음
전자기기의 발전으로 인해 데스크탑 뿐만 아니라 태블릿, 스마트폰 등의 전자기기에서 웹에 접속할 수 있게 되었지만, 전자기기들의 화면의 크기가 다양한 탓에 여러가지 버전의 웹페이지를 만들어야 하는 경우가 발생하게 됨. 이러한 불편함을 해결하기 위해 반응형 웹페이지가 탄생함
여러 장치의 다양한 특성에 대응하는 하나의 웹 문서 또는 사이트로써 브라우저의 크기(스크린의 크기, 디바이스의 종류)에 실시간으로 반응하여 크기에 따라 레이아웃이 변하는 웹 사이트를 의미함.
즉, 하나의 소스 코드로 모든 스크린에 최적화된 웹 사이트를 구축할 수 있는 방법론으로, 디바이스 종류에 따라 웹페이지의 크기가 자동적으로 재조정되는 것임.
사이트를 이루는 소스 코드는 하나지만 접속하는 스크린 사이즈에 따라 레이아웃을 유동적으로 달리 보여줌
[그림] 이제는 모바일 기기에서 어떻게 보일 지를 먼저 고려하며 웹을 디자인하게 되었습니다.
반응형 웹에서 빼놓을 수 없는 개념은 모바일 퍼스트라는 개념임
모바일 퍼스트(mobile first)란 (Luke Wroblewski)가 최초로 주장한 철학이자 전략이며, 사용자 경험(UX)을 디자인할 때 모바일일 경우에 최우선으로 초점을 맞춰 디자인하는 것
현재는 데스크탑 유저보다 모바일 유저가 공유하는 정보가 많다는 것은 부정할 수 없는 사실임
그렇다고 모바일 웹 버전을 늘리는 수준으로만 데스크탑 웹을 구축해서는 안 됨. 따라서 현재는 보다 효율적으로 PC부터 아이패드, 태블릿PC, 스마트폰까지 총망라하는 반응형웹을 구조하는 기술력이 주목받고 있다.
하나의 URL을 기반으로 화면이 바뀐다.
반응형 웹 디자인은 유연한 레이아웃에 대응하여 항상 최적의 화면을 제공함으로써 다양한 스크린 사이즈를 지닌 디바이스에 적응할 수 있다.
[그림] 인스타그램 : 하나의 URL을 기반으로 화면이 바뀌는 대표적인 예시
[그림] 네이버 : 특정 장치에 최적화된 페이지로 연결되는 별도의 URL이 있는 대표적인 예시
❌ 그러나 위의 예시처럼 특정 장치에 최적화된 페이지로 연결되는 별도의 URL이 있다면 반응형 웹이라고 부르지 않는다. 특정 장치에 연결이 되는 별도의 URL은 모바일의 경우 대개 m.domainname.com 같은 식으로, 도메인 앞에 모바일을 의미하는 “m”을 붙임으로써 구분한다. 특정 장치에 연결이 되는 별도의 URL과 화면이 구비된 웹 사이트의 경우, 데스크탑 버전의 웹 사이트를 띄운 브라우저를 줄였을 때 반응하지 않는다는 특징이 있다.
하나의 콘텐츠에 오직 하나의 HTML 소스만 있기 때문에 하나의 소스를 수정하면 모든 스크린 사이즈에 맞춰 컨텐츠가 최적화되기 때문에 유지보수가 효율적이다
웹페이지 내용을 수정해야 할 때도 하나의 페이지에서만 적용해도 동일하게 반영되고, 하나의 소스 코드로 관리가 가능하기 때문에 초기 개발 비용 및 유지 관리 비용의 절감 효과를 가져올 수 있다.
사용자 입장에서도 기기에 구애받지 않고 항상 최적의 화면을 경험할 수 있게 됨
검색엔진 최적화(SEO)에 유리해 검색 결과에서 상위권에 나타나게 할 수 있다.
반응형 웹은 하나의 URL을 기반으로 화면이 바뀌므로 PC용 URL과 모바일용 URL이 동일하다. 따라서 검색 포털 등 광고를 통한 사용자 접속을 효율적으로 관리할 수 있다.
이런 모바일 환경에서도 적응하게끔 만들어진 반응형 웹은 모바일을 전용으로 하는 사이트에 비해 무겁다.
반응형 웹 디자인은 읽어들여야 할 소스가 많아 불필요하게 많은 데이터를 소비하기 때문에 이는 사이트 속도와 직결이 됨
로딩의 속도나 이미지 리사이징의 문제로 성능이 떨어질 수 있으며, 실제로 사용하지 않은 자원을 전송 받거나 실제 사용되는 이미지보다 더 큰 이미지를 사용할 수 있음.
현재 존재하는 웹 브라우저는 스펙 및 사양이 제각기 다르기 때문에 하나의 웹 브라우저에서는 잘 반응하던 HTML 소스가 다른 웹 브라우저에서는 디자인이 깨지는 경우가 발생할 수 있다.
또한 CSS3의 특성상 인터넷 익스플로러(IE) 8 버전 이하에서는 사용이 불가능 해짐. 이런 문제 때문에 디자인의 자유도가 떨어지며, 100% 맞춤 디자인이 어렵다는 점이 발생함
CSS2.1 부터 미디어 타입으로 단말기 종류에 따라 각각 다른 스타일을 적용시키는 게 가능해졌다.
그러나 기기의 특성을 정확히 판단하기 어렵다는 단점 때문에 널리 사용되지 않았으나, CSS3부터는 이 미디어 타입을 개선하여 좀 더 구체적인 조건으로 필요한 스타일을 적용할 수 있도록 함
이런 미디어 쿼리는 반응형 웹 디자인의 핵심 부분입니다. 뷰포트(브라우저 창)의 크기에 따라 서로 다른 조판을 생성할 수 있기 때문이닷!
1.
<link href="css파일이름.css" media="screen and (min-width: 400px) and (max-width: 1000px)" rel="stylesheet">
CSS 파일을 HTML 파일에 적용하던 것처럼 <head>
태그 안에 <link>
태그를 위치 시킨다.
다른 css 파일을 적용할 때와 다른 점은 미디어 속성을 사용하여 조건을 지정한다는 점입니다. 미디어 속성 내 해당 조건을 만족할 때에만 해당 css 파일을 불러오게 됨
2.
<style type="text/css" media="screen and (min-width: 400px) and (max-width: 1000px)">
/* 여기 css를 작성합니다. */
</style>
HTML 파일 내 <head>
태그 안에서 <style>
태그를 열어 미디어 쿼리를 작성할 수도 있다. 이 방법도 미디어 속성 내 해당 조건을 만족할 때에만 해당 스타일을 적용하게 됨.
3. CSS 파일 혹은 태그 안에서 직접 미디어 쿼리 작성
CSS 파일 안 또는 태그 안에서 직접 미디어 쿼리를 작성하여 해당 미디어 쿼리의 조건을 만족할 때 스타일을 적용시키는 방법도 있다.
@media 미디어 타입 (조건(너비 및 높이)) {
(CSS 입력하는 부분)
}
--예제
@media screen (max-width: 400px) {
body {
color: red;
}
}
미디어 타입
: 코드가 어떤 미디어를 위한 것인지 브라우저에 알려줍니다.조건(너비 및 높이)
: 지정한 창의 너비나 높이를 기준으로 기준이 만족되면 스타일이 적용되고, 만족되지 않으면 적용되지 않습니다.CSS 입력하는 부분
: 조건문을 통과하고, 미디어 타입이 올바른 경우 스타일이 적용됩니다.지정할 수 있는 미디어 타입은 여러 종류가 있다.
반응형 디자인을 만들기 위해 가장 많이 사용하는 기능은 뷰포트 너비이며, min-width
와 max-width
, width
등의 미디어 기능을 활용해 뷰포트가 특정 너비 이상 또는 이하인 경우 CSS를 적용할 수 있다.
@media screen and (width: 600px) {
body {
color : red;
}
}
width(혹은 height)는 브라우저의 창 크기에 사용할 수 있습니다. 따라서 min-
혹은 max-
접두사를 붙이게 되면 최소값인지 최대값인지 표시할 수 있다.
@media screen and (max-width: 400px) {
body {
color: blue;
}
}
예를 들어, 뷰포트가 400px 보다 좁은 경우 색을 파란색으로 만들기 위해 이런 식으로 max-width 를 사용할 수 있다.
세로 모드인지 가로 모드인지 검사하여 CSS 스타일을 주고 싶은 경우, orientation으로 검사 할 수 있다.
@media (orientation: landscape) {
body {
color: rebeccapurple;
}
}
예를 들어 장치가 가로 방향인 경우, 해당 코드를 통해 본문의 텍스트 색상을 변경할 수 있다.
미디어 쿼리를 결합하거나, 쿼리 목록을 만들거나 하는 식으로 미디어 쿼리를 좀 더 깊이 있게도 사용할 수 있다.
and
를 사용해 미디어 기능을 합칠 수 있다.
@media screen and (min-width: 400px) and (orientation: landscape) {
body {
color: blue;
}
}
여기서 HTML 본문 텍스트가 파란색이 되는 유일한 경우는 뷰포트의 너비가 최소 400픽셀 이상이고 장치가 가로 모드인 경우에만 해당함.
두 조건을 모두 만족해야지 쿼리 안의 CSS 스타일이 적용됨
콤마로 분리를 한다면 미디어 쿼리의 해당 조건 중 어느 하나를 만족시킬 때 CSS 스타일을 적용시킬 수 있다
@media screen and (min-width: 600px), screen and (orientation: landscape) {
body {
color: blue;
}
}
뷰포트의 넓이가 600px 이상이거나, 장치가 가로 방향인 경우 텍스트는 파란색이 된다.
이 중 하나라도 조건을 만족한다면 쿼리 안의 CSS 스타일이 적용된다.
not
연산자를 사용하게 되면 미디어 쿼리의 의미를 반대로 적용시킵니다.
@media not all and (orientation: landscape) {
body {
color: blue;
}
}
이 예시는 방향이 세로인 경우에만 텍스트가 파란색으로 적용됨
[TIL]react, styled-component를 활용해 반응형 웹사이트 만들기
[CSS] 반응형 웹 디자인 적용하기 (styled-component에서 media query 적용)
CSS 애니메이션은 여러 개의 CSS 스타일을 부드럽게 전환시켜줌
그 중에서도 @keyframes
키워드를 활용하면 시간 순서대로 정밀하게 짜여진 애니메이션을 만들 수 있다.
키프레임을 활용하기 위해서는 우선 CSS로 키프레임 블록을 만들어야 함
/* '%' 단위로 시간 진행에 따른 상태를 작성해주면 됩니다. */
@keyframes 애니메이션이름 {
0% { /* from 이라고 작성해도 됩니다.*/
CSS속성 : 속성값;
}
50% { /* 애니메이션 진행도에 따른 스타일을 설정합니다. */
/* 필요하다면 1부터 99까지도, 소수점까지도 모두 작성해도 됩니다.*/
CSS속성 : 속성값;
}
100% { /* to 라고 작성해도 됩니다.*/
CSS속성 : 속성값;
}
}
해당 방법으로 회전하는 키프레임 애니메이션을 만들어보자
@keyframes lotate {
0% {
transform : rotate(0deg)
}
50% {
transform : rotate(180deg)
}
100% {
transform : rotate(360deg)
}
}
/* 시작 시점에선 0도, 50% 시점에선 180도, 완료 시점에선 360도 회전시키는 애니메이션입니다. */
애니메이션을 적용시키고 싶은 요소에 animation 속성으로 키프레임 이름을 불러오면 사용할 수 있다!
💡 그런데 키프레임을 사용하기 위해서는 애니메이션 이름 외에도 다양한 속성을 작성해줘야 함
animation
에 전달해줄 수 있는 속성들은 다음과 같다
animation
: 띄어쓰기로 쭉 나열하면 아래의 속성들을 한 번에 지정할 수 있음animation-name
: 애니메이션의 중간 상태를 지정하는 이름. @keyframes 블록에 작성animation-duration
: 한 싸이클의 애니메이션이 재생될 시간 지정animation-delay
: 애니메이션의 시작을 지연시킬 시간 지정animation-direction
: 애니메이션 재생 방향을 지정animation-iteration-count
: 애니메이션이 몇 번 반복될지 지정animation-play-state
: 애니메이션을 재생 상태. 멈추거나 다시 재생 시킬 수 있음animation-timing-function
: 중간 상태들의 전환을 어떤 시간간격으로 진행할지 지정animation-fill-mode
: 애니메이션이 재생 전 후의 상태 지정애니메이션을 적용하고 싶은 요소에 animation
속성의 첫번째 값으로, 혹은 animation-name
이라는 속성으로 @keyframes 키워드를 사용해서 만든 애니메이션 이름을 작성해주면 됨
적용할요소 {
animation : lotate;
}
적용할요소 {
animation-name : lotate;
}
하지만 이 속성만으로는 애니메이션이 재생되지 않는다. 여러 속성들 중 최소
animation-name
과animation-duration
은 지정해줘야 애니메이션이 실행되기 때문임!
애니메이션이 재생될 시간을 animation
속성의 두번째 값으로, 혹은 animation-dutation
이라는 속성으로 시간 단위로 작성하자.
작성해주지 않을 경우 기본값이 0
이기 때문에 애니메이션이 재생되지 않음
적용할요소 {
animation : lotate 3s ;
}
적용할요소{
animation-name : lotate;
animation-duration : 3s;
}
애니메이션 재생을 미룰 시간을 지정한다.
역시 animation
속성에 띄어쓰기로 구분해주거나, 혹은 animation-dutation
이라는 속성으로 시간 단위로 작성함
적용할요소 {
animation : lotate 3s 3s;
}
적용할요소{
animation-name : lotate;
animation-duration : 3s;
animation-delay : 3s;
}
animation-delay 의 값을 각각 0s
,3s
로 지정해줬을 때 0s
는 즉시, 3s
는 3초 후에 애니메이션이 재생됨
애니메이션 재생 방향을 지정합니다. 역시 animation
속성에 띄어쓰기로 구분해주거나, 혹은 animation-direction
이라는 속성으로 작성
적용할요소 {
animation : lotate 3s reverse ;
}
적용할요소 {
animation-name : lotate;
animation-duration : 3s;
animation-direction : arternate;
}
전달해줄 수 있는 값은 다음과 같다.
normal
: 기본 값. 재생이 끝나면 처음부터 다시 재생합니다.reverse
: 역방향으로 재생합니다.alternate
: 순방향부터 역방향을 번갈아가며 재생합니다.alternate-reverse
: 역방향부터 순방향을 번갈아가며 재생합니다.reverse가 시계방향으로 돔(보편적인 회전!)
애니메이션이 몇 번 재생될지 지정한다. 기본 값은 1
이며, 설정한 횟수만큼 애니메이션이 반복 재생된다.
infinite
로 설정할 경우 무한 반복 되며, 소수점을 작성할 경우 재생 도중 처음 상태로 돌아감. 예를 들어, 재생 시간이 3초일 때, 0.6을 전달할 경우 3 * 0.6을 한 1.8초만큼만 재생되고 처음 상태로 돌아가게 됨.
적용할요소 {
animation : lotate 3s infinite ;
/* 애니메이션이 무한 반복 됩니다. */
}
적용할요소 {
animation-name : lotate;
animation-duration : 3s;
animation-iteration-count : 3 ;
/* 애니메이션이 3번 반복 됩니다. */
}
애니메이션이 재생 상태를 설정한다.
기본 값인 running
, 애니메이션을 정지시키는 pause
를 값으로 지정할 수 있다.
보통 이벤트로 애니메이션을 재생 상태를 변경할 때 사용한다.
적용할요소 {
animation : lotate 3s pause ;
}
적용할요소 {
animation-name : lotate;
animation-duration : 3s;
animation-play-state : pause ;
}
애니메이션의 진행 속도를 설정한다.
애니메이션 재생 전 후의 상태를 지정한다.
none
: 기본 값. 재생중이 아닌 경우 요소의 스타일을 유지합니다.forwards
: 재생중이 아닌 경우 마지막 키프레임 스타일을 유지합니다.backwards
: 재생중이 아닌 경우 첫 번째 키프레임 스타일을 유지합니다.both
: 재생 전에는 첫 번째 키프레임 스타일을, 재생 후에는 마지막 키프레임 스타일을 유지합니다.적용할 요소 {
**animation-name : lotate;** /* lotate 라는 이름의 키프레임 애니메이션을 */
animation-duration : 3s; /* 3초 동안 재생하며, */
animation-iteration-count : infinite; /* 애니메이션을 무한 반복하고, */
animation-timing-function : linear; /* 선형으로 재생합니다. */
}
/* 아래와 같이 일괄 작성해도 동일하게 적용됩니다. */
적용할 요소 {
animation : **lotate** 3s infinite linear;
}
3초동안 로고가 서서히 회전하는 것을 확인할 수 있다.
이번에는 키프레임 설정에서 중간값만 50%에서 80%로 바꿔보자.
그 결과 애니메이션이 재생되는 3초중에서 80%인 2.4초동안 180도 회전하고, 나머지 20%인 0.6초동안 360도까지 회전하는 것을 확인할 수 있
이처럼 키프레임을 설정하면서 주는 중간값은 애니메이션 재생 시간을 기준으로 함
HTML의 <canvas>
태그와 Javascript를 사용하면 다양한 그래픽 요소를 만들 수 있다.
순한 도형을 그리는 것은 물론, 데이터 시각화, 애니메이션, 웹 게임 등 사용하기에 따라 무궁무진한 콘텐츠를 만들어낼 수 있다.
일단은 캔버스 태그를 작성하는 것으로 시작됨. 캔버스는 canvas 엘리먼트를 DOM으로 조작하는 방식으로 작성됨. 따라서 엘리먼트를 선택할 때 사용할 id를 작성해주는 것이 좋다.
<canvas id="canvas">
캔버스를 지원하지 않는 브라우저에서는 캔버스 대신 태그 사이 내용이 표시됩니다.
</canvas>
이제 자바스크립트를 사용해서 엘리먼트를 선택해준다.
const canvas = document.querySelector("#canvas");
캔버스를 본격적으로 다루기 전에, 너비와 높이를 설정해주어야 함.
(크기를 설정해주지 않으면 기본적으로 300픽셀 * 150픽셀의 사이즈로 생성됨)
설정 방법에는 두 가지가 있다.
1. 태그 속성으로 설정하기
width
, height
속성으로 설정해줄 수 있다.width
, height
속성은 픽셀 단위로만 명시해야 인식하도록 되어 있기 때문<canvas id="canvas" width="500" height="500"></canvas>
// 500픽셀 * 500픽셀로 설정됩니다.
<canvas id="canvas" width="50vw" height="40vh"></canvas>
// vw, vh를 전달했지만 50픽셀 * 40픽셀로 설정됩니다.
2. DOM으로 설정해주는 방법
canvas.width = 50vw;
canvas.height = 40vh;
// DOM으로 설정하면 50vw * 40vh 로 단위값을 지정해도 설정이 됩니다.
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
// 화면 크기에 맞춰서 설정해줄 수도 있습니다.
이후 실습에서 사각형 및 간단한 클릭 이벤트를 만들기 위해 몇 가지의 속성과 메소드를 사용할 예정. 해당 속성과 메소드는 Mozlia의 Canvas API에서 확인할 수 있음..
참고자료
https://developer.mozilla.org/ko/docs/Web/API/Canvas_API
https://www.w3schools.com/tags/ref_canvas.asp
fillStyle
속성으로 사각형 내부를 색칠할 색상을 설정해준다.ctx.fillStyle = 'blue'
fillRect
메소드를 사용해 사각형을 그려준다.ctx.fillRext = (10, 10, 100, 50)
lineWidth
속성으로 선의 굵기를, strokeStyle
속성으로 선의 색상을 설정해준다.ctx.lineWidth = 5;
ctx.strokeStyle = "black";
strokeRect
메소드를 사용해 사각형을 그려준다.ctx.strokeRect(10, 10, 100, 50)
//전달 인자는 이번에도 순서대로 x좌표, y좌표, 가로길이, 세로길이 입니다.
//위에서 그려준 색칠된 사각형 바로 위에 그려보세요.
clearRect
메소드로 지울 범위를 설정해준다.ctx.clearRect( 20, 20, 80, 30)
// 전달 인자는 역시 동일합니다. 그려놓은 사각형 가운데 부분을 지워보세요.
캔버스를 클릭하면 클릭하는 위치에 사각형을 그리는 이벤트를 만들어보자.
1. 우선 클릭이벤트가 일어날 때의 마우스의 위치를 구한다.
2. 클릭할 때 캔버스 위에서의 마우스 위치를 구하려면, 화면에서의 마우스 위치에서 화면에서의 캔버스 위치를 빼면 됨
화면상 마우스 위치를 구하는 이벤트 객체의 속성
event.clientX
event.clientY
화면상 캔버스의 위치를 구하는 속성
ctx.canvas.offsetLeft
ctx.canvas.offsetTop
혹은 event.offsetX
, event.offsetY
로 바로 구할 수도 있다.
canvas.onclick = function (event) {
const x = event.clientX - ctx.canvas.offsetLeft
const y = event.clientY - ctx.canvas.offsetTop
// 구한 좌표를 이용해서 사각형을 그리는 코드를 작성해보겠습니다.
ctx.fillRect(x - 15, y - 15, 30, 30);
// 클릭할 때마다 30픽셀*30픽셀 크기의 사각형을 그리도록 하려고 합니다.
// 이 때, x, y를 그대로 전달하면 해당 좌표부터 사각형이 시작되어 어색한 느낌을 줍니다.
// 클릭한 위치를 사각형의 정중앙이 되게 하려면 사각형크기/2 한 만큼 좌표에서 빼주면 됩니다.
// 따라서 x - 15, y - 15 를 전달합니다.
}