HTML 입문 | Selenium·Playwright에서 사용하는 태그·속성·로케이터 기초 완벽 가이드

Selenium・Playwright로 테스트 자동화를 시작하면 “요소를 찾을 수 없다”, “로케이터 작성 방법을 모르겠다”는 벽에 부딪히는 경우가 많습니다. 그 근본적인 원인의 대부분은 HTML을 읽는 방법을 모르는 것에 있습니다. 이 글에서는 QA 엔지니어가 테스트 자동화에 필요한 HTML 기초 지식을 실례와 함께 알기 쉽게 해설합니다.

💡 용어 해설:「로케이터」란?

Selenium・Playwright에서 페이지 상의 요소를 특정하기 위한 지정 방법 전체를 로케이터라고 합니다. CSS 셀렉터나 XPath도 로케이터의 일종입니다. 이 글에서는 「셀렉터」라고 쓰이는 경우도 있지만, 도구 사양상 로케이터로 통일합니다.

📌 이 글의 대상 독자

✅ Selenium・Playwright를 막 시작해서 HTML을 거의 읽어본 적이 없는 분
✅ 로케이터를 작성할 때 무엇을 단서로 삼아야 할지 막막한 분
✅ DevTools에서 HTML을 봐도 어디를 봐야 할지 모르는 분
✅ HTML 경험은 없지만 QA・테스트 자동화에 도전하고 싶은 분

✅ 이 글을 읽으면 얻을 수 있는 것

  • HTML 태그・속성의 기본 구조를 이해할 수 있다
  • idclassdata-testid의 차이와 사용 방법을 알 수 있다
  • 테스트 자동화에서 자주 사용하는 HTML 요소와 로케이터의 대응 관계를 익힐 수 있다
  • DevTools에서 HTML을 봤을 때 “무엇을 찾아야 하는지”를 알 수 있게 된다

👨‍💻 이 글의 신뢰성에 대해

본 글은 QA 엔지니어로서 15년 이상 Selenium・Playwright를 활용한 테스트 자동화에 종사해 온 필자가 작성했습니다. “HTML을 몰라서 첫 로케이터조차 쓸 수 없었다”는 실제 경험을 바탕으로, 테스트 자동화에 정말 필요한 지식만 추려 해설합니다.

📌 이 글의 결론

  • 테스트 자동화에 필요한 HTML 지식은 「태그・속성・폼 요소」의 3가지로 압축된다
  • Selenium에서는 id → data-testid → name 순서로 찾는다. Playwright는 요소 종류에 따라 get_by_role() / get_by_label() / get_by_test_id()를 구분해서 사용한다
  • HTML을 읽을 수 있으면 DevTools 사용법도 훨씬 이해하기 쉬워진다

테스트 자동화 코드를 작성할 때 반드시 등장하는 것이 「요소 특정」입니다. Selenium이라면 driver.find_element(By.ID, "email"), Playwright라면 page.get_by_test_id("login-btn")처럼 작성하는데, 이 "email"이나 "login-btn"이라는 값은 어디서 오는 걸까요?

답은 HTML 안에 있습니다. 테스트 자동화 도구는 HTML 요소에 붙은 속성을 단서로 요소를 찾습니다. 그렇기 때문에 “HTML을 읽을 수 있는지”가 테스트 자동화 습득 속도에 직결됩니다. 웹 개발 지식이 없어도 괜찮습니다. QA로서 필요한 최소한의 지식만을 실제 예시로 확인해 봅시다.

HTML의 기본 구조:태그와 속성이란?

HTML�� 웹 페이지의 골격을 만드는 언어입니다. 테스트 자동화 도구가 「버튼을 누른다」「입력란에 문자를 입력한다」는 조작을 할 때, 그 요소를 HTML 속성을 단서로 찾습니다. DevTools에서 어떤 속성을 확인하면 좋은지Chrome DevTools 입문도 참고하세요.

태그의 기본

HTML�� 태그(<〜>)라는 부품의 조합으로 구성됩니다. 대부분의 태그는 「여는 태그」와 「닫는 태그」가 쌍을 이룹니다.


<button>로그인</button>

<p>이 문장이 단락입니다.</p>


<input type="text">

속성이란?

태그에는 속성을 추가할 수 있습니다. 속성은 「그 요소의 추가 정보」를 나타내며, 속성명="값"의 형태로 여는 태그 안에 씁니다.


<input type="email" id="user-email" name="email" placeholder="이메일 주소">

이 속성의 값이 바로 테스트 자동화에서 로케이터를 작성할 때의 단서가 됩니다.

테스트 자동화에서 중요한 속성 5가지

HTML��는 많은 속성이 있지만, 테스트 자동화에서 사용하는 속성은 한정되어 있습니다. 다음 5가지를 파악하면 대부분의 로케이터를 작성할 수 있습니다.

속성명역할로케이터에서의 사용법안정성
id페이지 내 고유 식별자By.ID / #email⭐⭐⭐ 최우선
data-testid테스트 전용 식별자[data-testid='xxx']⭐⭐⭐ 최우선
name폼 전송 시 키 이름By.NAME / [name='email']⭐⭐ 비교적 안정
class스타일 그룹명By.CLASS_NAME / .btn-primary⭐ 디자인 변경으로 깨지기 쉬움
typeinput의 종류 지정[type='submit']⭐⭐ 용도가 명확한 경우에 유효

① id 속성:가장 신뢰할 수 있는 식별자

id는 페이지 내에서 1개만 사용할 수 있다는 규칙이 있어 로케이터로서 가장 안정적입니다.


<input id="login-email" type="email">
<button id="login-btn">로그인</button>
# Selenium
driver.find_element(By.ID, "login-email")
driver.find_element(By.CSS_SELECTOR, "#login-btn")

# Playwright
page.locator("#login-email")
page.locator("#login-btn")

② data-testid 속성:테스트 전용 최강 식별자

data-testid는 테스트를 위해 개발자가 의도적으로 추가하는 속성입니다. 디자인 변경이나 기능 수정의 영향을 받기 어렵고, 테스트 자동화에서 가장 깨지기 어려운 로케이터로 권장됩니다.


<button data-testid="submit-button" class="btn btn-primary btn-lg">
  제출하기
</button>
# Selenium(CSS 셀렉터로 취득)
driver.find_element(By.CSS_SELECTOR, "[data-testid='submit-button']")

# Playwright(전용 메서드 사용)
page.get_by_test_id("submit-button")

💡 data-testid가 없을 때는 어떻게 하나요?

담당 개발자에게 “테스트용으로 data-testid를 추가해 주실 수 있나요?”라고 요청하는 것이 베스트 프랙티스입니다. 테스트 품질 향상으로 이어지므로 많은 현장에서 수락받을 수 있습니다.

실무에서는 id가 존재하지 않는 화면도 드물지 않습니다. 그럴 때는 data-testid 추가 요청이 첫 번째 선택지가 됩니다. 프로젝트 초기부터 개발자와 「테스트 속성 추가 규칙」을 정해 두면 나중이 편해집니다.

💡 HTML 태그에는 「역할(role)」이 있다

<button> 태그는 내부적으로 role="button"으로 취급됩니다. 이것이 Playwright의 page.get_by_role("button", name="로그인")이 작동하는 이유입니다. HTML 태그명이 그대로 역할로 사용된다고 기억해 두면 Playwright의 시맨틱 로케이터를 이해하는 데 도움이 됩니다.

③ class 속성:편리하지만 깨지기 쉽다

class는 스타일(외형)을 적용하기 위한 그룹명입니다. 여러 요소에 같은 class를 붙일 수 있어 로케이터로서는 불안정해지기 쉽다는 단점이 있습니다.


<button class="btn btn-primary btn-lg disabled">제출하기</button>
                         ↑ 디자인 변경·상태 변화로 바뀌기 쉬움


<button class="MuiButton-root css-1abcde">제출</button>   <!-- Material UI -->
<button class="chakra-button">제출</button>               <!-- Chakra UI -->
<button class="Button_btn__abc123">제출</button>          <!-- CSS Modules -->
                                     ↑ 빌드할 때마다 바뀔 가능성 있음

⚠️ class는 최후의 수단으로 생각하자

btn-primaryactiveselected 같은 class는 디자인 변경이나 상태 변화로 바뀔 수 있습니다. React・Vue 등 프레임워크에서 생성된 class(css-1abcde 등)는 빌드마다 바뀌는 것도 있습니다. id・data-testid가 없는 경우에만 class를 사용하도록 합시다.

테스트 자동화에서 자주 사용하는 폼 요소

웹 앱 테스트에서 가장 많이 등장하는 것이 폼 요소입니다. 로그인・회원가입・검색 등 대부분의 조작이 폼을 통해 이루어집니다.

폼 요소와 로케이터 대응표

HTML 태그화면 표시Selenium 코드 예시Playwright 권장
<input type="text">텍스트 입력란find_element(By.ID, "...")
.send_keys("값")
get_by_label("라벨명")
<input type="email">이메일 입력란find_element(By.ID, "...")
.send_keys("값")
get_by_label("이메일")
<input type="password">비밀번호 입력란 (마스크)find_element(By.ID, "...")
.send_keys("값")
get_by_label("비밀번호")
<input type="checkbox">체크박스find_element(By.ID, "...")
.click()
get_by_label("약관에 동의")
<button>버튼find_element(By.ID, "...")
.click()
get_by_role("button", name="로그인")
<select>드롭다운Select(element).select_by_value("값")select_option("값")
<textarea>여러 줄 텍스트 입력find_element(By.ID, "...")
.send_keys("값")
get_by_label("댓글")
<a>링크find_element(By.LINK_TEXT, "텍스트")get_by_role("link", name="텍스트")

실전:로그인 폼의 HTML을 읽고 로케이터 작성하기

실제 HTML을 읽고 로케이터를 작성하는 흐름을 확인해 봅시다.


<form id="login-form">
  <label for="email">이메일 주소</label>
  <input type="email"
         id="email"
         name="email"
         data-testid="login-email"
         placeholder="예:user@example.com">

  <label for="password">비밀번호</label>
  <input type="password"
         id="password"
         name="password"
         data-testid="login-password">

  <button type="submit"
          id="login-btn"
          data-testid="login-submit">
    로그인
  </button>
</form>

이 HTML에서 작성할 수 있는 로케이터 예시입니다.

# Selenium의 경우(id 우선)
email_input    = driver.find_element(By.ID, "email")
password_input = driver.find_element(By.ID, "password")
login_button   = driver.find_element(By.ID, "login-btn")

email_input.send_keys("test@example.com")    # 샘플 URL
password_input.send_keys("password123")
login_button.click()

# Playwright의 경우① get_by_test_id(data-testid가 있는 경우)
page.get_by_test_id("login-email").fill("test@example.com")    # 샘플 URL
page.get_by_test_id("login-password").fill("password123")
page.get_by_test_id("login-submit").click()

# Playwright의 경우② 시맨틱 로케이터(get_by_label / get_by_role)
page.get_by_label("이메일 주소").fill("test@example.com")    # 샘플 URL
page.get_by_label("비밀번호").fill("password123")
page.get_by_role("button", name="로그인").click()

로케이터를 선택할 때의 우선순위

Selenium의 경우:안정된 속성 기반 로케이터 우선

① id② data-testid③ name④ CSS⑤ XPath

왼쪽일수록 안정 · 오른쪽일수록 깨지기 쉬움

Playwright의 경우:요소 종류에 따라 구분해서 사용

Playwright의 방식은 고정된 절대 순위가 아니라, 요소의 종류에 맞는 로케이터를 선택하는 것이 기본 방침입니다. 적절한 선택은 상황에 따라 달라집니다.

요소 종류권장 로케이터예시
버튼・링크 등 인터랙티브 요소get_by_role()get_by_role("button", name="로그인")
label이 있는 입력 폼get_by_label()get_by_label("이메일 주소")
data-testid가 있는 요소get_by_test_id()get_by_test_id("login-submit")
위의 방법으로 취득하기 어려운 경우locator()locator("#email")
💡 Playwright의 사고방식:사용자 시점으로 요소를 취득할 수 있는 로케이터를 우선합니다. 다만 get_by_test_id()가 더 안정적인 케이스도 많아서, 실무에서는 상황에 맞게 구분해서 사용하는 것이 현실적입니다.

HTML을 읽을 때 자주 막히는 포인트

🚧 주의 포인트 목록

① id가 동적으로 생성되어 매번 바뀐다

프레임워크에 따라서는 id="input-3f9a"처럼 랜덤한 id가 생성됩니다. 이런 id는 사용할 수 없습니다. 개발자에게 data-testid 추가를 요청하는 것이 최선책입니다.

② class가 여러 개 있어서 어떤 것을 사용해야 할지 모르겠다

btn-primaryactiveselected 같은 class는 디자인 변경이나 상태 변화로 바뀔 수 있습니다. class는 id・data-testid를 찾을 수 없는 경우의 최후의 수단으로 생각하고, 적극적으로 사용하지 않도록 합시다.

③ get_by_label()이 동작하지 않는다

get_by_label("이메일 주소")가 동작하지 않는 경우, <label for="email"><input id="email">for/id가 일치하지 않을 가능성이 있습니다. DevTools에서 HTML을 확인해 보세요.

④ 같은 class명의 요소가 여러 개 있어 특정할 수 없다

class="list-item"이 10개 있는 경우, CSS 셀렉터만으로는 특정할 수 없습니다. 부모 요소의 id와 조합해서 좁히거나(예: #product-list .list-item:first-child), data-testid를 사용합시다.

⑤ 버튼이 <button>이 아닌 <div>나 <span>으로 만들어져 있다

화면상 버튼이지만 HTML에서는 <div class="custom-btn">인 경우가 있습니다. XPath나 CSS 셀렉터로 취득할 수 있지만, DevTools에서 실제 태그를 확인하는 습관을 들입시다.

자주 묻는 질문 (FAQ)

Q. HTML은 어디서 확인할 수 있나요?

브라우저의 Chrome DevTools (F12) → Elements 탭에서 확인할 수 있습니다. 확인하고 싶은 요소를 우클릭 → 「검사」를 선택하면 해당 요소의 HTML이 표시됩니다. 자세한 사용법은 Chrome DevTools 입문을 참고하세요.

Q. HTML을 본격적으로 공부해야 하나요?

테스트 자동화 목적이라면 본격적인 공부는 불필요합니다. 태그・속성・폼 요소의 기초와 DevTools에서 HTML을 읽는 감각을 익히면 충분합니다. 웹 제작자 수준의 지식은 필요 없습니다.

Q. id와 class의 차이를 잘 모르겠습니다.

id는 페이지 내에서 1개만 사용할 수 있는 이름(개인 이름 같은 것), class는 여러 요소에 붙일 수 있는 그룹명(팀 이름 같은 것)입니다. 테스트 자동화에서는 id 쪽이 고유(유일)하므로 로케이터로서 신뢰할 수 있습니다.

Q. data-testid는 누가 추가하나요?

기본적으로는 개발자(프론트엔드 엔지니어)가 추가합니다. QA 엔지니어가 “이 요소에 테스트용 data-testid를 추가해 주실 수 있나요?”라고 요청하는 형태가 일반적입니다. 테스트 품질 향상으로 이어지므로 많은 현장에서 흔쾌히 대응해 줍니다. 프로젝트 초기부터 개발자와 합의해 두면 원활합니다.

Q. data-testid는 반드시 있어야 하나요?

필수는 아니지만, 있으면 테스트가 크게 안정됩니다. id나 name을 사용할 수 있는 경우에는 그것을 사용하고, 없는 경우에는 개발자에게 data-testid 추가를 상담하는 것이 베스트 프랙티스입니다.

Q. Selenium과 Playwright에서 로케이터 작성법이 다른가요?

기본적인 사고방식은 같지만 작성법이 다릅니다. Selenium은 By.IDBy.CSS_SELECTOR 등 속성 기반이 중심이며, Playwright는 요소 종류에 따라 get_by_role()get_by_label()get_by_test_id()를 구분해서 사용하는 것이 권장됩니다. 두 도구 모두 HTML 속성을 단서로 한다는 점은 공통입니다.

Q. CSS 셀렉터와 XPath 중 어느 것을 사용하면 좋을까요?

Selenium에서는 CSS 셀렉터를 사용하는 경우가 많지만, Playwright에서는 get_by_role()이나 get_by_label() 같은 시맨틱 로케이터가 권장됩니다. CSS・XPath는 두 도구 모두에서 「위의 방법으로 취득하기 어려운 경우의 대체 수단」으로 사용합니다. 자세한 내용은 CSS 셀렉터・XPath 입문을 참고하세요.

정리

  • HTML은 태그+속성의 조합으로 이루어져 있다. 속성의 값이 로케이터의 단서가 된다
  • Selenium에서는 id → data-testid → name 순서로 찾는다. Playwright는 요소 종류에 따라 get_by_role() / get_by_label() / get_by_test_id()를 구분해서 사용한다
  • class는 디자인 변경・상태 변화로 바뀌기 쉬우므로 최후의 수단으로 취급한다
  • 폼 요소(inputbuttonselect)는 테스트 자동화에서 가장 많이 다루는 요소
  • DevTools에서 HTML을 확인하는 습관을 들이면 로케이터 선택이 훨씬 빨라진다

HTML�� 전부 외울 필요는 없습니다. “id・data-testid・name을 찾는다”,”폼 요소의 종류를 알고 있다”,이 2가지만으로 테스트 자동화의 첫 번째 벽을 크게 넘을 수 있습니다. HTML을 읽을 수 있게 되었다면 다음은 Chrome DevTools를 사용해 실제 페이지의 HTML을 조사해 봅시다. 셀렉터 검증까지 한 번에 할 수 있게 됩니다.

🗺️ HTML에서 테스트 자동화까지의 학습 맵

① HTML 읽기
← 지금 여기
② DevTools로 확인③ 로케이터 작성④ 테스트 실행

📚 함께 읽으면 좋은 관련 글

タイトルとURLをコピーしました