에이전트에게 페이지를 고쳐 달라고 하면, 간단한 프로젝트에 낯선 이름의 파일들이 생깁니다: index.html, style.css, script.js. 또는 파일은 원래 있었는데 에이전트의 보고서에는 "스타일을 바꿨습니다"라고만 적혀 있어서, 이 문장만으로는 정확히 무엇을 건드렸는지 알 수 없습니다.

브라우저가 받는 세 가지 기본 기술, HTML, CSS, JavaScript를 살펴보겠습니다. 이해하기 쉽도록 빌드 과정이 없는 간단한 정적 페이지를 예로 듭니다. 실제 저장소에서는 파일 이름과 위치가 다를 수 있으므로, 수정하기 전에 에이전트에게 프로젝트 구조를 보여 달라고 하고 원하는 요소를 담당하는 파일을 찾게 하는 것이 좋습니다. 직접 손으로 레이아웃을 짜는 법은 이 글에서 다루지 않습니다. 그 일을 하라고 에이전트가 있으니까요.

페이지는 브라우저가 읽는 텍스트입니다

간단한 정적 페이지부터 시작하겠습니다. 이런 페이지의 소스는 평범한 텍스트 파일입니다. 메모장으로 열어 눈으로 읽을 수 있습니다. 별도의 빌드도 필요 없습니다. 브라우저가 HTML을 읽고, 연결된 리소스를 불러온 다음, 그것을 바탕으로 화면에 페이지를 그립니다.

이런 프로젝트의 시작점은 보통 index.html 파일입니다. 브라우저는 이 파일을 열어 마크업을 해석하고, 링크를 따라 스타일, 스크립트, 이미지, 글꼴을 불러옵니다.

브라우저가 간단한 정적 프로젝트의 세 파일을 읽고 완성된 페이지를 표시합니다index.htmlstyle.cssscript.js브라우저완성된 페이지
간단한 정적 프로젝트는 이렇게 구성될 수 있습니다. 브라우저가 연결된 세 파일을 불러와 페이지를 보여 줍니다

빌드 과정이 있는 프로젝트에서는 소스가 컴포넌트 안에 있을 수 있고, 최종 HTML, CSS, JavaScript는 별도의 도구가 만들어 냅니다. 아래에서 설명하는 역할은 여전히 유용한 지도가 되지만, 이런 이름의 파일 세 개를 그대로 찾을 필요는 없습니다.

우리의 간단한 예시에서는 역할이 서로 다른 파일 세 개를 사용합니다:

  • HTML - 페이지에 무엇이 있는가: 제목, 단락, 버튼, 이미지;
  • CSS - 어떻게 보이는가: 색상, 글꼴, 여백, 모서리 둥글기, 부드러운 전환;
  • JavaScript - 무슨 일이 일어나는가: 클릭했을 때, 텍스트를 입력했을 때, 타이머가 울렸을 때.

이제 하나씩 보겠습니다.

HTML: 마크업은 무엇으로 이루어지는가

HTML은 그림을 그리는 것이 아니라 마크업입니다. 버튼이 어떻게 생겼는지 설명하지 않습니다. "여기에 버튼이 있다"라고만 말하면, 브라우저가 알아서 자기 방식대로 그립니다.

마크업의 기본 단위는 태그입니다. 태그는 거의 항상 한 쌍입니다. 여는 태그와 닫는 태그가 있고, 그 사이에 내용이 들어갑니다.

button 플레이 코드 한 줄을 세 부분으로 나눈 그림: 여는 태그, 내용, 닫는 태그이며, 전체에는 HTML 요소라는 이름이 붙어 있습니다<button>플레이</button>HTML 요소여는 태그닫는 태그내용
이 예시에서는 세 부분이 모여 페이지의 요소 하나를 이룹니다

부분마다 이름이 있고, 전체는 요소라고 부릅니다. 이 단어는 기억해 두면 좋습니다. 페이지를 이야기할 때는 태그와 그 안에 든 것을 한데 묶어 "요소"라고 부르는 경우가 더 많습니다.

태그 이름은 영어 단어의 줄임말입니다: p는 paragraph, a는 anchor, img는 image에서 왔습니다. 외울 필요는 없지만, 처음 보는 태그가 무슨 역할을 하는지 짐작하는 데는 보통 도움이 됩니다.

닫는 태그에는 슬래시가 붙습니다. 닫는 태그가 없는 요소도 있습니다. 예를 들어 <img>는 안에 텍스트나 다른 태그를 넣을 수 없고, 이미지 주소는 src 속성으로 받습니다.

태그는 상자 안의 상자처럼 서로 겹쳐 들어가고, 닫을 때는 반대 순서로 닫습니다. 안쪽을 먼저, 바깥쪽을 나중에 닫습니다. 순서를 어겨도 브라우저가 멈추지는 않고, 나름대로 짐작해 보려고 합니다. 그런데 그 짐작은 대개 빗나갑니다.

두 번째 개념은 속성입니다. 여는 태그 안에 들어가서 그 태그에 대해 무언가를 알려 주는 추가 정보입니다. 링크가 어디로 가는지, 이미지를 어디서 가져오는지, 이 요소를 무엇이라고 부르는지 같은 것입니다.

<a href="https://example.com">사이트 열기</a>
<img src="cover.png" alt="표지">
<button id="play" class="btn">플레이</button>

마지막 줄의 class 속성은 잠시 뒤에 다시 등장합니다. 이 속성을 통해 버튼에 스타일이 적용됩니다. id="play" 속성은 버튼에 고유한 이름을 붙이고, 스크립트는 이 이름으로 버튼을 찾습니다.

이제 페이지 전체를 보겠습니다. 생각보다 짧습니다:

<!doctype html>
<html>
<head>
  <title>내 페이지</title>
</head>
<body>
  <h1>첫 페이지</h1>
  <p>평범한 텍스트 단락입니다.</p>
  <button id="play" class="btn">플레이</button>
</body>
</html>

두 부분으로 나뉩니다. <head>는 보조 정보를 담는 부분으로, 탭 제목과 스타일 링크가 여기에 들어갑니다. <body>는 독자가 화면에서 보는 모든 것입니다. 첫 줄은 브라우저에게 이 문서가 최신 HTML이라는 것을 알려 줄 뿐입니다.

페이지의 중첩 구조: html 안에 탭 제목이 담긴 head와 화면에 보이는 모든 것이 담긴 body가 있습니다<html></html><head></head><body></body><title>내 페이지</title><h1>, <p>, <button>, <img>
상자 안의 상자: head와 body는 html 안에 있고, 나머지는 모두 그 둘 안에 있습니다

그림은 마크업의 핵심 성질을 보여 줍니다. 페이지의 모든 것은 무언가의 안에 들어 있습니다. <body>는 <html> 안에, 버튼은 <body> 안에, 텍스트는 버튼 안에 있습니다. 파일에서 들여쓰기가 계단처럼 이어지는 것도 그래서입니다. 보기 좋으라고 하는 것이 아니라, 무엇이 무엇 안에 들어 있는지 보여 주는 것입니다.

실용적인 결론은 간단합니다. 브라우저 탭 제목과 스타일 연결은 <head>에 있고, 화면에는 전혀 보이지 않습니다. 나머지는 전부 <body>에 있습니다. 에이전트가 보고서에 "body에 블록을 추가했습니다"라고 쓴다면, 바로 두 번째 상자 이야기입니다. 새로 추가된 것은 보조 정보 부분이 아니라 페이지에 나타납니다.

HTML 태그는 백 가지가 넘지만, 실제 페이지에서는 거의 늘 같은 태그들이 쓰입니다:

태그하는 일
<h1> ... <h6>제목, 가장 큰 것부터 가장 작은 것까지
<p>텍스트 단락
<a>링크, 주소는 href 속성에 있습니다
<img>이미지, 파일 경로는 src 속성에 있습니다
<button>버튼
<ul> 및 <li>목록 및 목록 항목
<div>블록 컨테이너, 다른 요소를 위한 상자
<span>줄 안의 텍스트 조각, 따로 구분해 꾸미고 싶을 때

마지막 두 태그는 그 자체로는 아무 의미도 없고 아무것도 그리지 않습니다. 스타일과 스크립트가 붙잡기 좋은 빈 상자일 뿐인데, 바로 그래서 어느 페이지에서나 가장 많이 보입니다.

CSS: 페이지는 어떻게 모양을 갖추는가

마크업만 있는 페이지는 밋밋해 보입니다. 흰 바탕에 검은 글자, 회색 기본 버튼, 모든 것이 왼쪽에 붙어 있습니다. 이런 페이지와 잘 꾸며진 페이지의 차이는 대부분 CSS가 만듭니다.

CSS는 규칙으로 이루어집니다. 규칙은 두 가지 질문에 대한 답입니다. 무엇에 적용하는가, 그리고 무엇을 바꾸는가.

.btn {
  background: #6c5ce7;    /* 배경색 */
  color: #ffffff;         /* 텍스트 색상 */
  padding: 12px 24px;     /* 안쪽 여백 */
  border-radius: 12px;    /* 모서리 둥글기 */
}

첫 줄은 선택자입니다. 이 규칙이 어떤 요소에 적용되는지 알려 줍니다. 그다음 중괄호 안에 "속성: 값" 쌍이 이어지고, 각 쌍은 세미콜론으로 끝납니다.

btn 앞의 점은 클래스라는 뜻입니다. 버튼에 있던 class="btn" 속성을 기억하시나요? 바로 그것이 쓰였습니다. 마크업에서 요소에 표시를 붙이고, 스타일에서는 그 표시를 가리킵니다. 같은 표시를 버튼 열 개에 붙이면, 규칙 하나로 열 개 모두 똑같은 모양이 됩니다.

CSS 속성은 수백 가지지만, 남이 작성한 파일을 읽고 무슨 일이 일어나는지 이해하는 데는 몇 개면 충분합니다:

  • color - 글자 색, background - 배경 색이나 배경 이미지;
  • font-size와 font-family - 글꼴 크기와 글꼴 종류;
  • padding - 요소 안쪽 여백, margin - 바깥쪽, 이웃 요소와의 간격;
  • border-radius - 모서리 둥글기, "고급스러운" 느낌의 절반은 이것이 만듭니다;
  • transition - 부드러운 전환: 뚝 바뀌지 않고 0.2초에 걸쳐 바뀝니다.

규칙은 대개 별도 파일에 있고, 페이지는 보조 정보 부분의 한 줄을 보고 그 파일을 알게 됩니다:

<head>
  <link rel="stylesheet" href="style.css">
</head>

이 줄을 지우면 스타일 파일이 로드되지 않습니다. 텍스트와 요소는 마크업에 그대로 남지만, 익숙한 배치와 꾸밈은 사라질 수 있고, 경우에 따라 페이지를 쓰기도 불편해집니다.

같은 마크업을 두 번 그린 그림: 왼쪽은 스타일 없이 텍스트와 회색 직사각형 버튼만 있고, 오른쪽은 같은 요소에 여백, 색상, 둥근 모서리가 적용되어 있습니다HTML만HTML + CSS
요소도 같고 순서도 같습니다. 바뀐 것은 색상, 여백, 모양뿐입니다

그림의 왼쪽과 오른쪽은 같은 페이지입니다. 제목, 두 줄의 텍스트, 버튼. 요소는 하나도 늘거나 줄지 않았습니다. 이 예시에서는 스타일 파일만 수정했습니다.

이것은 어디부터 찾아볼지 알려 주는 지도이지, 넘을 수 없는 기술적 벽이 아닙니다. 배치를 새로 바꾸려면 에이전트가 HTML의 클래스나 컨테이너를 고쳐야 할 때도 있고, 잘못된 CSS 규칙이 버튼을 가려서 클릭이 안 될 수도 있습니다. 그래서 화면을 수정한 뒤에는 diff를 보고, 페이지를 열어 영향을 받는 동작을 확인합니다.

JavaScript: 사용자의 동작에 무엇이 일어나는가

HTML과 CSS만으로도 페이지를 보여 주고 부드러운 전환이나 애니메이션을 넣을 수 있습니다. 하지만 예시의 버튼에는 아직 자기만의 동작이 없습니다. 눌러도 점수가 바뀌지 않습니다.

페이지에 원하는 로직을 넣는 일은 보통 JavaScript가 맡습니다. 버튼은 이미 HTML에서 id="play"라는 고유한 이름을 받았습니다. 이제 흐름은 간단합니다. 요소를 찾고, 이벤트를 기다렸다가, 무언가를 바꿉니다.

// id로 버튼을 찾습니다
const button = document.getElementById("play");
let score = 0;

// 이벤트를 구독합니다: 클릭하면 무엇을 할지
button.addEventListener("click", function () {
  score = score + 1;
  button.textContent = "점수: " + score;
});

첫 번째 클릭에서 버튼 글자가 "점수: 1"로, 두 번째 클릭에서 "점수: 2"로 바뀝니다. 아무 일도 일어나지 않는다면, 먼저 HTML에 id="play"라고 적혀 있는지, 스크립트에도 같은 이름 play가 쓰였는지 확인하세요.

여기서 눈여겨볼 점은 세 가지입니다. const와 let은 변수, 즉 값을 담는 이름 붙은 상자를 만듭니다. addEventListener는 페이지가 클릭, 텍스트 입력, 마우스 올리기 같은 이벤트를 구독하게 합니다. 그리고 중괄호 안에는 함수가 있습니다. 이벤트가 일어나면 실행될 코드 조각입니다.

마지막 줄을 보세요. 스크립트가 버튼의 텍스트를 바꿉니다. 여기서 중요한 점이 있습니다. JavaScript는 페이지가 동작하는 도중에 마크업도, 스타일도 바꿀 수 있습니다. 단락을 추가하고, 블록을 숨기고, 버튼 색을 바꿀 수 있습니다. 그러니 층 사이의 경계는 벽이 아니라 역할 분담입니다.

실제로는 요소가 데이터에 반응하거나, 클릭을 처리하거나, 무언가를 계산한다면 JavaScript부터 찾아보세요. 부드럽게 나타나기, 색 바꾸기, 간단한 움직임은 CSS가 처리하는 경우가 많습니다. 이것은 출발점일 뿐 최종 진단은 아닙니다. 수정한 뒤에는 페이지를 열어 모양과 동작을 직접 확인하세요. 스크린샷 한 장으로는 부족합니다.

버튼 하나, 파일 세 개

지금까지 본 것을 요소 하나에 모아 보겠습니다. "플레이" 버튼은 세 파일에 동시에 걸쳐 있고, 파일마다 맡은 일이 다릅니다.

<button id="play" class="btn">플레이</button>
.btn {
  background: #6c5ce7;
  border-radius: 12px;
}
const playButton = document.getElementById("play");

playButton.addEventListener("click", function () {
  playButton.textContent = "게임 시작됨";
});

파일이 제대로 연결되어 있으면, 클릭할 때 버튼 글자가 "플레이"에서 "게임 시작됨"으로 바뀝니다. 이제 없는 함수를 지어낼 필요 없이 예시를 직접 확인할 수 있습니다.

이제 가장 쓸모 있는 부분입니다. 한 줄씩 지우면 어떻게 될까요:

  • HTML을 지우면 모든 것이 사라집니다. 꾸미고 움직일 대상이 더는 없습니다;
  • CSS를 지우면 버튼은 그대로 있고 동작도 하지만, 90년대의 회색 기본 버튼처럼 보입니다;
  • JS를 지우면 버튼은 예쁘지만 죽어 있습니다. 눌리기는 하는데 아무 일도 일어나지 않습니다.

여기서 작업을 맡길 때 쓸 간단한 지도가 나옵니다. 보이는 모습이 마음에 들지 않으면 스타일부터 찾아보세요. 일어나는 일이 마음에 들지 않으면 스크립트부터 보세요. 요소가 아예 없다면 마크업부터 시작하세요. 어디까지나 "시작"입니다. 실제 수정은 이웃한 층까지 건드릴 수 있으므로, 에이전트의 결과는 diff와 브라우저에서 확인합니다.

프로젝트 폴더에는 무엇이 있는가

간단한 페이지에서 가장 흔한 구성은 이렇습니다:

index.html    마크업, 진입점
style.css     스타일
script.js     동작

세 파일은 마크업의 두 줄로 연결됩니다. 스타일은 보조 정보 부분에서 연결하고, 스크립트는 맨 끝, </body>로 닫기 바로 전에 연결합니다. 그래야 스크립트가 실행될 때 모든 요소가 이미 만들어져 있습니다:

<head>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <!-- 페이지 마크업 -->
  <script src="script.js"></script>
</body>

다른 경우도 있습니다. 큰 프로젝트에서는 파일이 수십 개이고, css/, js/ 같은 폴더에 나뉘어 있으며, 옆에 이미지와 글꼴도 있습니다. 반대로 파일이 하나뿐일 때도 있는데, 이 경우는 바로 아래에서 다룹니다. 마크업, 스타일, 로직이라는 역할은 그대로지만, 파일 이름과 연결 방식은 다를 수 있습니다.

스타일과 스크립트가 페이지 안에 있을 때

파일 세 개는 가장 흔한 구성이지만 유일한 방식은 아닙니다. 같은 CSS를 세 군데 서로 다른 곳에 둘 수 있고, 언젠가는 세 가지 모두 만나게 됩니다.

첫 번째는 이미 보셨습니다. 별도 파일에 <link> 한 줄을 더하는 방식입니다. 두 번째는 별도 파일 없이 마크업 안에 바로 넣는 <style> 블록입니다:

<head>
  <style>
    .btn {
      background: #6c5ce7;
      border-radius: 12px;
    }
  </style>
</head>

안의 내용은 똑같습니다. 선택자, 중괄호, "속성: 값" 쌍. 바뀐 것은 위치뿐입니다. 페이지가 하나뿐이라 따로 파일을 만들 이유가 없을 때 이렇게 씁니다.

세 번째 위치는 인라인 스타일입니다. 속성이 요소 자체의 style 속성에 바로 붙어 있습니다:

<button class="btn" style="background: #e17055; font-size: 20px">플레이</button>

여기에는 선택자가 필요 없습니다. 규칙이 어디에 적용되는지는 뻔합니다. 바로 그 규칙이 적힌 요소입니다. 그래서 중괄호도, 클래스 앞의 점도 없고, "속성: 값" 쌍을 세미콜론으로 구분해 한 줄에 씁니다.

편한 건 딱 한 번뿐입니다. 그다음부터는 단점이 드러납니다. 규칙이 요소 하나에만 적용되므로, 버튼이 열 개면 복사본도 열 개이고, 나중에 고칠 때도 열 개를 다 고쳐야 합니다. 또 일반적인 인라인 스타일은 대개 파일에 있는 일반 규칙보다 우선합니다. 버튼 색을 style로 칠해 놓고, 나중에 style.css에서 같은 속성을 고치면서 왜 색이 안 바뀌는지 모르게 됩니다. 그래서 style 속성은 가장 먼저 확인하는 곳 중 하나입니다. 우선순위의 자세한 규칙은 아직 몰라도 됩니다.

스크립트도 마찬가지인데, 위치가 두 곳뿐입니다. 별도 파일은 <script src="...">로 연결하고, 태그 사이에 코드를 바로 쓸 수도 있습니다:

<script>
  document.getElementById("play").addEventListener("click", function () {
    alert("게임 시작됨");
  });
</script>

나중에 찾아볼 수 있도록 표 하나로 정리해 두겠습니다:

무엇어디에 있는가HTML에서의 모습
스타일별도 파일<link rel="stylesheet" href="style.css">
스타일페이지 안의 블록<style> ... </style>
스타일요소에 직접style="color: red"
스크립트별도 파일<script src="script.js"></script>
스크립트페이지 안의 블록<script> ... </script>

극단적인 경우는 모든 것을 한곳에 몰아넣은 경우입니다. 마크업, <style> 블록, <script> 블록이 index.html 하나에 다 들어 있습니다. 나쁠 건 없습니다. 작은 페이지라면 오히려 이쪽이 간단합니다. 파일이 하나라 브라우저에서 열면 바로 동작하고, 중간에 빠지는 파일도 없습니다. 불편함은 나중에, 페이지가 커져서 이 긴 파일에서 무언가를 찾아야 할 때 시작됩니다. 그때는 보통 내용을 파일별로 나누고, 그러면 앞에서 본 세 파일 구성이 됩니다.

에이전트에게 "스타일 바꿔 줘"라고 하기 전에, 스타일이 어디에 있는지부터 확인하세요. 프로젝트에 index.html 하나만 있다면 style.css 파일은 없을 수 있고, 수정은 마크업 안에서 이루어집니다. 요소가 바뀌지 않는다면 세 가지를 확인해 달라고 하세요. 필요한 스타일 파일이 연결되어 있는지, 선택자가 맞는지, 인라인 style이나 더 강한 규칙이 없는지. 이렇게 하면 원인을 짐작하지 않고도 찾을 범위가 좁혀집니다.

Claude Code와 함께 쓸 때는 어떻게 되는가

이제 에이전트가 페이지 작업을 맡을 때 무슨 일이 일어나는지 알 수 있습니다:

  • 간단한 정적 프로젝트라면 에이전트가 HTML, CSS, JavaScript를 직접 작성하고 연결할 수 있습니다. 다른 프로젝트에서는 먼저 구조를 보여 주고 원하는 요소를 담당하는 파일을 알려 달라고 하세요;
  • 파일에 기록하기 전에 무엇을 볼 수 있는지는 설정과 작업 모드에 따라 다릅니다. 에이전트가 제안을 미리 보여 준다면 검토하세요. 어떤 경우든 기록한 뒤에는 diff와 최종 파일을 확인하세요. style.css라는 이름은 파일의 역할을 짐작하게 해 줄 뿐, 아무것도 보장하지 않습니다;
  • 화면 수정은 눈으로 보고 영향을 받는 요소를 직접 클릭해서 확인하고, 동작 수정은 실제로 조작해서 확인하세요. 카운터가 더 이상 올라가지 않는다는 사실은 스크린샷으로는 알 수 없습니다;
  • 무언가 고장 났다면 짐작한 층이 아니라 눈에 보이는 증상을 설명하세요: "수정한 뒤 버튼은 보이는데, 클릭해도 아무 반응이 없어요". 그러면 에이전트가 HTML, CSS, JavaScript 사이의 연결을 확인합니다.