반응형

다국어 홈페이지 사이드 프로젝트에 접속한 전세계 유저 리스트

 

전 세계 사람들이 나에게 1원씩만(광고 수익) 주면 부자가 되지 않을까..? 싶어서 

16개국 다국어 지원을 통하여 사이드 프로젝트 홈페이지를 만들고 테스트해봤는데요.

어느정도 만족스러운 결과가 나와서 그 과정을 이 글에 공유해봅니다.

다국어 지원은 chatgpt AI로 번역했고, SEO 다국어 지원이 가능한지 가설 및 검증은 아래 링크의 "두루미스" 플랫폼을 참고해서 구현했습니다.

https://blog.naver.com/dreamyoungs_inc/223425945113

 

두루미스에 글을 작성하면 다른 언어들로 검색이 잘 될까요?

두루미스(durumis) 블로그 서비스를 개발하면서 저희도 가끔 고민했던 부분은 구글 검색에 다양한 언어로 ...

blog.naver.com

 

그리고 이 글에서는 "i18n을 어떻게 적용하는지"까지 내용에 넣으면 글이 너무 길어지기 때문에 다루지 않습니다.

next-intl등 여러 좋은 방식을 찾아보길 추천드립니다.

 

SEO란?


SEO
(Search Engine Optimization, 검색엔진 최적화)는 우리가 작성한 블로그 글이 구글 같은 검색 엔진 결과에서 더 잘 보이도록 만들어주는 과정입니다. 처음에는 다소 복잡해 보일 수 있지만, 하나씩 따라 해 보시면 분명 홈페이지 노출에 큰 도움이 될 거예요. 이 글에서는 SEO의 기초 개념부터 온페이지/테크니컬/오프페이지 SEO, 구조화 데이터 활용, 유용한 도구, 그리고 배포 전 체크리스트까지 차근차근 설명해 하겠습니다.

 

1. SEO 기본 용어 이해하기


먼저 SEO를 공부할 때 자주 접하는 핵심 용어들을 알아보겠습니다. 어려운 영어 용어도 많지만, 최대한 쉽게 풀어서 설명해 드릴게요.

 

  • 크롤링 (Crawling): 검색 엔진의 로봇 프로그램인 크롤러(crawler)가 웹사이트의 페이지들을 찾아다니며 콘텐츠를 수집하는 과정입니다. 예를 들어 구글의 크롤러인 Googlebot이 여러분의 블로그 글을 발견하고 내용을 긁어가는 작업이죠. 크롤링이 잘 되어야 내 블로그 글이 검색엔진에 알려지게 됩니다.

  • 인덱싱 (Indexing): 크롤링한 페이지들을 검색 엔진의 데이터베이스에 저장하고 정리하는 과정입니다. 검색 엔진은 수집된 정보를 분류하고 색인(인덱스)을 만들어 두는데, 도서관에서 책을 분류해 두는 것과 비슷합니다.
     페이지의 키워드나 내용에 따라 잘 정리되어야 사용자가 검색할 때 해당 페이지가 나타날 수 있어요.

  • 검색 결과 페이지 (SERP): Search Engine Results Page의 줄임말로, 말 그대로 사용자가 어떤 키워드로 검색했을 때 나오는 검색 엔진 결과 페이지를 뜻합니다. 특히 첫 번째 페이지 결과를 SERP라고 부르는 경우가 많습니다. 대부분의 사용자들은 검색 결과 첫 페이지까지만 보고 끝내기 때문에(75% 이상이 첫 페이지에서 검색을 마친다고 합니다). 내 블로그 글이 SERP 상위에 노출되는 것이 매우 중요합니다.

  • 메타 태그 (Meta Tag): 웹페이지의 <head> 영역에 들어가는 메타데이터(정보)로서, 검색 엔진과 브라우저에게 페이지 정보를 제공합니다. 대표적으로 제목(title)과 설명(description) 메타태그가 중요합니다. 메타 태그는 방문자 눈에는 직접 보이지 않지만, 검색 결과 목록에 표시되는 제목과 설명을 결정합니다.

  • 캐노니컬 태그 (Canonical Tag): 동일하거나 매우 비슷한 콘텐츠가 여러 URL로 중복돼 있을 때,
    검색 엔진에 "이 페이지의 원본은 이것이에요!" 하고 알려주는 태그입니다. <head> 안에 <link rel="canonical" href="정규 URL"> 형태로 넣습니다. 이 태그를 지정하면 검색 엔진은 중복 페이지들 중 canonical로 지정된 URL을 대표 페이지로 간주하여 랭킹 신호를 집중시킵니다. 예를 들어, example.com?page=1이나 example.com/index.html 등 여러 주소로 접속되는 같은 내용의 페이지가 있다면 하나를 canonical로 지정해야 불필요한 중복 색인을 막을 수 있습니다.

    ** 찾아본 결과, 다국어 홈페이지는 각각 번역한 페이지가 자신의 canoinical Tag 주인이 되는게 유리합니다.!

  • 사이트맵 (sitemap.xml): 웹사이트의 모든 페이지 목록을 모아둔 파일로, 책의 목차 같은 역할을 합니다. 주로 XML 형식으로 작성되며 사이트의 최상위 경로(예: https://내블로그/sitemap.xml)에 위치합니다. 사이트맵을 검색 엔진에 제출해 두면 크롤러가 사이트 구조를 한눈에 파악하여, 평소 찾기 어려운 페이지도 빠짐없이 크롤링하고 인덱싱할 수 있게 됩니다
     (※ 티스토리의 경우 기본적으로 RSS 피드가 사이트맵 역할을 하지만, 필요에 따라 직접 sitemap.xml을 제작해 Search Console에 제출할 수도 있습니다.)

  • robots.txt: 웹사이트 최상위 경로(루트 디렉터리)에 두는 텍스트 파일로, 검색 엔진 크롤러의 접근을 제어하는 지침을 적어둡니다. 예를 들어 "이러이러한 곳은 크롤링하지 마!" 혹은 "이 사이트맵 파일 위치는 여기야!" 하는 내용을 담습니다.
    robots.txt 파일이 없으면 크롤러는 웹사이트에서 접근할 수 있는 모든 페이지를 자유롭게 크롤링하며 특정 페이지를 검색 결과에 나오지 않게 막고 싶다면 robots.txt에 경로를 지정해 차단할 수 있습니다.
    또한 robots.txt 맨 아래에 Sitemap: 지시어를 넣어 사이트맵 위치도 알려줄 수 있어요.

  • 구조화 데이터 (Structured Data): 페이지의 내용을 검색 엔진이 더 체계적으로 이해할 수 있도록 추가하는 특별한 형식의 데이터입니다. 예를 들어 블로그 글이 어떤 주제의 기사인지, 작성자는 누구인지, 게시 날짜는 언제인지 등을 구조화된 형식으로 마크업하면, 검색 엔진이 그것을 읽고 이해하여 검색 결과에 풍부한 정보(리치 결과)를 보여줄 수 있습니다. 구조화 데이터는 주로 스키마.org 형태로 표현하며, HTML <script> 태그 안에 JSON-LD 형식으로 넣는 방법이 권장됩니다. 이를 적용하면 검색 결과에서 별점, 자주 묻는 질문(FAQ), 빵부스러기 경로 등 추가 정보가 표시될 수 있어 클릭률을
  • 높이는 데 도움이 됩니다. (실제로 리치 결과로 표시된 페이지는 일반 결과보다 클릭률이 82% 높았다는 사례도 있습니다)

각 용어가 뭘 뜻하는지 글 아래에서 차근차근 알려드릴게요.

 

2. 온페이지 SEO 최적화


온페이지 SEO
는 말 그대로 페이지 내부에서 할 수 있는 최적화 작업입니다. 블로그 글의 콘텐츠와 HTML 구조를 잘 정돈하여 검색 엔진 친화적으로 만드는 것을 의미합니다. 특히 티스토리 블로그 글을 작성할 때 아래 요소들을 신경 써 보세요.

 

메타 태그 최적화: 제목(title)과 설명(description)

 

온페이지 SEO의 첫 걸음은 메타태그 설정입니다. 검색 엔진은 페이지의 <title> 태그와 <meta name="description"> 태그를 읽어 해당 페이지의 제목과 요약을 이해합니다. 이 두 가지를 잘 써주는 것만으로도 SEO 효과를 크게 볼 수 있습니다:

 

  • 제목 태그: 블로그 글 제목은 <title>에 해당하며, 검색 결과에 파란색 큰 제목으로 표시됩니다. 글 내용과 밀접하며 핵심 키워드를 포함한 제목을 작성하세요. 예를 들어 이 글의 제목이 <title>티스토리 초보 개발자를 위한 블로그 SEO 가이드</title>라면, "티스토리", "개발자", "SEO 가이드" 같은 키워드가 담겨 있죠. 너무 길지 않게 (권장 50~60자 이내) 명확한 제목을 정하는 것이 좋습니다.
  • 메타 설명: <meta name="description" content="..."> 부분에 글 요약을 넣을 수 있습니다. 이 내용은 검색 결과의 회색 설명문구로 나타나며, 사용자들이 이 글을 클릭할지 결정하는 데 큰 영향을 줍니다. 간결하면서도 흥미를 끄는 요약을 1~2문장 정도 작성해 보세요. (티스토리에서는 글 작성 시 본문 요약 또는 설명 입력란이 있다면 활용하시면 됩니다.) 만약 메타 설명을 직접 작성하지 않으면, 검색 엔진이 본문 일부를 자동으로 발췌해 보여줍니다.

예시로 HTML 메타태그를 작성하면 다음과 같습니다

<head>
  <title>티스토리 초보 개발자를 위한 블로그 SEO 가이드</title>
  <meta name="description" content="티스토리에서 기술 블로그를 시작한 초심자 개발자를 위한 SEO 최적화 방법을 소개합니다.">
</head>

 

위와 같이 제목과 설명을 명확히 해 두면, 검색 엔진에 내 콘텐츠를 잘 소개하고 사용자도 클릭하기 전에 내용을 파악하기 쉬워집니다. 티스토리도 잘 찾아보시면 위 태그가 존재해요.

2-1) 시멘틱 태그 및 헤딩 태그 활용: H1~H3 구조 잡기

 

블로그 글을 작성할 때 시멘틱 태그를 체계적으로 사용하는 것도 중요합니다. 예시 한가지로 헤딩(heading) 태그를 들어볼게요.

헤딩은 글의 제목과 소제목들을 나타내는 HTML 태그인데요:

 

  • <h1>: 한 페이지에 단 한 번만 사용하는 최상위 제목입니다. 일반적으로 블로그 글의 제목이 h1에 해당합니다 (티스토리에서는 글 제목을 자동으로 h1으로 처리해줍니다).
  • <h2>, <h3>: 글의 주요 섹션 제목(h2)과 그 하위 소제목(h3)에 사용합니다. 글의 흐름을 논리적으로 나누어 주며, 중요한 키워드를 적절히 포함해 주는 게 좋습니다. 예를 들어 지금 보고 계신 글도 각 큰 챕터 제목이 h2, 그 안의 작은 주제가 h3 태그로 구성되어 있습니다.

검색 엔진은 헤딩 구조를 통해 이 페이지가 어떤 주요 주제와 하위 주제들로 이루어져 있는지 파악합니다. 따라서 헤딩을 계층적으로 잘 쓰면 검색엔진이 콘텐츠를 이해하기 쉽고, 독자들도 글을 한눈에 보기 편해집니다. 아래는 간단한 예시입니다:

 

<h1>블로그 글 제목 (예: 웹 접근성 가이드)</h1>
<p>여는 문단...</p>

<h2>1. 접근성이란 무엇인가?</h2>
<p>...설명...</p>

<h3>접근성의 중요 요소</h3>
<p>...설명...</p>

<h2>2. 접근성을 향상시키는 방법</h2>
<p>...설명...</p>

 

이처럼 h1 -> h2 -> h3 순으로 논리적인 아웃라인을 만들고, 단순히 글자 크기를 키우는 용도로 쓰지 않도록 주의하세요. 디자인을 위해 글자 크기를 키울 때는 CSS를 사용하고, 의미적인 구조는 헤딩 태그로 표현하는 것이 SEO에 좋습니다

 

2-2) 내부 링크 구성하기: 사이트 내 유기적 연결

내부 링크란 내 블로그의 다른 글이나 페이지를 본문 중에 연결하는 것입니다. 예를 들어 이전 글이나 관련 글이 있다면 본문에서 해당 키워드에 하이퍼링크를 걸어두는 식이죠. 내부 링크 최적화를 위한 팁은 다음과 같습니다:

 

  • 관련 글 연결: 현재 작성 중인 글과 주제가 비슷하거나 참고하면 좋을 이전 글이 있다면 링크를 거세요. 예를 들어 "지난 번에 HTTP와 HTTPS 차이에 대해 다뤘는데, 자세한 내용은 이 글에서 확인하세요."처럼요.
  • 키워드 앵커텍스트: 링크를 걸 때 클릭 here 같은 문구 대신 해당 페이지를 잘 나타내는 키워드로 링크를 거는 것이 좋습니다. 예를 들어 데이터베이스 성능 튜닝 글이라면 "데이터베이스 인덱싱 기법에 대해서는 이전 포스팅 인덱싱 최적화 방법을 참고하세요." 이렇게 굵은 키워드 부분에 링크를 거는 것이 SEO에 도움이 됩니다.
  • 사이트 구조 파악 도움: 내부 링크가 잘 연결되어 있으면, 방문자가 내 블로그 안에서 더 많은 페이지를 탐색하게 되어 체류 시간도 늘어나고 이탈률이 줄어듭니다. 또한 크롤러도 링크를 따라가며 사이트의 콘텐츠를 효율적으로 발견하므로 색인 구축에 유리해요.

내부 링크를 너무 과하게 걸 필요는 없지만, 자연스럽게 연결될 수 있는 부분이 있으면 적극 활용해 보세요. 티스토리에서는 글 작성 시 편집기에서 링크 아이콘을 눌러 쉽게 본문 링크를 추가할 수 있습니다.

참고: 온페이지 SEO에서는 이 외에도 이미지의 대체 텍스트(alt 속성)를 넣어주는 것, 모바일 친화적 디자인을 사용하는 것, 페이지 로딩 속도를 높이는 것 등이 모두 포함됩니다. 하지만 이러한 부분은 아래 테크니컬 SEO에서 추가로 다루겠습니다.

 

** 글을 잘 쓰면 자발적으로 사람들이 레퍼런스로 참조하겠죠? 글 품질이 중요한 부분입니다.

 

3. 테크니컬 SEO (Technical SEO) 고려사항


이제 테크니컬 SEO 분야로 넘어가 보겠습니다. 테크니컬 SEO는 말 그대로 사이트 기술적 요소들을 최적화하여 검색 엔진이 사이트를 더 잘 크롤링/인덱싱하고, 사용자에게도 더 나은 경험을 제공하도록 하는 작업들입니다. 초심자 개발자 분들도 알아두면 좋은 주요 항목을 살펴보겠습니다.

 

3-1) Canonical URL 설정하기

 

앞서 용어 설명에서 다룬 캐노니컬 태그를 다시 한 번 강조합니다. 만약 티스토리 블로그에서 동일한 콘텐츠가 여러 경로로 접근될 수 있다면 canonical 설정을 고려해야 합니다. 예를 들어, "http://"로도 열리고 "https://"로도 열리거나, ?category=... 같은 파라미터에 따라 같은 글이 다른 URL로 보이는 경우가 있을 수 있습니다. 이런 상황에서는 페이지 <head>에 다음과 같이 원본 URL을 지정하는 캐노니컬 태그를 넣습니다:

 

<link rel="canonical" href="https://yourblog.tistory.com/원본글주소" />

 

이렇게 하면 검색 엔진은 중복된 여러 URL 중 canonical로 지정된 주소만 대표로 취급하고 나머지는 중복으로 판단하여 랭킹에 불이익이 없도록 처리해줍니다.

티스토리 기본 도메인을 사용하는 경우에는 큰 문제는 없지만, 개인 도메인을 연결한 경우 yourblog.tistory.com와 www.yourdomain.com 두 가지 주소로 접속되는 이슈가 생길 수 있으니 이럴 때 canonical 태그로 하나로 정해주시면 좋습니다.

 

사이드 프로젝트에서 적용한 canonical Tag

 

한 대표 언어만 canonical tag로 설정해야할지 아니면 각 언어마다 canonical tag를 설정해야할지 헷갈렸었는데, 여러 페이지(https://webmasters.stackexchange.com/questions/140553/use-of-canonical-tag-on-website-with-different-language-versions-and-separate-mo) 를 참고해보면 각 언어마다 canonical tag를 설정해주는게 옳은 방식이라고 합니다.

 

사이드 프로젝트에서 기본주소/{언어} 로 각 언어로 번역한 동일한 페이지를 만들어놓고, 각 페이지 별로 각각 카노니컬 태그를 설정해줬습니다. 예를 들어 /ko(한국어) 페이지에는 /ko가 canonical Tag 주인으로 설정되어 있고 다른 언어를 alternate로 설정해두었고, /ja(일본어) 페이지에선 /ja가 canonical Tag로 지정되어 있고 다른 언어들이 alternate로 지정되어 있습니다.

 

3-2) 사이트맵 파일과 robots.txt 설정하기

 

sitemap.xmlrobots.txt 파일은 테크니컬 SEO의 기본이라 불립니다. 티스토리 블로그도 마찬가지로 이 개념을 이해하고 활용하면 검색 엔진 크롤러 친화적인 사이트가 됩니다.

  • 사이트맵(sitemap.xml): 내 블로그의 글 목록(및 페이지 목록)을 모두 나열한 XML 파일입니다. 직접 작성하기 어렵다면 검색하면 사이트맵 자동 생성 도구도 많으니 활용하시면 돼요. 완성된 sitemap.xml 파일은 Search Console에 제출해서 구글에 알려줄 수 있습니다. 사이트맵을 제출해 두면 구글이 내 블로그의 새 글도 빠르게 발견할 수 있고, 혹시 내부 링크가 부족해 못 찾는 페이지도 색인될 수 있습니다.
  • 사이트맵 예시 (XML 형식):
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>https://yourblog.tistory.com/</loc>
    <lastmod>2025-05-25</lastmod>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://yourblog.tistory.com/예시글1</loc>
    <lastmod>2025-05-20</lastmod>
    <priority>0.8</priority>
  </url>
  <!-- ...다른 URL들... -->
</urlset>

 

 

  • 위 예시는 사이트의 홈 페이지와 어떤 글 하나를 목록에 넣은 것입니다. <lastmod>는 마지막 수정 날짜, <priority>는 페이지 중요도를 표시하는데 필수는 아니라서 없어도 괜찮습니다. 티스토리의 경우 기본 제공되는 RSS 피드를 이용해 Search Console에서 사이트맵으로 등록할 수 있습니다. (티스토리 RSS가 글 목록을 제공하므로 사실상 사이트맵 역할을 일부 합니다.)

 

  • robots.txt: 사이트의 루트(최상위 경로)에 robots.txt라는 텍스트 파일을 두면 검색 로봇들이 먼저 이를 확인합니다. 이 파일 안에는 크롤링 허용/비허용 규칙사이트맵 위치 등을 기술할 수 있습니다 티스토리 공식 도메인은 기본적인 robots.txt가 자동으로 설정되어 있어 수정할 순 없지만, 개인 도메인을 사용하면서 직접 서버를 운영한다면 robots.txt를 직접 만들어야 합니다.

    robots.txt 예시:
User-agent: *
Disallow: /admin/
Allow: /

Sitemap: https://yourblog.tistory.com/sitemap.xml

 

위 내용은 모든 크롤러(User-agent: *) 에게 /admin/ 경로는 크롤링하지 말라고 지시하고, 그 외는 모두 허용(Allow)하는 설정입니다. 마지막 줄에는 사이트맵 URL을 명시했습니다. 대다수의 경우 특별히 숨기고 싶은 페이지가 없다면 Disallow 지시자 없이 모두 허용하는 것이 좋습니다. 참고로 robots.txt를 잘못 설정해서 전체 사이트를 Disallow해버리면 검색 유입에 치명적이니, 항상 조심해서 다뤄주세요.

 

3-3) Core Web Vitals 지표 개선하기 (LCP, INP, CLS)

구글은 사용자 경험을 중시하기 때문에, 웹 성능 지표들도 검색 순위에 반영하고 있습니다. 특히 Core Web Vitals(코어 웹 바이탈)라는 세 가지 주요 지표를 정의하여 사이트 품질을 평가하고 있는데요, 각각 다음을 의미합니다.

  • LCP (Largest Contentful Paint): 최대 콘텐츠 표시 시간으로, 페이지 로드 시작 후 가장 큰 콘텐츠 요소(이미지 또는 큰 텍스트 블록 등)가 화면에 나타나는 데 걸리는 시간입니다. 쉽게 말해 본격적인 내용이 로딩되는 속도라고 볼 수 있어요. 2.5초 이내에 LCP가 발생하면 좋은 것으로 평가됩니다.
  • INP (Interaction to Next Paint): 다음 페인트까지의 상호작용으로, 사용자가 페이지에서 어떤 동작(클릭 등)을 했을 때 다음 화면이 그 동작에 반응하여 렌더링되기까지의 시간입니다. 이는 인터랙션 반응성을 측정하는 지표입니다. 0.2초(200ms) 미만이면 우수한 것으로 간주됩니다. (기존에는 FID(첫 입력 지연) 지표를 사용했지만, INP가 보다 포괄적인 지표로 새롭게 도입되었습니다.)
  • CLS (Cumulative Layout Shift): 누적 레이아웃 이동 점수로, 페이지 로딩 중 예상치 못한 레이아웃 변경이 얼마나 발생하는지를 수치화한 것입니다. 예를 들어 이미지가 늦게 로드되어 텍스트가 밀려난다거나, 광고 삽입으로 화면 요소들이 튀는 경우 CLS 점수가 높아집니다. 0.1 이하이면 안정적인 페이지로 평가합니다

 

 

이 세 가지 지표는 사용자에게 쾌적한 페이지 경험을 제공하는지를 나타내며, 구글 검색에서도 중요한 참고 신호로 사용되고 있습니다. 그렇다면, 각 지표를 어떻게 개선할 수 있을까요? 몇 가지 팁을 소개합니다:

 

  • LCP 개선: 가장 큰 요소가 빨리 나타나도록 사이트를 최적화하세요. 예를 들어 첫 화면에 보이는 이미지 용량을 줄이고, 필요한 경우 지연 로드(lazy-load)는 아래쪽 이미지에만 적용합니다. 또, 서버 응답속도를 높이거나 CDN을 이용해 콘텐츠 전송을 빠르게 하는 것도 LCP 향상에 도움이 됩니다. 한마디로 사용자가 첫 콘텐츠를 빨리 볼 수 있게 해주는 작업들입니다.
  • INP 개선: 자바스크립트 등의 대응 속도를 높이기 위해 노력합니다. 너무 무거운 스크립트는 비동기로 로드하거나 필요한 부분만 실행하고, 사용자가 상호작용할 때 메인 쓰레드를 오랫동안 블로킹하지 않도록 코드를 최적화합니다. 복잡한 작업은 Web Worker 등으로 분산하거나, 애니메이션 및 이벤트 핸들러를 효율적으로 작성하는 등의 방법이 있습니다. 결과적으로 사용자 조작에 즉각 반응하는 페이지를 만들자는 것이죠.

  • CLS 개선: 로딩 중 레이아웃이 튀지 않도록 미리 대비합니다. 예를 들어 이미지에는 width/height 속성을 지정하여 자리가 미리 확보되게 하고, 광고나 동적 콘텐츠가 삽입되는 공간도 최소한의 높이를 미리 예약해 둡니다. 글꼴이 로드되며 갑자기 텍스트가 커지는 경우도 있으니, 웹폰트 사용 시 FOIT/FOUT 현상도 신경 쓰는 것이 좋습니다. 핵심은 사용자 스크롤 중에 내용이 밀려서 불편하지 않게 만드는 것입니다.

위 개선 사항들은 모두 개발 단계에서 조금씩 신경 써야 하는 부분이지만, 초심자 분들도 이미지 크기 최적화나 불필요한 스크립트 최소화, 그리고 티스토리에서 제공하는 반응형 스킨 등을 활용하는 것으로도 충분히 시작할 수 있습니다. 

 

3-4) HTTPS 보안 적용의 필요성

 

마지막 테크니컬 요소로 HTTPS에 대해 짚고 넘어가겠습니다. HTTPS는 HTTP에 보안 프로토콜(TLS)이 추가된 것으로, 사용자와 서버 사이의 통신을 암호화하여 도청이나 위변조를 방지합니다. 오늘날 웹 환경에서 HTTPS는 사실상 기본이며, SEO 측면에서도 매우 중요합니다.

 

구글은 이미 2014년에 HTTPS 사용 여부를 랭킹 신호로 활용하기 시작했다고 발표한 바 있습니다. 비록 영향력은 작다고 했지만 시간이 지날수록 중요도가 커지고 있고, 현재는 HTTPS가 기본이 된 사이트들이 검색에서 유리한 것은 확실합니다. 사용자의 신뢰도 측면에서도 주소창에 자물쇠 아이콘이 보이지 않는 사이트는 클릭을 꺼리기 때문에 방문자 유치에도 불리해요.

 

티스토리 자체는 https:// 프로토콜을 지원하므로, 개인 도메인을 연결한 경우에도 SSL 설정을 꼭 하셔야 합니다. (티스토리 관리자 설정 > 블로그에서 HTTPS 사용 여부를 확인할 수 있습니다. 또는 Cloudflare 같은 서비스를 이용해 개인 도메인에 무료 SSL을 적용할 수도 있습니다.) 사이트 전체가 HTTPS로 제공되지 않고 일부만 HTTP라면 혼합된 콘텐츠 경고가 뜨면서 사용자에게 불안감을 줄 수도 있으니, 블로그 자산(이미지 등)도 가급적 https 주소를 사용하세요.

 

요약하면, 속도/보안 등 기술적인 부분도 SEO의 일부입니다. 검색엔진은 양질의 콘텐츠와 함께 빠르고 안전한 사이트를 사용자에게 제공하고자 하므로, 우리 블로그도 이에 맞게 기술적인 토대를 다져두면 좋겠습니다.

 

 

3-5) 구조화 데이터(JSON-LD) 적용하기

앞서 구조화 데이터에 대해 간단히 설명드렸는데요, 이번에는 왜 구조화 데이터를 써야 하는지어떻게 적용하는지 조금 더 살펴보겠습니다.

 

구조화 데이터를 사용하는 이유

일반적인 웹페이지는 사람이 읽기 위한 HTML 콘텐츠로 작성되지만, 구조화 데이터검색엔진이 기계적으로 이해하기 쉽도록 추가로 제공하는 데이터입니다. 이 데이터를 추가하면 다음과 같은 이점이 있습니다:

  • 콘텐츠 명확한 이해: 예를 들어 블로그 글에 구조화 데이터를 넣으면, 이 글의 제목, 저자, 발행일, 본문 요약 등이 어떤 것인지 명시적으로 표시할 수 있습니다. 검색 엔진은 이를 참고하여 해당 정보를 보다 정확하게 파악합니다.
  • 리치 결과(Rich Results): 구조화된 데이터를 활용하면, 구글 검색 결과에 별점, 썸네일 이미지, 방문자 리뷰, 레시피 조리 시간, FAQ 항목 등 다양한 추가 정보를 노출시킬 수 있습니다. 이런 풍부한 결과는 사용자 눈길을 끌어 CTR(클릭률) 상승에 도움이 됩니다. (실제로 앞서 언급했듯이, 리치 결과가 일반 결과보다 클릭률이 82% 높다는 분석도 있습니다.)
  • 음성 검색 및 AI 활용: 구조화 데이터로 콘텐츠를 잘 정리해 두면, 구글 어시스턴트 같은 음성 검색이나 향후 AI 검색 기능에서도 내 콘텐츠를 적절한 답변으로 활용할 확률이 높아집니다. 이는 미래를 대비한 포인트이긴 하지만 알아두면 좋겠죠.

그렇다면, 이렇게 좋은 구조화 데이터를 어떻게 추가할까요? 구글에서는 JSON-LD 형식을 사용할 것을 권장하고 있습니다. JSON-LD는 자바스크립트 객체 표기 형태로 데이터를 표현하기 때문에, 따로 페이지의 화면에 보이지 않고 <script> 태그 안에 정보를 넣어두기만 하면 됩니다.

 

구조화 데이터 간단 예제 

<script type="application/ld+json"> 
{
  "@context": "https://schema.org",
  "@type": "WebApplication",
  "applicationCategory": "EntertainmentApplication",
  "name": "Simmey - 우리의 얼굴 매칭 AI를 사용하여 부모님과 얼마나 닮았는지 확인해보세요!",
  "description": "우리의 얼굴 매칭 AI를 사용하여 부모님과 얼마나 닮았는지 확인해보세요! 재미있고 흥미로운 가족 닮은꼴 비교를 시작할 수 있는 메인 페이지입니다.",
  "author": {
    "@type": "Person",
    "name": "lodado"
  },
  "keywords": "face matching, ai, fun, family",
  "url": "https://mamapapa.vercel.app/",
  "datePublished": "2025-05-25T08:11:55.646Z",
  "isAccessibleForFree": true,
  "publisher": {
    "@type": "Organization",
    "name": "lodado",
    "logo": {
      "@type": "ImageObject",
      "url": "https://mamapapa.vercel.app/Logo.svg"
    }
  },
  "operatingSystem": "ALL",
  "browserRequirements": "A modern browser with JavaScript enabled",
  "offers": {
    "@type": "Offer",
    "price": "0.00",
    "priceCurrency": "USD"
  }
}
</script>

 

위는 제가 실제로 사이드프로젝트에 적용한 JSON-LD  태그입니다. 

 

Tip: 구조화 데이터를 추가한 후에는 구글 리치 결과 테스트 도구를 사용해서 올바르게 구현되었는지 검증해 보세요. 오류가 있다면 검색엔진에 반영되지 않을 수 있으니, 반드시 확인하는 습관을 들이는 것이 좋습니다.

 

3-6) 메타태그 - Open Graph 태그 

 

twitter meta tag

 

 

이외에도 twitter, facebook등 여러 소셜 미디어에서 사용하는 메타 태그 - Open Graph 태그 (og:title, og:description, og:image 등) 를 추가하면 SEO 향상에 도움이 됩니다.

 

4) 오프페이지 SEO 개념과 실천 방법


지금까지는 내 블로그 내부에서 할 수 있는 SEO에 집중했다면, 이제 오프페이지 SEO에 대해 이야기해보겠습니다. 오프페이지 SEO란 내 사이트 외부의 요소들로 검색 순위에 영향을 주는 것들을 말합니다. 그중 가장 대표적인 것이 백링크(Backlink) 입니다.


오프페이지 SEO란?

간단히 말해, 다른 사이트로부터 내 사이트로 연결되는 링크외부에서의 평판을 관리하는 것입니다. 구글 같은 검색 엔진은 어떤 사이트에 좋은 콘텐츠가 많으면, 다른 사이트들도 그 사이트를 많이 링크한다고 판단합니다. 그래서 품질 좋은 백링크가 많을수록 신뢰도와 권위가 높다고 보고 랭킹을 올려주는 것이죠. 반대로 출처가 의심스러운 스팸 링크가 많으면 오히려 패널티를 받을 수도 있습니다.

 

거창한 링크 빌딩 전략을 펼치기는 어렵겠지만, 쉬운 방법 몇 가지를 실천해 볼 수 있습니다:

  • 콘텐츠 공유: 내가 쓴 유용한 글이 있다면 SNS에 직접 공유하세요. 트위터, 페이스북, 링크드인, 개발자 커뮤니티 등 관련된 곳에 포스팅해서 사람들의 관심을 끌면 자연스럽게 방문자도 늘고, 누군가 내 글을 인용해갈 가능성도 생깁니다. 처음부터 큰 영향은 아니어도 노출 기회를 넓힌다는 측면에서 중요합니다.

  • 커뮤니티 참여 및 링크: 개발자라면 Stack Overflow나 Hashnode, Reddit, 또는 국내 개발자 커뮤니티(예: OKky, Dev.to, Velog 등)에 활동하면서 관련 질문에 답변을 달거나 글을 쓰며 자연스럽게 내 블로그 글 링크를 남길 수도 있습니다. 단, 무턱대고 홍보 링크만 남기는 것은 스팸으로 보일 수 있으니 주의하세요. 정말 해당 질문에 도움이 되는 상세한 답변을 제공하면서 참고 링크로 내 글을 언급하는 식이 바람직합니다.
  • 게스트 포스팅 & 협업: 기회가 된다면 다른 블로그에 게스트 포스트를 기고하고 내 블로그를 소개하거나, 지인들의 블로그와 교차로 링크 교환을 할 수도 있습니다. 예를 들어 다른 분의 블로그에 내가 쓴 글을 올리면서 "원문: 내 블로그 링크"를 남기는 방식입니다. 이는 어느 정도 컨텐츠 신뢰를 쌓은 후에 가능하겠지만, 하나의 방법이 될 수 있어요.

  • 디렉토리 및 프로필 활용: 기술 블로그들의 모음 디렉토리에 내 블로그를 등록하거나(국내에 SEO 디렉토리는 흔치 않지만, 해외엔 alltop 같은 사이트들이 있음), 개발 관련 프로필(GitHub, LinkedIn)에 블로그 주소를 넣어두는 것도 링크 노출을 늘리는 소소한 팁입니다.

무엇보다 중요한 것은 고퀄리티 콘텐츠 생산입니다. 콘텐츠가 좋아야 사람들이 자발적으로 공유하고 링크해 주기 때문에, 이것이 가장 이상적인 오프페이지 SEO라 할 수 있습니다. 처음부터 백링크 숫자에 집착하기보다는 블로그에 유용한 글을 꾸준히 쌓고, 커뮤니티에서 신뢰를 얻는 것이 장기적으로 SEO에 큰 도움이 될 거예요.

 

고퀼리티 콘텐츠 생산을 어떻게 하냐고요?
가장 어려운 부분일꺼 같은데 운칠기삼이라고 봅니다.
제 사이드 프로젝트도 이유는 모르겠지만 러시아 검색엔진쪽에서 많이 유입되는거 같네요..

 

배포 전 SEO 체크리스트

마지막으로, 이제 홈페이지를 발행하기 전에 중요 요소들을 하나씩 체크해 봅시다. 아래 SEO 체크리스트를 통해 빠뜨린 부분은 없는지 확인해보세요:

 

  • 제목 태그와 메타 설명 작성: 글의 주제를 명확히 담은 제목(title)을 정했고, 매력적인 메타 설명(description)을 추가하셨나요? (검색 결과에 표시될 문구입니다.)

  • URL 주소 확인: 티스토리에서 자동 생성된 제 글 URL(슬러그)이 의미있게 잘 설정되어 있나요? (가능하다면 영문으로 간단히 키워드를 포함하는 게 좋지만, 티스토리는 자동으로 생성됩니다. 예: https://myblog.tistory.com/15보다는 .../seo-guide 처럼 식별 가능하면 좋습니다.)
  • 헤딩 구조 점검: 본문에 h1은 하나만 있고, h2/h3 등의 소제목이 논리적으로 계층을 잘 이루고 있나요? 혹시 글씨 크기를 키우려고 헤딩을 남용하지 않았는지 확인하세요.

  • 키워드 최적화: 글 내용 중에 주요 키워드가 자연스럽게 포함되어 있나요? 제목, 첫 문단, 헤딩 등에 핵심 단어가 들어가면 좋습니다. 다만 키워드 과다 남용은 금물입니다. 독자를 위한 글쓰기가 우선이에요.

  • 내부 링크 추가: 관련있는 다른 포스팅이 있다면 서로 링크를 연결해 두었나요? 새로운 글에서는 이전 관련 글을, 그리고 나중에라도 이전 글에 이 새로운 글의 링크를 추가하면 더욱 좋습니다.

  • 이미지 대체 텍스트(Alt): 글에 이미지나 그림을 넣었다면 <img alt="..."> 속성에 이미지 설명을 넣었는지 확인합니다. 이는 시각장애인용 보조기기에도 필요하고 SEO에도 유용합니다.

  • 모바일 환경 확인: 모바일에서 내 블로그가 읽기 편한지 확인해 보셨나요? 화면 크기에 따라 레이아웃이 깨지거나 글씨가 너무 작지 않은지 점검하세요. 모바일 친화적(모바일 프렌들리) 사이트는 검색 순위에도 유리합니다.

  • 페이지 속도 확인: PageSpeed Insights 등으로 페이지 점수가 너무 낮게 나오지는 않았나요? 이미지 최적화필요없는 스크립트 지우기 등을 통해 속도를 개선해 보세요. LCP/CLS 지표가 나쁘게 나오면 해당 요소를 수정하는 것도 잊지 마세요.

  • HTTPS 적용 여부: 블로그 주소가 http://가 아닌 https://로 접속되고 있는지 확인합니다. 티스토리 기본 도메인은 HTTPS이지만, 개인 도메인은 SSL 설정을 해야 합니다. 브라우저 주소창에 자물쇠가 뜨는지 꼭 확인하세요.

  • 구조화 데이터 추가: 가능하다면 JSON-LD 형태의 구조화 데이터 스크립트를 페이지에 넣었는지 확인합니다. (티스토리에서는 스킨 편집이나 개별 글 HTML 모드에서 추가 가능) 나중에라도 한 번 도전해보세요.

  • Search Console 색인 요청: 글을 발행했다면 Google Search Console에 가서 새 URL을 색인 요청 해보세요. 이렇게 하면 크롤러가 비교적 빨리 방문해서 색인해갈 확率이 높아집니다.

  • SNS 공유 준비: 마지막으로, 소셜 미디어에 공유할 준비가 되었나요? Open Graph 태그 (og:title, og:description, og:image 등)도 자동 설정되도록 스킨을 구성하면 좋습니다. 공유했을 때 미리보기 카드가 깔끔히 나오면 클릭률 상승에 도움이 되니까요.

내용이 다소 많았지만, 요약하자면 검색엔진이 내 블로그를 잘 찾아가도록 돕고, 방문자에게 좋은 경험을 주는 것이 SEO의 핵심입니다.

 

마지막으로 제가 테스트한 사이드 프로젝트 공유하고 글 마쳐봅니다..!

 

https://mamapapa.vercel.app/ko

 

Simmey - 우리의 얼굴 매칭 AI를 사용하여 부모님과 얼마나 닮았는지 확인해보세요!

우리의 얼굴 매칭 AI를 사용하여 부모님과 얼마나 닮았는지 확인해보세요! 재미있고 흥미로운 가족 닮은꼴 비교를 시작할 수 있는 메인 페이지입니다.

mamapapa.vercel.app

 

홈페이지 자체는 닮은 얼굴 매칭 - 테스트 결과를 보여주는 단순한 웹앱인데요. 사실 광고 및 마케팅을 안해서 SEO를 적용시키더라도 방문자가 별로 없을줄 알았는데, YAndex라고 러시아 검색 엔진에서 자동으로 크롤링해가고 많은 유저(?)들이 들어와서 놀랬네요

 

 

reference

https://wormwlrm.github.io/2023/05/07/SEO-for-Technical-Blog.html

 

기술 블로그를 위한 SEO - 재그지그의 개발 블로그

개인 기술 블로그에 적용한 SEO 방법들을 소개하고, 그 결과물을 공유합니다.

wormwlrm.github.io

https://searchadvisor.naver.com/

 

네이버 서치어드바이저

네이버 서치어드바이저와 함께 당신의 웹사이트를 성장시켜보세요

searchadvisor.naver.com

 

및 구글 서치어드바이저 등

 

 

 

 

반응형
반응형

worker 적용한 cavas(좌측)와 미적용된 canvas(우측), 상단의 count 올라가는 속도가 차이가 난다.

 

 

웹 성능 최적화를 위해 브라우저의 메인 스레드(Main Thread) 부담을 줄이는 것은 매우 중요합니다. 이번 글에서는 웹 초보자도 이해하기 쉽게 Web Worker, OffscreenCanvas, Comlink를 활용해 메인 스레드 작업을 분산하고 성능을 향상시키는 방법을 소개합니다.

 

Web Worker란? 왜 메인 스레드 작업을 분산해야 하나?

Web Worker는 브라우저에서 메인 스레드와 별도로 동작하는 백그라운드 스레드입니다. 쉽게 말해 웹 페이지의 UI와 독립적으로 실행되는 자바스크립트 환경입니다. Web Worker를 사용하면 메인 스레드가 해야 할 무거운 작업을 워커로 위임할 수 있어요

 

이로써 메인 스레드는 보다 중요한 UI 렌더링이나 사용자 입력 처리 등에 집중하고, 무거운 연산으로 인한 프리즈(멈춤) 현상을 줄일 수 있습니다.

 

웹 성능이 저하되는 흔한 이유는 메인 스레드가 과부하되어 UI가 응답하지 않는 상태가 되는 것입니다. 예를 들어 복잡한 계산이나 큰 이미지 처리 등을 메인 스레드에서 하면, 그동안 버튼 클릭이나 화면 렌더링이 멈출 수 있죠. Web Worker로 이러한 작업을 옮기면 브라우저가 다중 스레드처럼 작업하여 UI를 매끄럽게 유지할 수 있습니다. 요약하면, Web Worker는 웹 앱에 멀티스레딩 효과를 주어 성능을 높이는 도구입니다.

 

** 성능상 우월한 방법이 아닙니다! 병렬 처리를 위할때 유용합니다. 

 

OffscreenCanvas: 워커에서 캔버스를 그리기 위한 비밀병기

Canvas를 활용한 그래픽 연산은 웹에서 많이 사용되지만, 기존에는 이 <canvas> 요소가 메인 스레드의 DOM과 연결되어 있어 워커에서 직접 조작할 수 없었습니다. OffscreenCanvas(오프스크린 캔버스)는 이런 제약을 해결해 주는 기술입니다. OffscreenCanvas는 화면에 보이지 않는 캔버스를 의미하며, 캔버스를 DOM과 분리하여 화면 밖(off-screen)에서 렌더링할 수 있게 해줍니다. 덕분에 Web Worker 내부에서도 캔버스에 그림을 그릴 수 있죠.

 

 

오프스크린 캔버스를 쓰는 이유는 간단합니다. 메인 스레드의 부담을 줄이기 위해서입니다. 예를 들어 복잡한 애니메이션이나 물리 시뮬레이션을 Canvas로 구현한다면, 메인 스레드에서 매 프레임 그림을 그리느라 다른 작업을 못할 수 있습니다.

 

OffscreenCanvas를 사용하면 이러한 캔버스 그리기 연산을 워커로 넘겨 병렬 처리할 수 있습니다. 메인 스레드는 UI 업데이트이벤트 처리에 집중하고, 워커는 OffscreenCanvas에 그림을 그린 다음 그 결과만 메인 스레드로 보내 화면에 표시하는 식이죠. 이렇게 하면 캔버스 애니메이션도 부드럽게 돌리고, UI도 끊김 없이 반응하도록 만들 수 있습니다.

 

Comlink: Web Worker와의 통신을 쉽게 해주는 라이브러리

Web Worker를 직접 사용하다 보면, postMessage와 onmessage로 메시지를 주고받는 코드가 다소 번거롭습니다.

 

 

Comlink(컴링크)는 이를 간단하게 만들어주는 경량 라이브러리입니다. Comlink를 쓰면 마치 메인 스레드에서 워커 내부 함수나 변수를 직접 호출하는 것처럼 프로그래밍할 수 있어요.

 

웹 워커와 통신 (postMessage) 흐름도

 

내부적으로는 postMessage를 추상화하여 자동으로 메시지를 전달해주기 때문에, 개발자는 복잡한 메시지 핸들러 대신 평범한 함수 호출 형태로 워커와 소통할 수 있습니다

 

예를 들어 Comlink 없이라면:

  • 메인 스레드에서 worker.postMessage(data)로 데이터를 보내고,
  • 워커 내부에서 self.onmessage로 이벤트를 받아 처리한 뒤,
  • 다시 self.postMessage(result)로 결과를 메인에 보내고,
  • 메인에서는 worker.onmessage로 결과를 받는

일련의 과정을 코딩해야 합니다.

 

Comlink를 쓰면 Web Worker와의 통신을 프록시 객체로 감싸서(일종의 RPC), 개발자가 쉽게 비동기 함수 호출처럼 다루도록 도와주는 도구입니다.

 

예제로 보는 Web Worker + OffscreenCanvas 활용 (Matter.js 물리 시뮬레이션)

이제 간단한 예시로 위 개념들을 연결해보겠습니다. Matter.js라는 자바스크립트 2D 물리 엔진을 이용해 공 몇 개가 튕기는 물리 시뮬레이션을 만든다고 가정해봅시다. 이 시뮬레이션은 계산량이 많으니 Web Worker에서 실행하고, 메인 스레드에서는 현재 프레임 수나 객체 개수 등의 count 상태만 화면에 표시하도록 해볼게요.

 

Main Thread

const canvas = document.getElementById('simCanvas');
const offscreen = canvas.transferControlToOffscreen();
const worker = new Worker('physics-worker.js');
worker.postMessage({ canvas: offscreen }, [offscreen]);

// UI에서 1초마다 count 증가 표시 (워커와는 별개로 동작)
let count = 0;
setInterval(() => {
  document.getElementById('counter').innerText = `Count: ${count++}`;
}, 1000);

 

  • 메인 스레드(main.js): 메인 HTML에 <canvas id="simCanvas"></canvas>와 <div id="counter"></div>가 있다고 합시다. 메인에서는 워커를 생성하고 캔버스를 OffscreenCanvas로 넘깁니다.

 

  • 위 코드에서 transferControlToOffscreen()은 DOM 캔버스를 OffscreenCanvas 객체로 변환하여 워커로 소유권 이전(transfer) 하는 역할을 합니다. 이렇게 하면 이후부터는 워커가 해당 캔버스에 직접 그림을 그릴 수 있어요. 또한 메인에서는 1초마다 단순 카운트 숫자를 올려서 #counter 영역에 표시합니다. 이 count 증가 로직은 메인 스레드에서 별도로 돌기 때문에, 물리 시뮬레이션이 돌아가더라도 UI 카운터가 멈추지 않고 계속 업데이트 됩니다.

 

Worker Thread

importScripts('matter.min.js');  // 워커에서 Matter.js 라이브러리 로드
let engine, render;

onmessage = (event) => {
  const offscreenCanvas = event.data.canvas;
  const ctx = offscreenCanvas.getContext('2d');
  // Matter.js 엔진 초기화 (중력, 세계 설정 등)
  engine = Matter.Engine.create();
  // Matter.js에서는 render를 직접 사용하지 않고 OffscreenCanvas의 ctx로 그림
  function update() {
    Matter.Engine.update(engine, 16);            // 물리 세계 한 스텝 진행 (approx 60fps)
    drawScene(ctx, engine.world);               // 사용자 정의: world의 객체들을 ctx로 그리기
    requestAnimationFrame(update);              // 다음 프레임 업데이트 예약
  }
  update(); // 시뮬레이션 시작
};

 

  • 워커 스레드(physics-worker.js): 워커 쪽에서는 메인으로부터 메시지를 받아 OffscreenCanvas 객체를 얻습니다. 그리고 Matter.js 엔진을 초기화하고, 주기적으로 물리 시뮬레이션 업데이트 + 캔버스 렌더링을 합니다.

 

 

  • 위 예시는 단순화를 위해 의사코드 형태로 나타냈지만, 핵심은 워커에서 주기적으로 Matter.js 엔진을 업데이트하고 OffscreenCanvas의 2D 컨텍스트에 결과를 그림입니다.
  • requestAnimationFrame도 워커 환경에서 사용할 수 있는데, 이 경우 OffscreenCanvas에 그리는 것이므로 메인 화면에 바로 반영됩니다. 메인 스레드는 이 과정에 관여하지 않으므로, 물리 계산과 캔버스 렌더링으로 인한 메인 스레드 블로킹이 발생하지 않습니다. 메인은 그저 앞서 설정한 setInterval로 UI 카운트만 올리고 있을 뿐이죠.

worker 적용한 cavas(좌측)와 미적용된 canvas(우측), 상단의 count 올라가는 속도가 차이가 난다.

 

  • 메인에서의 결과: 실제로 실행해보면, <canvas>에는 워커가 그린 Matter.js 물리 시뮬레이션 (예: 공들이 튕기는 애니메이션)이 매끄럽게 표시되고, 동시에 <div id="counter">에는 1, 2, 3... 하는 카운트 숫자가 끊김 없이 증가하는 것을 볼 수 있습니다. 만약 워커를 사용하지 않고 모든 작업을 메인에서 했다면, 물리 연산이나 그리기로 인해 카운트 업데이트가 지연되거나 멈췄을 겁니다. 이처럼 워커+오프스크린 캔버스 구조는 무거운 연산을 백그라운드에서 처리하면서도 메인 UI를 부드럽게 유지시킵니다.

맺으며

정리하면, Web Worker는 무거운 작업을 메인 스레드에서 떼어내어 비동기로 처리할 수 있게 해주고, OffscreenCanvas는 그런 워커에서 그래픽을 그릴 수 있도록 도와주며, Comlink는 메인-워커 간 통신을 개발자 친화적으로 만들어 줍니다. 이 세 가지를 조합하면, 초기 단계의 웹 개발자도 비교적 쉽게 메인 UI의 성능을 최적화하는 구조를 설계할 수 있습니다.

 

** 다시 적지만, 애니메이션이 좀 더 매끄러워지는거 같은 성능상의 이점은 없습니다

다만 "무거운 연산"을 메인 쓰레드에서 분리 가능합니다. 


reference 

 

https://web.dev/articles/offscreen-canvas

 

 

반응형
반응형

블로그에 개인적으로 사용한 "기술"을 요약해놓고 나중 복기하는 용도로 사용했었는데,

 

chatgpt가 나타난 이후로는 위 용도를 완전히 대체해버려서

블로그를 쓰거나 보는것을 계속 미루게 되는것 같습니다.

 

그래도 간단히 요즘 공부한 것을 요약해서 써볼려고 합니다..

 

1. Logical Properties란?

CSS Logical Properties(논리적 속성)은 요소의 좌우(인라인 방향)나 상하(블록 방향)처럼 문서의 쓰기 방향에 따라 바뀌는 속성을 말합니다​

 

기존 CSS 속성들은 left, right, top, bottom처럼 물리적인 방향을 지정했지만, Logical Properties는 이러한 대신

인라인(inline)과 블록(block) 방향으로 속성을 지정합니다. 예를 들어 left와 right는 인라인 방향의

시작(start)과 끝(end)으로, top과 bottom은 블록 방향의 시작과 끝으로 표현됩니다​

 

이렇게 함으로써 요소의 실제 배치 방향(LTR인지 RTL인지 등)에 따라 속성이 자동으로 적용되는 것입니다.

 

새로운 박스 모델

박스 모델 출처 - https://wit.nts-corp.com/2019/08/05/5621

 

  1. Width, Height
  • 영어(LTR) 환경:
    • width는 텍스트의 흐름 방향이므로 inline-size로 대체
    • height는 문장이 쌓이는 방향이므로 block-size로 대체
  • 몽골어와 같이 수직 텍스트 환경:
    • 텍스트 흐름이 수직이므로 inline-size가 height가 되고,
    • 문장이 쌓이는 방향이 수평이 되어 block-size가 width로 대체

2. Position Offsets

  • 기존의 top/left/bottom/right는 논리적 속성으로 변환되며,
    • top → inset-block-start
    • left → inset-inline-start
    • bottom → inset-block-end
    • right → inset-inline-end

요약하자면 아래와 같습니다.

margin-top: margin-block-start;
margin-left: margin-inline-start;
margin-bottom: margin-block-end;
margin-right: margin-inline-end;
border-top: border-block-start;
border-left: border-inline-start;
border-bottom: border-block-end;
border-right: border-inline-end;
padding-top: padding-block-start;
padding-left: padding-inline-start;
padding-bottom: padding-block-end;
padding-right: padding-inline-end;

 

 

이외에도 다양한 속성들이 있는데, 아래 링크에서 잘 설명해둔것 같습니다.

 

https://wit.nts-corp.com/2019/08/05/5621

 

2. 왜 RTL/LTR이 중요할까?

 

tailwind의 ltr, rtl 예시, 출처 - https://v3.tailwindcss.com/docs/hover-focus-and-other-states#rtl-support

 

전세계에는 영어처럼 왼쪽에서 오른쪽으로 쓰는 언어(LTR)뿐만 아니라 아랍어, 히브리어처럼 오른쪽에서 왼쪽으로 쓰는 언어(RTL)도 많이 있습니다​

 

웹 페이지를 다국어로 지원할 때 단순히 left, right 같은 물리적 속성만 사용하면, RTL 언어에서는 레이아웃이 의도와 다르게 표시되는 문제가 발생합니다. 왜냐하면 예를 들어 left는 문서의 방향과 무관하게 항상 왼쪽을 의미하기 때문에, RTL 문서에서도 그대로 왼쪽에 적용되어 “시작 부분”에 적용되지 않기 때문입니다​

이러한 문제 때문에 RTL 지원을 위해 별도의 CSS를 작성하거나, dir="rtl"일 때 클래스를 다르게 적용하는 등의 추가 작업이 필요해지곤 합니다.

 

 

3. Tailwind에서 기존 클래스를 덮어쓰는 방법

Tailwind CSS는 유틸리티 퍼스트(utility-first) 프레임워크로, 기본적으로 물리적 속성 기반의 클래스(.ml-4는 margin-left 등)를 제공합니다. Tailwind 자체적으로는 (과거 버전 기준) 논리적 속성 전용 유틸리티를 제공하지 않았기 때문에, RTL 지원을 위해서는 플러그인이나 커스터마이징이 필요했습니다. 다행히 Tailwind v3부터는 일부 논리적 속성을 다루는 유틸리티가 도입되었는데요. 예를 들어 ms-4는 margin-inline-start: 1rem, me-4는 margin-inline-end: 1rem에 해당하여, 콘텐츠 방향에 따라 좌우 마진을 알아서 적용해줍니다​

 

이미 tailwind를 사용하면서 기본 값들 (w, ml-1 등등..)에 익숙해졌는데 새로운 값을 배우려니 귀찮기도 하고,

혹시 크로스 브라우징 이슈가 발생한다면.. (caniuse에 따르면 ie가 아니면 거의 문제없긴 합니다) 롤백이 쉽도록

 

직접 커스텀 플러그인으로 기존 위치 정보(width, left 등)을 logical properties로 overwrite하는 플러그인을 구현해서 사용해봤습니다. .ml-<값> 클래스가 margin-inline-start를, .mr-<값> 클래스가 margin-inline-end를 지정하도록 유틸리티를 추가하면 됩니다.

 

// tailwind.config.js의 plugins 배열 안
plugins: [
  function ({ addUtilities, theme, variants }) {
    const spacing = theme("spacing");
    const newUtilities = {};
    for (const [key, value] of Object.entries(spacing)) {
      newUtilities[`.ml-${key}`] = { "margin-inline-start": value };
      newUtilities[`.mr-${key}`] = { "margin-inline-end": value };
    }
    addUtilities(newUtilities, variants("margin"));
  }
]

 

이렇게 하면 Tailwind의 기존 .ml-1, .mr-1, .ml-2, .mr-2, ... 클래스들이 모두 물리적 margin-left/right 대신 논리적 margin-inline-start/end로 동작하도록 덮어쓰게 됩니다.

 

https://gist.github.com/lodado/e286cdc452c6362117c2129abfab562a

 

위 링크는 제가 지금 사용하고 있는 커스텀 플러그인 코드 예시입니다. 

 

5. 마무리

CSS Logical Properties를 적극 활용하면 별도의 RTL 전용 스타일시트 없이도 하나의 CSS로 양쪽 방향의 레이아웃을 모두 커버할 수 있습니다. 이는 다국어 웹사이트나 글로벌 서비스에서 유지보수를 훨씬 쉽게 만들어줍니다​

이 글을 쓰면서 알게 된건데, 비슷한 역할을 하는 tailwindcss-vanilla-rtl 같은 플러그인 라이브러리가 이미 있군요..

 

그리고 이걸 왜 공부했냐고요?

다국어 지원이 되는 사이드 프로젝트를 구현하다가, 전 세계 사용 언어 5위권에 속하는 아랍어(rtl)를 지원하기 위해 

logical properties를 사용했습니다..! 

 

아래 링크에서 제 사이드 프로젝트를 확인 가능하고,

 

https://mamapapa.vercel.app/

 

 

덤으로 rtl ltr이 지원되는 swipe(?) 기능 list 도 확인하실 수 있습니다..! 

 

ltr일때 왼쪽으로 스와이프 기능
rtl일때 오른쪽으로 스와이프 하는 기능

 

 

 

참고 자료:

CSS Tricks – CSS Logical Properties and Values​

MDN Web Docs – CSS logical properties and values 모듈​

 

Tailwind CSS 공식 문서​

 

Dev.to – CSS Logical Properties - RTL in a web platform​

 

 

반응형
반응형

 

CORS는 많이 들어봤는데

CORB란것을 '사이트 격리'에 대해 알아보다가

새로 알게 되었다.

 

참고) 사이트 격리

 

- It ensures that pages from different websites are always put into different processes.

- It also blocks the process from receiving certain types of sensitive data from other site

 

즉, Chrome's Site Isolation effectively makes it harder for untrusted websites to access or steal information from your accounts on other websites.

 

Cross-Origin Read Blocking(CORB)

 

Cross-Origin Read Blocking (CORB) is an algorithm that can identify and block dubious 
cross-origin resource loads in web browsers before they reach the web page.

 

For example, it will block a cross-origin text/html response requested 
from a <script> or <img> tag, replacing it with an empty response instead.

 

출처 : https://developers.google.com/web/updates/2018/07/site-isolation

 

즉, 웹에서 cross origin의 data resource(xml, html, json 등)를 읽어와 사용하지 못하도록 브라우저에서 막는 동작이다.

 

원리 

 

CORB가 어떻게 동작하는지 알아보자.

보통 web client는 서버에 두가지의 요청을 보낸다.

 

  1. data resources such as HTML, XML, or JSON documents
  2. media resources such as images, JavaScript, CSS, or fonts

보통 1번은 SOP & CORS 설정에 따라 브라우저에 의해 blocking 되거나 보이게 된다.

(참고로 2번 media resources들은 cors에 상관없이 요청 가능하다. ex-JSONP)

 

조건 

그리고 CORB는 위 조건을 만족한다면

renderer processa cross-origin data resource를 받아와 사용하는 것을 금지한다.

(a new security feature that prevents the contents of balance.json from ever entering the memory of the renderer process memory based on its MIME type.)

 

참고)

X-Content-Type-Options: nosniff는 Microsoft에서 제안하는 확장 헤더이며 웹서버가 보내는 MIME 형식 이외의 형식으로 해석을 확장하는 것을 제한하는 크로스사이트스크립트 방어법이다.

 

즉, nosniff 옵션이 켜있다면 브라우저는 이게 HTML, XML, JSON중 하나인것으로 Content-type 종류로 인하여 헷갈리지 않고 바로 확정 지을 수 있다.

(가끔 어떤 서버는 이미지에 대해 text/html로 잘못 분류하기도 한다. 이걸 방지 가능)

 

이점 

 

CORB를 사용하면 다음과 같은 이점이 있다.

 

- Mark responses with the correct Content-Type header.

- out of sniffing by using the X-Content-Type-Options: nosniff header.

- 보안! (In browsers with Site Isolation, it can keep such data out of untrusted renderer processes entirely, helping even against side channel attacks like Spectre)

예시

그럼 예시 데모를 한번 보자.

 

https://anforowicz.github.io/xsdb-demo/index.html

 

CORB demo

Demo of CORB This page demonstrates how Cross-Origin Read Blocking (CORB) works. Please see one of the following resources for more information about CORB: Repro steps to trigger CORB: Make sure that CORB is active In Chrome M68 and later CORB is active by

anforowicz.github.io

 

<button> Add 1 <img src="https://www.chromium.org/"> </button>
<button> Add 2 <img src="https://www.w3.org/.../dummy.pdf"> </button>

 

들어가서 버튼을 한번 눌러보면

CORB 차단이 뜬다.

 

위 버튼들은 data resource(text/html, application/pdf) 요청을 cross-origin 서버에 보내는 버튼들이고, CORB에 의해 막히게 된다.

그리고 CORS와 동일하게 정상적인 요청이 왔어도 (status 200) 브라우저에서 막도록 구현된 것을 확인할수 있다.

 

 

tmi)

현재 tistory 스킨에서 영어를 읽으려니 눈이 아프다 -_-;

 

 

함께 읽으면 좋은 글)

 

CORS

https://beomy.github.io/tech/browser/cors/

 

[Browser] CORS란?

이번 포스트에서는 교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)에 대해 이야기해보도록 하겠습니다. 아래 사진과 같은 에러를 보신 적이 있으셨을 수도 있습니다.

beomy.github.io

 

reference 

 

https://chromestatus.com/feature/5629709824032768

 

https://stackoverflow.com/questions/18337630/what-is-x-content-type-options-nosniff

 

https://webhack.dynu.net/?idx=20161120.001&print=friendly 

 

https://bingbingba.tistory.com/8

 

https://developers.google.com/web/updates/2018/07/site-isolation

 

Site Isolation for web developers  |  Web  |  Google Developers

Chrome 67 on desktop has a new feature called Site Isolation* enabled by default. This article explains what Site Isolation is all about, why it’s necessary, and why web developers should be aware of it.

developers.google.com

 

반응형
반응형

이 글은 사용자 입력(input)을 받았을 때 컴포지터가 어떻게 부드러운 상호작용을 하는지에 관한 글이다

(출처는 https://developers.google.com/web/updates/2018/09/inside-browser-part4)

 

Inside look at modern web browser (part 4)  |  Web  |  Google Developers

Input event handling with the compositor thread

developers.google.com

 

사용자 입력을 받았을때

 

브라우저 관점에서 입력이란 모든 사용자의 제스처(이벤트)를 의미한다. 스크롤도 이벤트이고, 화면 터치, 마우스 포인터를 올리는거도 입력 이벤트이다.

 

 

화면 터치와 같은 사용자 제스처가 발생했을 때 가장 먼저 제스처를 수신하는 것은 브라우저 프로세스이다. 브라우저 프로세스는 제스처가 어디에서 발생했는지만 알고 있다. 탭 내부의 콘텐츠는 렌더러 프로세스가 처리해야 한다. 

 

그래서 브라우저 프로세스는 이벤트 종류와 좌표값(x,y 등)만 렌더러 프로세스에 넘기게 된다.

렌더러 프로세스는 이벤트 대상과 이벤트 리스너를 실행해 이벤트를 적절히 처리한다.

 

스크롤의 예시로 렌더러 프로세스 내부동작을 알아보자.

 

그림 출처 : https://developers.google.com/web/updates/2018/09/inside-browser-part4#compositor_receives_input_events

 

스크롤할때 레스터화된 레이어를 컴포지터가 합성해 스크롤을 부드럽게 처리한다.

이벤트리스너가 없다면 컴포지터 쓰레드는 메인 쓰레드와 상관없이 스스로 합성해서 프레임을 만들어낼 수 있다.

 

그런데 이벤트가 달려있다면 다르게 동작하게 된다.

합성하는 쓰레드는 컴포지트 쓰레드이고, 

이벤트를 실제로 처리하는 쓰레드는 JS를 동작시키는 메인 쓰레드이다.

어떻게 둘이 상호작용을 하게 될까?

 

고속 스크롤 불가 영역(non-fast scrollable region)

 

JS가 실행되는 작업은 메인 스레드의 영역이므로 이벤트 핸들러가 연결된 영역을 고속 스크롤 불가 영역(non-fast scrollable region)이라고 표시한다. 이 영역에서 이벤트가 발생하면 렌더러 프로세스는 우선 컴포지터 스레드에게 작업을 보내고, 컴포지트 스레드는 입력 이벤트를 메인 스레드로 보내야하는지 정보를 확인 후 넘겨준다.

 

만약 고속 스크롤 불가 영역이 아니라면 컴포지터 스레드는 메인 스레드를 기다리지 않고 새 프레임을 합성한다.

(컴포지터 스레드는 복사된 자신만의 레이어 트리를 가지고 있는다. - pending tree -> active tree?)

 

그렇다면 여기서 한가지 의문점을 가지게 된다.

이벤트 위임을 설정할때는 어떻게 될까?

 

ex)

document.body.addEventListener('touchstart', event => {  
    if (event.target === wantedNode) {
        event.preventDefault();
    }
});

이벤트 위임을 document나 root 등 최상위에 선언했을때

이벤트위임을 최상위에 선언했을경우 다음 그림과 같이 페이지가 전부 고속 스크롤 불가 영역에 속하게 된다.

 

이런 문제를 방지하기 위해 passive : true 옵션을 전달하면 메인스레드에서 이벤트를 받지만, 컴포지터가 메인 스레드의 처리를 기다리지 않고 새 프레임을 만들어도 되는 힌트를 브라우저에 주는 옵션을 줄 수 있다.

ex)

document.body.addEventListener('touchstart', event => {  
    if (event.target === wantedNode) {
        event.preventDefault();
    }
}, {passive: true});

 

JS로 가로로만 스크롤을 제한하고 싶을때 

passive : true 옵션을 주면 부드럽게 스크롤이 된다는거까지는 알았다. 그런데 스크롤을 JS의 event.preventDefault() 함수로 제한한다면 쓰레드가 다르므로 event.preventDefault() 가 실행되기 전 이미 수직 스크롤이 실행될 수도 있다. 그래서 event.cancelable()를 사용하면 스크롤 시작 여부를 확인 가능하다.

document.body.addEventListener('pointermove', event => {
    if (event.cancelable) {
        event.preventDefault(); // block the native scroll
        /*
        *  do what you want the application to do here
        */
    }
}, {passive: true});

 

======

 

역주 : 모질라에 따르면 passive : true는  event.preventDefault()가 내부에서 실행이 안될꺼라는 약속이라는데

위 코드를 실제로 실행해보면 에러가 뜬다.

 

아래 링크 참고

https://developer.mozilla.org/ko/docs/Web/API/EventTarget/addEventListener

위 코드를 복붙해서 실행했을때 나온 오류

https://stackoverflow.com/questions/37721782/what-are-passive-event-listeners

 

What are passive event listeners?

While working around to boost performance for progressive web apps, I came across a new feature Passive Event Listeners and I find it hard to understand the concept. What are Passive Event Listene...

stackoverflow.com

스텍오버플로우에 따르면

By marking a touch or wheel listener as passive, 
the developer is promising the handler won't call preventDefault to disable scrolling. 
This frees the browser up to respond to scrolling immediately without waiting for JavaScript, 
thus ensuring a reliably smooth scrolling experience for the user.

라는데 원글의 예시 코드는 이해를 돕기 위한 '예시'인지 좀 혼란스럽긴 하다.. 

일단 스택오버플로우와 원글의 공통점을 추론해보자면

passive : true를 설정하면 메인 쓰레드(JS)가 작동하지 않고 스크롤 이벤트때 컴포지트 쓰레드가 바로 동작하는 개념은 맞는듯 싶다.

 

======

 

(아무튼 계속 시작)

 

또는 아에 touch-action에서 아예 수직 스크롤 이벤트를 지워버릴수도 있다.

#area {
  touch-action: pan-x;
}

 

이벤트 대상 찾기

 

컴포지터 쓰레드가 메인 스레드로 보낼때 이벤트 대상을 찾는 hit test를 한다.

이벤트가 발생한 좌표에 무엇이 있는지 확인을 위해 paint recoards data를 이용한다.

(브라우저의 렌더링 단계에서 파싱->스타일->layout->paint->composite 에서 paint)

 

(아마 opcacity, transform등의 정보를 따로 담고 있는 property tree의 정보도 참고하기 위해서

paint tree를 참고하는거로 추론?)

 

메인 스레드 이벤트 전송 최소화

 

일반적으로 모니터는 1초당 60번 (60프레임) 화면을 갱신한다. 그리고 애니메이션도 화면 갱신 주기에 맞춰야

부드럽게 움직인다.

 

일반적으로 touchEvent는 초당 60~120회 전달하고, 마우스는 초당 100회정도 전달한다.

즉, 화면 갱신보다 이벤트 갱신 주기가 더 짧아서 이벤트가 뚝뚝 끊겨보이는 상황을 연출할 수도 있다.

 

너무 과도한 호출로 버벅거림을 유발하는 이벤트

 

그래서 메인 호출이 과다해지는것을 막기 위해서 Chrome은 자체적으로 연속적(coalesces continuous)인 이벤트(wheel , mousewheel , mousemove , pointermove , touchmove)는 다음번 requestAnimationFrame() 메서드 실행 직전까지 전송하지 않고 기다리게 된다.

 

keydown, keyup, mouseup, mousedown, touchstart, touchend와 같은 비연속적인(discrete) 이벤트는 즉시 전달된다.

 

한 프레임 안에서 합쳐진 이벤트 정보를 얻기 위해 getCoalescedEvent() 사용

드로잉 앱 같은 경우 프레임 사이 사이 경로가 누락되 선을 매끄럽게 그리지 못할 수도 있다. 이때 getCoalesecedEvents를 사용하면 합쳐진 이벤트의 정보를 얻을 수 있다.

 

 

 

 

reference 

 

https://d2.naver.com/helloworld/6204533

https://developers.google.com/web/updates/2018/09/inside-browser-part4

 

Inside look at modern web browser (part 4)  |  Web  |  Google Developers

Input event handling with the compositor thread

developers.google.com

 

반응형
반응형

주의) 이글은 깁니다...

 

크롬에서 렌더링은 렌더러 프로세스가 담당한다.

이 글과 이전글은 GPU가 실제 클라이언트에서 어떻게 쓰이는지 원리를 알기 위해 찾아보았던 내용이다.

그 내용을 아래에 후술한다.

 

렌더러 프로세스에 관한 이전 글)

https://lodado.tistory.com/19

 

[운영체제] 크롬 웹 브라우저의 구조 (프로세스 & 쓰레드)

자바스크립트는 싱글 쓰레드이지만, 크롬 브라우저의 탭 하나하나는 각각 하나의 프로세스이고 멀티 쓰레드 환경이다. 이전에 썼던 이벤트 루프 관련 글에서 정확히 브라우저의 내부 구조가 어

lodado.tistory.com

 

www.google.com을 검색할때 크롬에서 일어나는일 

 

면접 단골 질문이긴 한데 네트워크 말고 크롬이 하는 일만 집중해서 간단히 살펴보자.

자세한 과정은 아래 링크를 추천한다.

브라우저마다 상세 구현은 다를 수 있기 때문에

'흐름' 을 파악하는 정도면 좋을 것 같다.

 

https://developers.google.com/web/updates/2018/09/inside-browser-part2?hl=ko 

 

모던 웹 브라우저 들여다보기 (파트 2)  |  Web  |  Google Developers

브라우저가 탐색 요청을 처리하는 방법을 학습하십시오.

developers.google.com

 

Brower Process 도식도

브라우저 프로세스는 주소 창, 뒤로 및 앞으로 이동 버튼을 포함한 어플리케이션의 "chrome" 부분을 제어한다.

또한 네트워크 요청 및 파일 액세스와 같은 웹 브라우저의 권한이 부여된 보이지 않는 부분을 제어한다.

 

브라우저 프로세스 내부를 보면

버튼이나 입력창을 그리는 UI 스레드,

인터넷에서 데이터를 수신하기 위해 통신 스택을 건드리는 네트워크 스레드,

파일 같은 것들에 접근하기 위한 스토리지 스레드

등을 가지고 있다. 

 

 

 

Browser Process가 내부 NetWork thread에 브라우저 탐색 과정을 수행하게 시키고, 작업이 완료되면 

Renderer Process에게 IPC를 통해 페이지 렌더를 요청한다.

이후 과정이 우리가 흔히 아는 브라우저의 렌더링 과정이다.

 

Renderer Process가 하는 일 

렌더러 프로세스는 브라우저 탭 안에서 일어나는 모든 일들을 담당한다.

렌더러 프로세스의 핵심 역할은 HTML, CSS 그리고 자바스크립트를 사용자가 인터렉션할 수 있는 웹 페이지로 만드는 것이다.

 

프로세스는 여러개의 쓰레드로 구성되어 있다.

 

Main Thread : 대부분의 코드를 처리한다. (파싱, 렌더 등)

Work Threads : 웹 워커 혹 서비스 워커를 사용할 경우 워커 스레드가 자바스크립트 코드 일부분을 처리한다.

Compositor & Raster Thread  : 렌더러 프로세스 내부에서 페이지를 효율적이며 매끄럽게 렌더하기 위해 실행된다.

compositor와 Raster thread의 역할은 후술한다.

 

브라우저의 렌더링 과정 

웹킷의 동작 과정

이것 또한 표준이 없어서... 세부 구현이 브라우저마다 다를 수 있지만 흐름 자체를 이해하자.

브라우저는 파싱  스타일  레이아웃  페인트  합성  렌더 등의 과정을 거친다. 그 후에 JS나 CSS를 통해 DOM이나 CSS에 변화가 생길 경우 reflow 혹은 repaint 등의 과정을 수행한다.

 

1) 파싱

 

HTML 파싱

 

브라우저가 HTML 을 파싱하고 읽어들이는 과정이다.

렌더러 프로세스가 탐색을 위한 커밋 메세지를 받고 HTML 데이터를 받기 시작할 때, 메인 스레드는 텍스트 문자열 (HTML)을 파싱하기 시작하고 이를 Document Object Model (DOM)으로 변환한다.

DOM은 페이지에 대한 브라우저의 내부 표현일 뿐만 아니라 웹 개발자가 자바스크립트를 통해 상호 작용할 수 있는 데이터 구조 및 API이다.

 

예측 파싱

HTML 문서에 <img> 혹은 <link>등이 있는 경우, 사전 로드 스케너는 HTML 파서에 의해 생성된 토큰들을 살짝 보고 브라우저 프로세스에 있는 네트워크 스레드에게 요청을 보낸다.

 

파싱 차단 리소스

 

파싱 과정에서 자바스크립트가 파싱을 중단시킬수도 있다.

<script> 태그를 만나면 HTML 문서를 파싱하는것을 멈추고 자바스크립트 코드를 로딩, 파싱, 실행한다.

이를 JavaScript는 파싱 차단 리소스(parser blocking resource)라고 부른다.

 

이를 방지하기 위해서는

 

  • <script>를 body 제일 아래에 놓는다 (가장 고전적인 방법)
  • 비동기로 데이터를 내려받고 다운로드가 완료되면 실행되는 async 태그를 사용한다.
  • 비동기로 데이터를 내려받고 파싱이 완료되면 실행되는 defer 태그를 사용한다. (가장 추천)
  • 리소스 우선순위화 - <link rel="preload"> 사용

가장 추천되는 방식은 head에 script + defer attribute이다.

asnyc, defer에 대해서는 아래 글 추천

 

https://guiyomi.tistory.com/101

 

Javascript - script 로딩 시 async vs defer

HTML 파일에서 외부 js 파일을 가져오는 방법은 다음과 같다. 그럼 여기서 궁금한 점이 발생한다. script 태그의 위치는 어디에 위치해야 할까? 보통 브라우저는 HTML 문서를 파싱할 때, 위에서부터

guiyomi.tistory.com

 

CSS 파싱

외부/내부의 스타일시트의 CSS를 해석해 CSSOM 트리를 구성한다.

속성을 주지 않아도 각 element들은 브라우저마다 고유의 css 속성을 가지며, 이것을 인위적으로 통일하거나

다 지우기 위해서 보통 개발할때 normalize.css나 reset.css를 사용한다.

 

렌더 차단 리소스(rendering-blocking-resource)

 

HTML, CSSOM이 완성 이전까지 브라우저는 렌더링을 멈추게 된다.

즉, css를 네트워크에서 빨리 받아오는게 중요하다.

<link rel="preload" as="script" href="super-important.js">
<link rel="preload" as="style" href="critical.css">

preload, preconnect, prefetch 등을 사용해 브라우저에게 우선순위를 알려줄 수 있다.

 

<link href="style.css"    rel="stylesheet">
<link href="style.css"    rel="stylesheet" media="all">
<link href="print.css"    rel="stylesheet" media="print">
<link href="portrait.css" rel="stylesheet" media="orientation:landscape">
<link href="other.css"    rel="stylesheet" media="min-width: 40em">

그리고 미디어 쿼리를 이용해 자신이 사용하는 미디어 타입에 걸맞는 css만 받아오고, 다른 기기의 css는 받아오지 않는 식으로 (용량을 줄여) 최적화 할 수 있다.

 

2) 스타일 

 

dom tree와 CSSOM tree가 생성되었다면 결합해서 Render Tree를 만든다.

렌더링 트리에는 페이지를 렌더링하는 데 필요한 노드만 포함된다.

 

그리고 어떤 렌더 객체는 DOM 노드에 대응하지만 트리의 동일한 위치에 있지 않다. float 처리된 요소 또는 position 속성 값이 absolute로 처리된 요소는 흐름에서 벗어나 트리의 다른 곳에 배치된 상태로 형상이 그려진다. 대신 자리 표시자가 원래 있어야 할 곳에 배치된다.

 

3) 레이아웃(재시작시 Reflow)

 

레이아웃은 요소들의 기하학적인 구조를 찾는 과정이다.

현재 viewport 기준으로 정확히 DOM이 어디있는지 위치, 크기를 계산한다.

 

만약 CSS나 돔의 layout과 관련된 요소(width, font-size 등)가 변경된다면 reflow 과정이 생길수도 있다.

 

추가적으로

 

display: none을 사용하면 렌더링 트리에서 요소가 완전히 제거된다.

visibility : hidden을 사용하면 레이아웃에서 공간을차지하지만 요소가 보이지 않는다.

 

그리고 레이아웃 트리를 순회하면서 속성 트리(property tree)를 만드는 작업이 페인트와 레이아웃 사이에 끼여있다.

속성 트리는 clip, transform, opacity등의 속성 정보만 가진 트리이다. 

최신 Chrome에서는 이런 속성만 별도로 관리하고 각 노드에서는 속성 트리의 노드를 참조하는 방식으로 변경되고 있다.

4) 페인트(재시작시 repaint)

레이아웃 트리를 따라가 페인트 기록을 생성한다.

 

배경 이미지, 텍스트 색상, 그림자등 실제 레이아웃의 수치를 변형시키지 않는 스타일의 변경이 일어나면

repaint만 발생한다.

일반적으로 reflow가 발생되면 repaint도 같이 발생한다.

(레이아웃 수치를 다시 계산해서 배치를 해야하기 때문에)

 

5. 합성(composite)

페이지를 그리는 방법

 

컴포지팅은 한 페이지의 부분들을 여러 레이어로 나누고 그 것들을 각각 레스터화하며 컴포지터 스레드에서 페이지를 합성하는 기술이다. 그리고 만약 스크롤이 발생하면, 레이어들이 이미 레스터되었기 때문에, 해야 할 것은 새로운 프레임을 합성하는 것이다.

 

 

https://developers.google.com/web/updates/2018/09/inside-browser-part3#what_is_compositing

에니메이션은 레이어들을 움직이는 동일한 방식으로 이뤄지고 새로운 프레임을 합성한다.

어떻게 웹 사이트가 여러 레이어로 나뉘는 지 개발자 도구의 Layers panel에서 볼 수 있다.

 

참고) 레스터화와 벡터화

 

레스터화는 각 요소 이미지를 컴퓨터가 이해할 수 있는 비트맵으로 변환하고, 하나의 비트맵으로 합성하는 과정이다.

https://m.blog.naver.com/reductionist101/221567932033

 

래스터, 벡터 차이

래스터(raster)와 벡터(vector)는 컴퓨터가 이미지를 저장하는 방식이며, 둘 사이에는 차이가 있다. 첫 번...

blog.naver.com

 

Layer에 대해서

 

메인 스레드는 레이아웃 트리를 순회하여 레이어 트리를 생성한다. (이 부분은 개발자 도구 성능 탭의 Update Layer Tree 참고)

 

모든 요소들에 대해 레이어를 지정할 수도 있다. 하지만 수많은 레이어를 합성하는 것은 웹페이지의 작은 부분을 매 프레임마다 새로 래스터화하는거보다 느릴 수 있다.

 

그래서 메인 쓰레드를 사용하지 않고 레스터와 컴포지트 하는 방식을 알아보자 (쉬운 말로 GPU를 써보자)

 

 

타일들을 레스터화(비트맵 생성) 시키고 GPU에 전송시키는 레스터 쓰레드들

레이어 트리가 생성되고 페인트 순서가 결정되고 나면, 메인 스레드는 컴포지터 스레드에게 정보를 커밋한다.

그러면 컴포지터 스레드가 각 레이어를 레스터라이즈(=레스터화)한다.

 

컴포지터 스레드는 레이어들을 여러 타일로 쪼개고 각 타일을 다수의 레스터 스레드에게 보낸다.

레스터 스레드들은 각 타일을 레스터화하고 그 것들을 GPU 메모리에 저장한다.

 

컴포지터 스레드는 서로 다른 레스터 스레드들에 대해 우선 순위를 정할 수 있어서 화면 안에 보이는 (혹은 가까이 있는) 것들이 먼저 레스터될 수 있다.

 

쿼드 군집으로 컴포지터 프레임을 생성해 GPU에게 IPC를 사용해 넘긴다.

 

타일들이 레스터되면, 컴포지터 스레드는 쿼드 군집(draw quads) 라 하는 타일 정보를 모아 컴포지터 프레임을 생성한다.

 

드로우 쿼드  메모리에서 타일의 위치 및 페이지 합성을 고려하여 타일을 그릴 페이지의 위치와 같은 정보를 포함합니다.
컴포지터 프레임 한 페이지의 프레임을 나타내는 쿼드 군집의 컬렉션입니다.

 

컴포지터 프레임은 IPC를 통해서 브라우저 프로세스에게 넘어간다. 

즉, 조각조각 내서 IPC로 넘긴다. 이해하면서 내 멘탈도 지금 조각조각 나고 있다.

 

 이 때, 다른 컴포지터 프레임이 브라우저 UI 변화에 따라 UI 스레드에 의해 혹은 확장 기능에 대한 다른 렌더러 프로세스들에 의해 추가될 수 있다. (GPU process는 하나니까.. 근데 이런 경우가 언제 있는지는 잘 모르겠다)

 

이러한 컴포지터 프레임들은 GPU에게 보내져 화면에 보여진다. 만약 스크롤 이벤트가 발생하면, 컴포지터 스레드는 GPU에게 보내질 다른 컴포지터 프레임을 생성한다.

 

이러한 방식의 장점은 메인 스레드의 개입 없이(reflow와 repaint 없이) 컴포지팅이 GPU에 의해 수행된다는 것이다.

 

 

현재 CSS의

  • opacity
  • translate
  • rotate
  • scale
  • will-change 

옵션이 GPU 가속을 지원한다.

그리고 전 글에도 적었지만, 무분별한 GPU 남용은 오히려 해가 된다.

보통은 잘 바뀌지 않는 값과 에니메이션을 레이어를 분리해 지정하는게 좋다. 

(The Animation Process From 1938)

이 영상에서는 배경은 그대로 두고 앞에서 움직여야 하는 전경만 별도의 셀로 만들어서 프레임을 촬영한다. 

-> 크기, 내용은 그대로고 이동(에니메이션)만 하는 element를 지정하는게 좋다

-> 작을수록 좋다

 

함께 읽어보면 좋을 글) 

 

https://docs.google.com/presentation/d/1QRchHprSPW4JVwAUVWmGmq3gmR8nLWrJmGYFzWHW9G4/edit#slide=id.g7b5233544_0274

 

Threaded GPU Rasterization

Threaded GPU Rasterization crbug.com/454500 State of GPU Rasterization (M-42)

docs.google.com

 

https://web.dev/why-speed-matters/

 

속도가 왜 중요합니까?

사용자 경험에서 속도는 중요한 역할을 합니다. 모바일 속도로 인한 지연은 실망스러울 뿐만 아니라 비즈니스 결과에도 부정적인 영향을 미칠 수 있습니다.

web.dev

 

https://web.dev/fast/

 

빠른 로드 시간

사이트 성능을 높이기 위한 기술.

web.dev

 

reference 

https://d2.naver.com/helloworld/5237120

https://d2.naver.com/helloworld/59361

https://junilhwang.github.io/TIL/Javascript/Design/Vanilla-JS-Virtual-DOM/#_1-%E1%84%87%E1%85%B3%E1%84%85%E1%85%A1%E1%84%8B%E1%85%AE%E1%84%8C%E1%85%A5-%E1%84%85%E1%85%A9%E1%84%83%E1%85%B5%E1%86%BC-%E1%84%80%E1%85%AA%E1%84%8C%E1%85%A5%E1%86%BC

 

Vanilla Javascript로 가상돔(VirtualDOM) 만들기 | 개발자 황준일

Vanilla Javascript로 가상돔(VirtualDOM) 만들기 본 포스트는 React와 Vue에서 사용되고 있는 가상돔(VirtualDOM) 직접 만들어보는 내용이다. 그리고 이 포스트를 읽기 전에 Vanilla Javascript로 웹 컴포넌트 만들

junilhwang.github.io

 

https://developers.google.com/web/updates/2018/09/inside-browser-part3?hl=ko 

 

모던 웹 브라우저 들여다보기 (파트 3)  |  Web  |  Google Developers

브라우저 렌더링 엔진의 내부 작동 방식

developers.google.com

https://velog.io/@itssweetrain/Reflow-%EC%99%80-Repaint

 

성능 최적화와 관련해서 : reflow 와 repaint

이렇게 렌더 트리 생성이 끝나면 배치가 시작된다. 레이아웃 단계는 트리를 생성하면서 계산된 노드와 스타일을 기기의 뷰포트에서 어떤 위치에서 어떻게 보이도록 하는지 결정하는 단계입니

velog.io

 

https://d2.naver.com/helloworld/2061385

 

 

https://medium.com/@cwdoh/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%ED%81%AC%EB%A1%AC-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%84%B1%EB%8A%A5-%EC%9D%B8%EC%9E%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-4c9e4d715638

 

프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기

3년 전에 개인 블로그에 적었던 글이라 이미 보신 분들도 있으리라 생각됩니다만, 미디엄에서 이전의 기술관련 글들을 같이 관리할 겸 같이 포스팅하기로 하였습니다. :)

medium.com

 

반응형
반응형

자바스크립트는 싱글 쓰레드이지만, 크롬 브라우저의 탭 하나하나는 각각 하나의 프로세스이고 멀티 쓰레드 환경이다. 

이전에 썼던 이벤트 루프 관련 글에서 정확히 브라우저의 내부 구조가 어떻게 구성되었는지 궁금해서 찾아보았다. 

 

참고) 이전글

https://lodado.tistory.com/16

 

[이벤트루프] 자바스크립트에서 정확한 타이머 구현?

*잘못된 부분이 있으면 피드백 주시면 감사하겠습니다! 자바스크립트에서 타이머 이벤트를 쓸 수 있는 방법으로는 setTimeout, setInterval 두가지가 있다. 이 함수들이 어떻게 비동기를 지원할까? 자

lodado.tistory.com

컴퓨터 아키텍처 3개 레이어 - 브라우저가 돌아가는 환경

 

하단부의 Machine Hardware, 중앙부의 운영 체제, 상단부의 어플리케이션.

 

브라우저가 돌아가는 환경을 이해하기 위해서는 컴퓨터의 전반적인 구조를 이해할 필요가 있다.

 

Machine Hardware (스마트폰, 컴퓨터 등)

 

물리적으로 구현된 하드웨어 위에서 컴퓨터가 동작

실제 작업을 물리적으로 처리하는 공간이다.

최근에는 브라우저에서 단순 CPU를 넘어서서 고속 렌더링, 에니메이션을 처리하기 위해 추가적으로 GPU라는 개념이 등장했다.

 

CPU 

Central Processing Unit - CPU

 

CPU는 컴퓨터의 뇌라고 볼 수 있다.

다양한 작업을 실제적으로 처리하는 공간이다.

최근엔 싱글 CPU를 넘어서서 멀티 코어등 다양한 방식을 이용해 '병렬성'을 지원하려는 연구가 활발하다.

 

GPU

 

Graphics Processing Unit - GPU

최근 브라우저에서 GPU를 이용하려는 연구도 활발하다.

GPU는 공장이라고 비유할 수 있다.

CPU는 다양한 작업을 유연하게 처리하는데 특화되어 있다면

GPU는 연산을 수많은 코어에서 동시에 처리하는데 특화되어 있다.

GPU 가속 연산 덕분에 CPU 하나로는 오래 걸릴 연산을 금방 끝낼 수 있다.

 

GPU가 연산을 하기 위해서는 CPU가 GPU에 데이터를 전송해줘야 연산이 가능하다.

이것을 비유하자면 CPU는 배송 트럭이라고 생각하고, GPU는 공장이라고 비유해보면 좋을것 같다.

 

GPU Bottleneck - 병목현상

CPU가 배송(I/O, 효율적인 프로그래밍)를 빨리 해줘야 공장이 100% 효율로 가동 가능하다.

공장이 최신식(GPU의 성능이 매우 좋아도)이라도 CPU의 배송이 느리다면 제 효율을 낼 수 없다.

그리고 반대로 배송(CPU의 성능이 매우 좋아도)이 엄청 빨라도 공장의 효율이 좋지 않다면 제 효율을 낼 수 없다.

 

요약하자면 둘 다 중요하다.

안드로이드 같은 경우 웹앱을 사용할 경우

GPU 연산이 좋다고 모든 연산을 위임하다보면 위 GPU Bottleneck 현상 혹은 너무 많은 작업으로 오히려 CPU만 사용할때보다 느려질 수 있다.

 

그리고 하드웨어적인 한계가 있기 때문에 CPU, GPU의 성능을 아무리 올려도 언젠간 한계에 부딫치게 된다.

프론트엔드 엔지니어가 관여할 수 있는 부분은 '렌더링 최적화' 등 주어진 자원 내에 최대의 효율을 내는게 주 업무다.

 

Operating System (윈도우, 리눅스, 안드로이드 등)

 

소프트웨어적으로 구현된 운영체제 위에서 어플리케이션이 동작 

(운영체제는 하드웨어와 이용자 사이에서 쉽게 이용할 수 있도록 인터페이스 역할을 한다. 윈도우가 왜 이름이 '윈도우'인지 생각해보면 좋을듯!)

 

Application (브라우저 - 크롬, 오페라 등)

 

우리가 사용하는 브라우저 어플리케이션이다. 운영체제가 지시하는 메커니즘에 따라 CPU & GPU를 동작 시키게 요청한다. 

동작(프로그래밍)을 잘 시키냐에 따라 브라우저의 제 성능을 이끌어낼 수 있다. 

 

프로세스 & 쓰레드

 

그리고 브라우저 아키텍처를 이해하기 이전에 프로세스 & 쓰레드 구조를 이해할 필요가 있다. 

이 부분은 면접 단골질문이기도 하고 학교에서 많이 배우므로 간략하게 설명하고 넘어가겠다.

 

프로세스 

 

프로세스는 운영체제로부터 자원을 할당받은 작업의 단위이다.

즉, 어플리케이션 하나가 프로세스 하나가 될 수 있다.

 

참고) 프로그램에 대해

 

더보기

프로그램은 어떤 작업을 위해 실행 할 수 있는 파일을 말하며 메모리구조에서 code 영역에 있는 실제 물리적 파일을 뜻한다.

프로세스는 컴퓨터에서 연속적으로 실행되고 있는 컴퓨터 프로그램을 뜻하며 메모리에 올라와 실행되고 있는 프로그램의 인스턴스이다.

 

즉, 프로그램(passive) <-> 프로세스(active)관계라고 할 수 있다.

 

쓰레드 

 

쓰레드는 프로세스 내에서 운영체제로부터 할당받는 자원을 실행하는 단위이다.

프로세스 내부에서 여러개가 생길 수 있다.

 

그외 자세한 정보는 다음 링크 추천 

https://gmlwjd9405.github.io/2018/09/14/process-vs-thread.html

 

[OS] 프로세스와 스레드의 차이 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

 

프로세스와 쓰레드 생성 과정

 

process 내부의 쓰레드들

 

어플리케이션이 실행되면 프로세스가 생성되고,

프로세스는 작업을 위해 쓰레드(들)을 생성 할 수 있다.

그리고 OS는 프로세스에게 메모리 한 조각을 주고 모든 상태 정보를 고유 메모리 공간에 저장할 수 있게 한다. 어플리케이션이 끝나면 프로세스도 사라지고 OS가 메모리를 해제한다.

 

(개인적 생각으로 여기서 말하는 메모리는 RAM 메모리를 뜻하는것으로 추론된다.)

프로세스간 통신 - Inter Process Communication (IPC)

 

IPC

그리고 프로세스는 다른 프로세스에게 별도의 작업을 수행하도록 요청 혹은 통신이 가능하다. 많은 어플리케이션이 이 방식을 채택하고 있어 워커 프로세스가 무응답 상태에 빠지더라도 어플리케이션의 다른 부분을 수행하고 있는 프로세스들을 종료할 필요 없이 해당 프로세스만 재시작할 수 있다.

 

IPC에 대한 정보는 다음 링크 추천

https://jwprogramming.tistory.com/54

 

IPC의 종류와 특징

IPC(Inter Process Communication) - 프로세스 간 통신에 대하여 종류와 특징들에 대하여 살펴보겠습니다. [리눅스 커널 구조] - 위 그림처럼 Process는 완전히 독립된 실행객체입니다. 서로 독립되어 있다

jwprogramming.tistory.com

 

브라우저 아키텍처

 

다른 여러 브라우저 구조들

중요한점은 브라우저를 구현하는 '표준'이 없기 때문에 브라우저(IE, 오페라, 웨일, 크롬 등등..)마다 내부 작동 방식이 다를 수 있다.

 

그래서 공통적인 흐름을 이해하는것이 중요하다. (ex : 프로세스 & 쓰레드 구조로 동작하는구나!)

이 글은 2018년 기준 크롬 브라우저를 기준으로 설명한다.

 

크롬의 멀티 프로세스 아키텍처 도식도

 

크롬은 멀티 프로세스 아키텍처를 이용한다.

*중요점 : 크롬은 여러개의 렌더러 프로세스를 가질 수 있다(보통 탭 하나당 하나).

 

각 중요한 프로세스의 설명은 다음과 같다.

프로세스 설명
브라우저 주소 창, 뒤로 및 앞으로 이동 버튼을 포함한 어플리케이션의 "chrome" 부분을 제어합니다.
또한 네트워크 요청 및 파일 액세스와 같은 웹 브라우저의 권한이 부여된 보이지 않는 부분을 제어합니다.
렌더러 웹사이트가 디스플레이 될 때 탭 안의 모든 것 담당.
플러그인 플래시와 같은 웹사이트가 사용하는 모든 플러그인 담당.
GPU 다른 프로세스와 분리된 GPU 작업을 제어합니다. GPU는 여러 앱의 요청을 제어하고 동일한 표면에 표시하기 때문에 다른 프로세스로 분리됩니다.

 

멀티 프로세스 아키텍처의 장점

 

그럼 왜 이런 멀티 프로세스 구조를 가질까?

 

개별 탭에서 실행되는 여러 프로세스의 도식도;

 

보통 탭 하나당 하나의 프로세스를 가진다. 

(추가적으로 사이트 격리 옵션이 켜지고 iframe이 내부에서 실행되면 하나의 개별 Renderer 프로세스를 또 가진다)

 

참고)

https://blog.chromium.org/2017/05/improving-extension-security-with-out.html

 

Improving extension security with out-of-process iframes

Security is critical to Chrome, and many features protect Chrome users as they browse the web. Google Safe Browsing warns users away from ...

blog.chromium.org

 

만약 크롬이 단일 프로세스 환경이고 renderer process가 다중 쓰레드 환경이라면 한 탭이 고장이 나게 되면 모든 탭에 영향을 끼치게 된다. (메모리 영역에서 stack을 제외한 heap, code, data 등 여러 영역을 공유하기 때문?) 

 

그런데 다중 프로세스 환경이라면 탭이 하나 고장한 경우 그냥 닫아버리고 다른 탭으로 이동하면 된다.

 

그외 장점으로는 보안 및 샌드박싱 (운영체제는 프로세스의 권한을 제한하는 기능을 제공)이 있다.

 

메모리 공간 절약

 

최종적인 크롬의 아키텍처

그런데 각 프로세스가 메모리 공간을 할당받아 사용하다보면 메모리 부족 현상이 일어날수도 있고 효율적이지 않다.

그래서 크롬이 고성능 장치에서 실행될 때에는 안정성을 위해 각 서비스를 별개의 프로세스로 분리하고, 자원이 부족한 장치에서는 서비스를 하나의 프로세스로 합쳐 메모리 점유를 낮추는 메커니즘이 들어가 있다.

 

즉, 크롬에서 최대 프로세스 개수에 제한을 두었다.

이 구조는 안드로이드에서도 구현되어 있어 유사한 프로세스를 합쳐 메모리 점유를 줄이는 방식을 실행한다.

 

기타 브라우저의 동작 방식

 

전반적으로 mutli process architecture를 따르는 듯하다.

 

IE8

 

 

 

크롬의 브라우징 프로세스와 렌더링 프로세스 두개를 심플하게 가지는거 같다.

One mainframe process

Zero or multiple tab processes

tab process의 경우 RAM 크기에 따라 자동으로 크기가 조절된다.

 

Firefox

 

Firefox의 경우엔 멀티 프로세스 아키텍처인것은 크롬과 동일하다. 다만 4개까지의 다중 프로세스를 허용하고 이후 

탭의 경우는 구글과 비슷하게 기존 프로세스 내부에서 메모리 영역을 공유한다.

 

Chrome using 1.77x more RAM than Firefox in 64-bit and 2.44x in 32-bit mode. (모질라의 주장에 따르면!)

 

모질라의 주장에 따르면 자기들이 메모리를 제일 적게 쓴다고 하는데

프로세스를 4개까지만 만드니까 당연한 내용이다 😂

 

 

같이 읽어보면 좋을 글)

https://levelup.gitconnected.com/how-web-browsers-use-processes-and-threads-9f8f8fa23371

 

How web browsers use Processes and Threads

A process can be described as an application’s executing program. A thread is the one that lives inside of process and executes any part…

levelup.gitconnected.com

 

https://medium.com/@cwdoh/%ED%94%84%EB%A1%A0%ED%8A%B8%EC%97%94%EB%93%9C-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%ED%81%AC%EB%A1%AC-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%84%B1%EB%8A%A5-%EC%9D%B8%EC%9E%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-4c9e4d715638

 

프론트엔드 개발자를 위한 크롬 렌더링 성능 인자 이해하기

3년 전에 개인 블로그에 적었던 글이라 이미 보신 분들도 있으리라 생각됩니다만, 미디엄에서 이전의 기술관련 글들을 같이 관리할 겸 같이 포스팅하기로 하였습니다. :)

medium.com

 

reference 

 

https://wvganjana.medium.com/how-web-browsers-use-process-threads-67e156abb3c5

 

How web browsers use Process & Threads

As we all know Chrome and Firefox both using multi-threading in architecture. But they support it in different ways.

wvganjana.medium.com

 

https://www.wepc.com/tips/cpu-gpu-bottleneck/

 

CPU and GPU Bottleneck: A Detailed Explanation

Have you ever experienced playing a game and you get sudden FPS drop from time to time? The next second, you’re dead.. If you try to observe, these sudden

www.wepc.com

 

https://developers.google.com/web/updates/2018/09/inside-browser-part1?hl=ko 

 

모던 웹 브라우저 들여다보기 (파트 1)  |  Web  |  Google Developers

브라우저에서 사용자 코드를 하이레벨 아키텍처부터 렌더링 파이프라인 세부 기능에 이르는 기능성 웹사이트로 전환하는 방법

developers.google.com

 

반응형

+ Recent posts