GROWTH LOG STORIES

함께 만든 성장을,
기록으로 연결합니다.

AI와 함께 배우고, 직접 만들고, 서로 나눈
그로스로그 멤버들의 생생한 성장 기록을 만나보세요.

성장 기록
5기+이어진 커뮤니티
HEALTHIO
PROJECT

사진 한 장으로 시작하는 건강 루틴, Health IO

대표 이야기 읽기

ALL STORIES

성장의 순간을
한곳에서 만나보세요.

프로젝트의 시작부터 모임에서 나눈 인사이트까지,
그로스로그가 함께 만든 기록을 모았습니다.
개의 성장 기록

성장일지

[GL 3기] 도커 첫 주차 정리, SSR을 했는데도 검색이 안 되던 이유, HTML이 조각으로 도착하는 방식 (성장일지 3회차 큐레이션) 🌱

GROWTH LOG🌱 2026. 8. 7. 05:23

안녕하세요! 그로스로그 입니다!😊 🌱

스터디 첫 주를 통째로 정리한 도커 노트, 회사에서 받은 요청에서 출발한 SEO 추적기, 그리고 "HTML은 어떻게 도착하는가"를 끝까지 파고든 기록. 3기 3회차입니다.

성장일지는 멤버들이 2주에 한 번씩 자신의 성장을 기록하는 활동이에요. 매 회차 운영진이 모든 글을 읽고, 그중 특히 마음에 남은 글을 함께 골라 큐레이션합니다.

 

01

🐳 도커 스터디 1주차 — Docker 소개 & 활용

박지수B 님

박지수B 님 원문에 실린 이미지
이런 내용이에요
도커·쿠버네티스 스터디의 첫 주차 기록입니다. 도커가 왜 나왔는지부터 시작해 아키텍처, 설치, 기본 명령어, docker run 옵션, 컨테이너 네트워크 모드, 도커파일까지 한 편에 담았어요.
명령어마다 주석이 붙어 있어서 그대로 따라 할 수 있습니다. 실습하며 친 명령을 정리해둔 형태예요.
그리고 함께 쓰면 안 되는 옵션 조합까지 적어뒀습니다. 직접 부딪혀본 사람만 남길 수 있는 부분이죠.

앞선 두 회차에서 JVM과 GC를 정리하셨던 그분입니다. 이번엔 인프라 쪽으로 넘어오셨어요.

조금 더 들어가 보면

글이 도커를 설명하는 순서가 좋습니다. 무엇인지보다 왜 나왔는지를 먼저 짚어요.

전통적으로는 OS 위에 애플리케이션을 바로 올렸습니다. 그러다 클라우드로 넘어오며 하이퍼바이저가 생겼고, 서버 하나에 가상 머신(VM)을 여러 대 띄우게 됐죠.

그런데 VM에는 무거운 지점이 있습니다. VM마다 운영체제를 통째로 하나씩 갖고 있어야 해요. 애플리케이션 하나 돌리려고 OS 전체를 띄우는 셈입니다. 부팅도 오래 걸리고 메모리도 많이 씁니다.

컨테이너는 여기를 바꿉니다. 호스트의 OS 커널을 함께 쓰고, 컨테이너 런타임만 얹어 프로세스를 격리해요. 그래서 글의 표현대로 "하이퍼바이저의 필요성이 사라졌다"는 말이 나옵니다.

"몇 초 만에 뜨고, 수십 개를 한 서버에 올릴 수 있다"는 도커의 특징이 여기서 나옵니다. 무거운 OS 계층을 걷어냈으니까요.

글이 짚은 디테일 하나도 재미있습니다. "도커는 유닉스 도메인 소켓 통신을 이용. TCP/IP 통신이 아니라서 빠르다." 도커 CLI와 도커 데몬은 같은 기계 안에 있으니 네트워크를 거칠 이유가 없죠. 파일처럼 생긴 통로로 바로 주고받습니다.

📝 원문에서는 이렇게 실습합니다

설치 직후 반드시 하게 되는 권한 설정이 있습니다.

# Ubuntu 사용자를 docker 그룹에 추가 (docker socket 접근 권한)
sudo usermod -aG docker Ubuntu

# 위 명령어 입력 후 SSH 재접속해야 함
exit

"SSH 재접속해야 함"을 적어둔 게 좋습니다. 그룹 변경은 다시 로그인해야 반영되거든요. 이걸 모르면 명령을 제대로 쳤는데도 계속 권한 오류가 나서, 뭘 잘못했나 한참 헤맵니다.

핵심 명령어는 이 한 줄에 다 들어 있습니다.

docker run \
  --name nginx-docker \
  -d \
  -p 3000:80 \
  -v $(pwd):/tmp-dir \
  --restart always \
  nginx:latest

옵션 하나씩이 각각 다른 문제를 풉니다.

· -d — 백그라운드 실행. 터미널을 닫아도 계속 돕니다

· -p 3000:80호스트 3000번을 컨테이너 80번에 연결. 컨테이너 안에서만 열린 포트를 밖에서 쓸 수 있게 만드는 다리예요

· -v $(pwd):/tmp-dir — 호스트 폴더를 컨테이너 안에 붙입니다. 컨테이너가 사라져도 데이터는 남습니다

· --restart always — 죽으면 다시 띄웁니다

-v(볼륨)가 특히 중요합니다. 컨테이너는 지워지면 안의 내용도 같이 사라지거든요. DB를 컨테이너로 띄웠는데 볼륨을 안 잡으면, 컨테이너를 지우는 순간 데이터가 전부 날아갑니다.

🧭 같이 쓰면 안 되는 조합

이 글에서 가장 실전적인 부분입니다.

--restart--rm은 같이 사용할 수 없다. (--restart: 죽으면 어떻게 계속 살릴지 / --rm: 죽었을 때 바로 제거)
-d-it는 함께 사용할 수 없다. (docker exec -it 활용)

첫 번째는 의미가 정면으로 부딪히기 때문입니다. "죽으면 살려라"와 "죽으면 지워라"를 동시에 시킬 수는 없죠.

두 번째도 마찬가지예요. -d는 "백그라운드로 보내라", -it는 "터미널을 붙여 상호작용하겠다"입니다. 등을 돌리고 대화할 수는 없습니다. 그래서 백그라운드로 띄운 다음 docker exec -it로 들어가는 게 정석이에요.

옵션의 뜻만 외우면 이런 충돌을 예측 못 합니다. 각 옵션이 무엇을 해결하려는 건지 알아야 조합이 보여요.

큐레이터 노트

스터디 첫 주를 통째로 남긴 것이 뽑은 이유입니다.

스터디에서 배운 내용은 대개 흩어집니다. 노트에 조금, 슬랙에 조금 남다가 결국 못 찾게 되죠. 이 글은 한 주 분량을 한 편에 묶었습니다. 나중에 도커를 다시 만났을 때 이 글 하나만 열면 됩니다.

그리고 명령어에 전부 주석을 단 형태가 실용적입니다. docker ps -a가 뭘 하는지 매번 검색하지 않아도 되게요. 같은 스터디를 하는 동료에게도 그대로 도움이 됩니다.

연재로 이어진 것도 좋았습니다. 2주차는 쿠버네티스, 3주차는 가용성과 네트워크. 1회차 JVM, 2회차 GC에 이어 이번 기수 내내 시리즈로 쌓아가고 계세요. 한 편씩 보면 정리 글이지만, 모아놓으면 학습 궤적이 됩니다.

원문 읽으러 가기  ↗zisooya.tistory.com/26
 

02

🏷️ 시맨틱 마크업 : 구글에서 내 사이트가 잘 보이지 않는 이유

신지훈 님

신지훈 님 원문에 실린 이미지
이런 내용이에요
회사에서 요청이 들어옵니다. "우리 사이트를 검색해도 다른 사이트가 나오거나, 아예 안 나온다."
확인해보니 사이트 이름 말고 다른 페이지들이 검색 순위에서 밀리고 있었어요. SSR로 SEO는 어느 정도 했다고 생각했는데 놓친 게 있었습니다. 바로 시맨틱 마크업이었죠.
시맨틱 태그가 왜 필요한지를 "이름표 없는 상자" 비유로 설명하고, 자주 쓰면서 헷갈리는 태그들을 정리했습니다.

1회차에서 Tanstack Query로 SSR을 붙이셨던 그분입니다. 그 작업의 후일담에 가까운 글이에요.

조금 더 들어가 보면

이 글의 출발점이 특별합니다. "SSR을 했는데도 검색이 안 된다."

1회차 글에서 이분은 SEO를 위해 SSR을 도입했습니다. 서버에서 HTML을 만들어 보내면 검색 엔진이 내용을 읽을 수 있으니까요. 맞는 판단이었습니다.

그런데 그것만으로는 부족했어요. 왜일까요.

SSR은 "검색 엔진이 글자를 볼 수 있게" 만듭니다. 시맨틱 마크업은 "그 글자가 무슨 역할인지 알게" 만듭니다. 둘은 다른 문제예요.

<div>로만 짠 페이지는 검색 엔진 입장에서 글자 덩어리입니다. 어디가 제목이고 어디가 본문이고 어디가 광고인지 구분이 안 돼요. 반면 <article>, <nav>, <header>가 붙어 있으면 구조가 읽힙니다.

글의 비유가 아주 좋습니다.

"<div>는 이름표가 없는 상자입니다. semantic 마크업이 들어간 태그는 이름표가 있는 상자라고 할 수 있겠죠."

그리고 팬더 인형 찾기 예시로 이어집니다. 이름표 없는 상자 열 개"팬더"라고 적힌 상자. 어느 쪽에서 빨리 찾을까요.

검색 엔진이 하는 일이 딱 그겁니다. 수십억 개의 상자를 열어보는 일. 이름표가 붙어 있으면 안 열어봐도 되죠.

🧭 그리고 SEO 말고도

글이 짚은 이점 중 SEO 말고 두 가지가 특히 중요합니다.

웹 접근성 — 시각장애가 있는 사용자는 스크린 리더로 페이지를 읽습니다. 이때 <nav>가 있으면 "메뉴 건너뛰기"가 가능해집니다. <div>뿐이면 매 페이지마다 메뉴를 처음부터 다 들어야 해요. 태그 하나가 실제 사용 경험을 바꿉니다.

코드 가독성 — 남이 짠 페이지를 열었을 때, <div>가 스무 겹 중첩된 것과 <header><main><aside>로 나뉜 것은 파악 속도가 다릅니다.

그리고 저자의 이 문장이 솔직해서 좋았습니다.

"저 또한 시맨틱 마크업을 알기 전 <div>로 활쏘기를 많이 했습니다."

자기가 그랬다는 걸 밝히고 시작하는 글은 읽는 사람을 편하게 만듭니다. 훈계가 아니라 공유가 되니까요.

🧭 <article><section>, 헷갈리는 지점

글이 "가장 많이 헷갈리는 태그"로 꼽은 둘입니다. 기준을 하나 더 얹어보면 이렇습니다.

<article>은 떼어내도 말이 되는가로 판단합니다. 블로그 글 하나, 뉴스 기사, 상품 카드처럼 RSS로 뽑아내도 온전한 것이면 <article>입니다.

<section>은 떼어내면 맥락을 잃습니다. "회사 소개" 안의 "연혁" 같은 것이죠. 그 페이지 안에서만 의미가 있습니다.

판별이 애매할 때 쓰는 실용적인 기준도 있습니다. 제목(<h2> 등)을 붙이는 게 자연스러운가. 자연스러우면 <section>이나 <article>이고, 어색하면 그냥 <div>가 맞습니다. 시맨틱 태그를 억지로 쓰는 것도 좋지 않아요.

큐레이터 노트

한 사람의 문제 해결이 두 회차에 걸쳐 이어진 기록이라 뽑았습니다.

1회차에 SSR을 붙였고, 3회차에 "그런데도 안 되더라"를 들고 왔습니다. 처음 세운 가설이 부분적으로만 맞았다는 걸 인정하고 다음 원인을 찾아간 과정이에요. 이런 연속성은 한 편짜리 글에서는 절대 안 보입니다.

회사에서 받은 실제 요청에서 출발한 것도 좋았습니다. "공부해봤다"가 아니라 "해결해야 했다"에서 나온 글이라 방향이 뚜렷해요. 검색 순위가 밀린다는 구체적인 증상이 있고, 그 원인을 찾아간 경로가 남았습니다.

이 저자의 다음 글이 "웹사이트에 구조화된 데이터 활용하기"더라고요. 시맨틱 마크업 다음 단계인 JSON-LD로 넘어가셨습니다. 하나의 문제를 계속 파고들고 계세요.

원문 읽으러 가기  ↗rec8730.tistory.com/158
 

03

📡 [1] HTML의 렌더링에 대해 궁금했던 것들 — stream

강단 님

강단 님 원문에 실린 이미지
이런 내용이에요
"HTML은 어떻게 도착하는가" 하나만 붙들고 끝까지 파고든 글입니다.
HTML은 다 받은 다음에 처리되는 게 아니라 스트림 형식으로 조금씩 도착하며 그때그때 파싱됩니다. 그러면 자연히 질문이 생기죠. "그 조각은 무슨 기준으로 쪼개지는가?"
답을 세 층으로 나눠 찾습니다. 서버 전송 방식 · 네트워크 패킷 크기 · 브라우저 버퍼링 정책. 그리고 브라우저별 버퍼 크기 차이까지 갑니다.

제목에 [1]이 붙어 있습니다. 연재의 첫 편이에요. 궁금증 하나가 시리즈가 된 경우입니다.

조금 더 들어가 보면

출발점은 아주 단순한 사실입니다. HTML은 통째로 오지 않습니다.

브라우저는 Content-Type: text/html을 보는 순간 "아, HTML이구나" 하고, 도착하는 대로 조금씩 읽어 파싱을 시작합니다. 다 받을 때까지 기다리지 않아요.

이게 왜 중요할까요. 긴 페이지의 윗부분이 먼저 보이는 이유가 여기 있습니다. 아직 아래쪽은 도착도 안 했는데 위쪽은 이미 화면에 그려져 있죠. 사용자 체감 속도를 결정하는 지점입니다.

여기서 글의 질문이 나옵니다. "그럼 그 조각은 무슨 기준으로 나뉘는가?" 보통은 여기서 멈추는데, 이 글은 안 멈춥니다.

1️⃣ 서버 전송 방식 — chunked transfer encoding

서버는 데이터를 조각(chunk) 단위로 실시간 전송할 수 있습니다. 글이 정리한 핵심이 이겁니다.

"크기를 몰라도, 데이터가 준비되는 대로, 조각조각 보내자."

HTTP/1.0에서는 응답에 반드시 Content-Length를 넣어야 했습니다. 전체 크기를 미리 알아야 했다는 뜻이에요. 그런데 DB를 조회해가며 HTML을 만드는 상황이면 다 만들기 전엔 크기를 모릅니다. 그럼 다 만들 때까지 아무것도 못 보내죠.

HTTP/1.1의 Transfer-Encoding: chunked가 이 제약을 풉니다. 완성 전에 보내기 시작할 수 있게 된 거예요.

그리고 글이 짚은 결정 요인들이 실무적입니다. 서버 설정(nginx, Express), 코드에서 flush() 호출 여부, 스트리밍 프레임워크(React 서버 컴포넌트) 사용 여부. React의 Streaming SSR과 Suspense가 왜 가능한지가 여기서 설명됩니다. 준비된 부분부터 흘려보내는 거니까요.

2️⃣ 네트워크 패킷 단위 — MTU

두 번째 층은 물리 계층입니다. 이더넷 패킷은 보통 1,400~1,500바이트예요. HTML이 그보다 크면 무조건 여러 패킷으로 쪼개집니다. 서버가 한 번에 보내려 해도 소용없어요.

글의 이 체감 설명이 좋습니다.

"1500bytes 체감 : 짧은 뉴스 기사 제목 하나 정도(짧은 HTML 덩어리). 진짜 조금임..."

숫자를 감각으로 바꿔준 부분입니다. 요즘 웹페이지 HTML이 수십~수백 KB인 걸 생각하면, 수십에서 수백 조각으로 나뉘어 온다는 뜻이에요.

3️⃣ 브라우저 버퍼링 정책 — 여기가 이 글의 백미

세 번째 층이 가장 흥미롭습니다. 조각이 도착해도 브라우저가 바로 파서에 넘기지 않습니다. 일단 버퍼에 모아뒀다가 조건이 맞으면 넘겨요.

그 조건이 브라우저마다 다릅니다.

· Chrome — 안정성 중시. 18KB 정도 쌓이면 넘김. 대신 스크립트·이미지 선제 로딩(preload)에 적극적

· Firefox8KB 정도에서 시작. 더 빨리 파싱하고 메모리 최적화에 신경

· Safari — 가장 공격적. 조금만 쌓여도 바로 넘김. 반응성은 높지만 잦은 파싱 요청으로 효율이 떨어질 수 있음

그래서 글의 결론이 이렇게 나옵니다.

"같은 환경, 같은 HTML 문서라도 브라우저마다 처리 속도가 다름."

"크롬에선 괜찮은데 사파리에선 좀 밀린다"는 현상의 뿌리가 여기 있습니다. 코드 문제가 아니라 버퍼 정책 차이일 수 있는 거예요. 특히 대형 스트리밍 페이지에서요.

큐레이터 노트

질문 하나를 끝까지 밀고 간 글이라 뽑았습니다.

"HTML은 스트림으로 온다"까지는 많은 자료에 나옵니다. 그런데 "그 조각은 무슨 기준으로 쪼개지나"를 묻는 사람은 드물어요. 더구나 답을 서버 → 네트워크 → 브라우저 세 층으로 나눠 찾아낸 건 상당한 작업입니다.

브라우저별 버퍼 크기까지 조사한 것이 특히 인상적이었습니다. 18KB, 8KB 같은 숫자는 쉽게 안 나오는 정보예요. 궁금증이 진짜였다는 뜻이죠.

그리고 이 글이 [1]편이라는 게 좋았습니다. 이어서 [2] HTML Parsing, [3] Render Tree로 계속됩니다. "궁금했던 것들"이라는 제목 그대로, 하나씩 해소해가는 연재예요. 성장일지가 바라는 형태입니다.

원문 읽으러 가기  ↗kangdanne.tistory.com/330

💡 세 편을 겹쳐 읽으며

세 글이 다루는 층이 다릅니다. 인프라, 마크업, 네트워크.

그런데 나란히 놓으면 웹페이지 하나가 만들어져 사용자에게 닿기까지의 경로가 됩니다.

박지수B 님의 도커는 그 페이지를 어디서 돌릴 것인가를 다룹니다. 컨테이너에 담아 어디서든 같은 환경으로 띄우는 일이요.

강단 님의 스트림은 그 서버가 만든 HTML이 어떻게 브라우저까지 가는가를 다룹니다. 조각으로 나뉘어 흘러가는 과정이요.

신지훈 님의 시맨틱 마크업은 도착한 그 HTML이 무엇을 말하고 있는가를 다룹니다. 사람에게도, 검색 로봇에게도요.

담기고 → 옮겨지고 → 읽히는 한 줄입니다.

그리고 세 글이 공유하는 태도가 하나 더 있어요. 셋 다 "된다"에서 멈추지 않았습니다.

도커는 명령어를 치면 컨테이너가 뜹니다. SSR을 붙이면 HTML이 나옵니다. 페이지를 열면 화면이 그려지고요. 전부 그냥 되는 일들이에요. 그런데 세 사람은 각자 그 안을 열어봤습니다. 옵션이 왜 충돌하는지, 왜 검색에는 여전히 안 잡히는지, 조각이 무슨 기준으로 나뉘는지를요.

이번 회차에서 가져갈 것

1. 컨테이너에는 볼륨을 챙기기. 컨테이너가 지워지면 안의 데이터도 사라집니다. DB나 파일을 다룬다면 -v는 선택이 아니라 필수예요.

2. 옵션은 뜻이 아니라 목적으로 이해하기. --restart--rm, -d-it가 같이 못 쓰이는 건 하려는 일이 정면으로 부딪히기 때문입니다. 목적을 알면 조합이 보여요.

3. SSR과 시맨틱 마크업은 다른 문제. SSR은 글자를 보이게 하고, 시맨틱 태그는 그 글자의 역할을 알게 합니다. 둘 다 해야 검색에 제대로 잡혀요.

4. <div> 대신 이름표 붙이기. <header>, <nav>, <main>, <article>. 스크린 리더 사용자에게는 태그 하나가 실제 경험을 바꿉니다. 다만 억지로 붙이진 마세요 — 제목을 붙이는 게 어색하면 그냥 <div>가 맞습니다.

5. 브라우저마다 다르게 보이면 코드만 의심하지 말기. 버퍼링 정책이 다르면 같은 HTML도 처리 속도가 다릅니다. 특히 큰 페이지에서요.


좋은 글 남겨주신 박지수B 님, 신지훈 님, 강단 님께 감사드립니다! 😊

다음 큐레이션으로 다시 찾아오겠습니다! 🌱

- 에디터 · 성장일지 큐레이터 -


※ 본 큐레이션은 각 저자가 공개한 글을 소개하는 것이며, 모든 원문의 저작권은 저자에게 있습니다. 저자 본인의 요청이 있을 경우 즉시 수정 또는 삭제합니다.

WRITE YOUR GROWTH

오늘의 배움을
내일의 성장으로.

기록은 나를 돌아보게 하고, 공유는 우리를 연결합니다.
당신의 다음 성장 이야기도 그로스로그에서 시작해보세요.

커뮤니티 둘러보기