Selenium에서 XPath 마스터하기: 요소를 찾는 방법
소프트웨어 개발 생명주기에서 테스트 엔지니어는 핵심적인 역할을 합니다. 이들은 팀이 오류 없이 작동하는 애플리케이션을 제공하는 데 필수적입니다. 테스트 엔지니어는 애플리케이션이 사용자에게 배포되기 전에 다양한 테스트를 진행하여 안정성을 확보합니다.
테스터는 웹 요소를 정확하게 식별하고 상호 작용할 수 있는 능숙한 기술을 갖춰야 합니다. Selenium은 현대 개발 팀에서 테스트 자동화에 가장 많이 활용되는 도구 중 하나입니다. Selenium은 Selenium Grid, Selenium WebDriver, Selenium IDE, Selenium RC라는 네 가지 주요 구성 요소로 이루어져 있습니다.
이번 글에서는 XPath와 함께 사용되는 Selenium WebDriver에 집중하여 살펴볼 것입니다. XPath의 정의, 기본 구문, 그리고 Selenium 환경에서 XPath를 활용하는 방법을 자세히 알아보겠습니다.
XPath란 무엇인가?
XPath(XML Path Language)는 XML 문서 내의 특정 요소와 속성을 검색하고 조작하기 위한 쿼리 언어입니다. XPath는 경로 표현식을 사용하여 XML 문서의 특정 부분을 지정하고, 그로부터 정보를 효율적으로 추출하는 방법을 제공합니다.
XPath의 구문은 파일 시스템 경로와 유사하며, 속성과 계층 구조를 기반으로 요소를 선택하는 데 유용한 기능과 기호를 포함하고 있습니다. XPath는 XML, HTML, XSLT 등 다양한 기술과 함께 데이터 추출 및 조작에 사용됩니다.
XPath를 사용하는 이유는 무엇인가?
- 유연성: XPath는 태그 이름, ID, 클래스 외에도 다양한 속성을 사용하여 웹 요소를 식별할 수 있습니다. CSS 선택자와 달리 더 다양한 방법으로 요소를 찾을 수 있습니다.
- 재사용성: XPath 표현식을 변수에 저장하여 코드 내에서 재사용함으로써 효율성을 높일 수 있습니다.
- 정확한 노드 선택: XPath는 웹 문서 내의 특정 요소를 정확하게 지정하는 표준화된 방법을 제공합니다.
XPath의 기본 구문
XPath를 사용하면 DOM을 통해 웹페이지 내의 모든 요소를 검색할 수 있습니다. 기본 구문을 이해하기 전에 다음 XPath 표현식에 대한 이해가 필요합니다.
표현식 | 설명 -----|----- nodename | nodename 또는 tagname으로 지정된 모든 노드를 선택합니다. / | 루트 노드에서 선택합니다. // | 문서 내 어느 위치에 있든 선택 항목과 일치하는 노드를 선택합니다. . | 현재 노드를 선택합니다. .. | 현재 노드의 부모 노드를 선택합니다. @ | 속성을 선택합니다.
XPath의 표준 구문은 다음과 같습니다.
XPath=//tagname[@attribute="value"]
위 구문에서 이중 슬래시(//)는 탐색을 시작하는 위치를 나타내며, 이후 태그/노드 이름으로 정의된 현재 노드를 지정합니다.
절대 XPath 대 상대 XPath
XPath를 사용할 때 두 가지 주요 경로 유형이 있습니다. 절대 XPath와 상대 XPath입니다.
절대 XPath
절대 XPath는 루트 노드에서 시작하여 목표 요소까지의 직접 경로를 지정합니다. 즉, 문서의 최상위 노드부터 시작하여 특정 노드까지 모든 단계를 명시적으로 나타냅니다.
다음 HTML 코드를 예시로 들어보겠습니다.
<!DOCTYPE html>
<html>
<head>
<title>koreantech.org</title>
</head>
<body>
<div>
<h1>Welcome to koreantech.org</h1>
</div>
</body>
</html>
위 코드에서 "koreantech.org에 오신 것을 환영합니다"라는 텍스트를 포함하는 <h1> 요소를 찾으려면 다음 경로를 사용할 수 있습니다.
/html/body/div/h1
위의 경로는 다음과 같이 해석됩니다.
- /html: 루트 노드인 <html> 요소
- /html/body: <html> 요소의 자식인 <body> 요소
- /html/body/div: <body> 요소의 자식인 <div> 요소
- /html/body/div/h1: <div> 요소의 자식인 <h1> 요소
따라서 가장 안쪽 요소에 접근하기 위해서는 이 경로를 정확히 따라야 합니다.
절대 XPath를 사용해야 하는 경우
절대 XPath는 정확한 경로를 따라야 하므로, 페이지 내에 유사한 속성을 가진 여러 요소가 있을 때 특정 요소를 정확하게 선택하는 데 유리합니다. 하지만 HTML 문서 구조의 작은 변화에도 매우 민감하게 반응하므로, 구조가 변경되면 XPath가 작동하지 않을 수 있다는 단점이 있습니다.
상대 XPath
상대 XPath는 문서 내의 어느 노드에서든 시작하여 대상 노드에서 끝나는 경로입니다. 이 방식은 문서 구조의 변경에 덜 민감하며, 일반적으로 더 유연하고 안정적이어서 선호됩니다. 상대 XPath를 사용하면 문서의 어느 위치에서든 요소를 검색할 수 있습니다. 상대 XPath 표현식은 이중 슬래시 ‘//’로 시작합니다.
앞서 제시된 HTML 문서에서 "Welcome to koreantech.org"라는 텍스트를 가진 <h1> 요소를 찾기 위한 상대 XPath는 다음과 같습니다.
//body/div/h1
상대 XPath를 사용해야 하는 경우
상대 XPath는 유연성과 정확성 사이의 균형을 제공합니다. 이 경로는 요소 간의 관계가 명확하게 유지되는 한 HTML 문서 변경에 더 강건합니다.
Selenium에서 XPath를 사용하여 요소 찾기
Selenium은 웹 브라우저 자동화를 위한 오픈 소스 프레임워크입니다. 이 프레임워크는 테스터가 웹 요소와 체계적이고 자동화된 방식으로 상호 작용할 수 있도록 돕는 다양한 라이브러리와 도구를 제공합니다.
다음과 같은 노래 목록을 포함한 웹 문서를 예시로 들어보겠습니다.
<!DOCTYPE html>
<html>
<head>
<title>Song Library</title>
</head>
<body>
<h1>Song Library</h1>
<ul class="song-list">
<li class="song" title="Song Title 1">Song 1 - Artist 1</li>
<li class="song" title="Song Title 2">Song 2 - Artist 2</li>
<li class="song" title="Song Title 3">Song 3 - Artist 1</li>
<li class="song" title="Song Title 4">Song 4 - Artist 3</li>
</ul>
</body>
</html>
- 루트 노드는 <html>입니다.
- <body>는 부모 노드입니다.
- <h1>은 <body>의 자식 노드입니다.
- <ul>은 <body>의 자식 노드입니다.
- <li>는 <ul>의 자식 노드입니다.
위 HTML 문서에서 다양한 XPath 로케이터를 사용할 수 있습니다. 예를 들어 ID, 이름, 클래스 이름, 포함된 텍스트, 시작 텍스트, 종료 텍스트 등을 사용하여 요소를 찾을 수 있습니다. Selenium은 다양한 프로그래밍 언어를 지원하며, 여기서는 Python을 사용하여 설명하겠습니다.
인덱스를 사용하여 찾기
세 번째 노래를 찾고 싶다면 다음 코드를 사용할 수 있습니다.
third_song = driver.find_element_by_xpath("//li[@class='song'][3]")
print("Third Song:", third_song.text)
위 코드에서는 상대 XPath를 사용하여 ‘li’ 노드에서 시작합니다. Selenium이 목록에서 세 번째 노래를 찾으면 해당 텍스트를 출력합니다.
속성을 사용하여 찾기
‘Artist 1’의 모든 노래를 찾고 해당 제목을 출력하는 XPath를 사용할 수 있습니다. 코드는 다음과 같습니다.
songs_by_artist1 = driver.find_elements_by_xpath("//li[contains(@class, 'song') and contains(text(), 'Artist 1')]")
print("Songs by Artist 1:")
for song in songs_by_artist1:
print(song.text)
텍스트를 사용하여 찾기
이 로케이터는 특정 텍스트를 포함하는 요소를 찾는 데 유용합니다. 예를 들어, "Song 4"라는 텍스트를 가진 노래를 찾아 해당 텍스트를 출력할 수 있습니다. 이 코드를 사용하여 로케이터를 표현할 수 있습니다.
song_with_text = driver.find_element_by_xpath("//li[contains(text(), 'Song 4')]")
print("Song with Text:", song_with_text.text)
XPath 축
지금까지 설명한 방법들은 간단한 웹 페이지에서 잘 작동합니다. 하지만 때로는 텍스트, ID, 클래스 이름과 같은 기본적인 XPath 검색 방법이 작동하지 않을 수 있습니다. 이럴 때 XPath 축을 활용하여 동적 콘텐츠를 검색할 수 있습니다.
XPath 축은 다른 요소와의 관계를 기반으로 요소를 찾을 수 있게 합니다. 다음은 일반적으로 사용되는 XPath 축 로케이터의 몇 가지 예입니다.
조상
조상 축 방법은 중첩된 요소가 많은 XML 문서를 다루는 데 적합합니다. 이 방법을 사용하면 현재 노드의 모든 조상 요소(가장 가까운 것부터 가장 먼 것까지, 부모, 조부모 등)를 선택할 수 있습니다.
다음 XML 코드를 예시로 들어보겠습니다.
<bookstore>
<book>
<title>The Great Gatsby</title>
<author>F. Scott Fitzgerald</author>
<genre>Fiction</genre>
</book>
<book>
<title>The Biggest Dilemma</title>
<author>George Orwell</author>
<genre>Dystopian</genre>
</book>
</bookstore>
만약 "The Biggest Dilemma"라는 제목을 가진 책의 ‘title’ 요소의 모든 조상을 선택하고 싶다면 조상 축 방법을 사용할 수 있습니다.
//title[text() = '1984']/ancestor::*
팔로잉
팔로잉 축 방법은 현재 노드의 닫는 태그 뒤에 오는 모든 노드를 찾습니다. 이 방법은 대상 노드의 계층 구조나 위치를 고려하지 않고 단순히 문서 순서대로 뒤에 나타나는 노드를 선택합니다. 예를 들어 XML 문서나 여러 섹션으로 나뉜 웹페이지에서 특정 섹션 뒤에 나타나는 요소를 쉽게 식별할 수 있습니다.
부모
XPath의 부모 축 메서드는 현재 노드의 부모 노드를 선택합니다. 다음 경로를 사용하여 부모 노드를 찾을 수 있습니다.
//tag[@attribute="value"]/parent::tagName
이 방법은 현재 노드의 자식 요소에 쉽게 식별할 수 있는 고유 속성이 있고, 부모 노드를 통해 이를 확인하고 싶을 때 유용합니다.
자식
XPath의 자식 축 메서드는 현재 노드의 모든 자식 노드를 선택합니다. 이 방법은 특정 요소의 하위 노드를 선택하는 데 매우 유용하며, XPath 축 방법 중 가장 인기 있는 방법 중 하나입니다.
다음 코드를 살펴보겠습니다.
<section id='text'>
<p>Paragraph one</p>
<p>Paragraph two</p>
<p>Paragraph three</p>
<p>Paragraph four</p>
</section>
이 축을 사용하면 코드에서 모든 ‘p’ 요소를 찾을 수 있습니다.
//section[@id='text']/child::p
자주 묻는 질문
CSS 선택기 대신 XPath를 사용하는 이유는 무엇입니까?
CSS 선택기는 ID, 태그 이름, 클래스 등을 기반으로만 요소를 찾을 수 있습니다. 반면에 XPath는 위치, 텍스트 콘텐츠, HTML 구조의 다른 특성을 기반으로 요소를 찾을 수 있습니다. 또한 XPath 표현식을 변수에 저장하고 애플리케이션에서 재사용할 수 있습니다.
Selenium에서 XPath는 어떤 언어를 지원합니까?
Selenium을 지원하는 모든 언어에서 XPath를 사용할 수 있습니다. JavaScript, Java, Python, Ruby, C#, PHP 등으로 스크립트를 작성할 수 있습니다.
XPath의 대안은 무엇입니까?
CSS 선택기, 이미지 인식 또는 Selenium의 내장 로케이터를 XPath 대신 사용할 수 있습니다. CSS 선택자는 가장 일반적인 대안 중 하나이며 태그 이름, ID, 클래스를 기반으로 요소를 찾을 수 있습니다. 이미지 인식은 이미지를 기반으로 요소를 찾는 데 사용됩니다. Selenium의 내장 로케이터는 사용 편의성을 높이기 위해 설계되었습니다.
결론
이제 Selenium에서 XPath를 정의하고, 절대 XPath와 상대 XPath의 차이점을 이해하고, 다양한 XPath 로케이터를 사용하여 요소를 찾을 수 있게 되었습니다. 어떤 로케이터를 사용할지는 콘텐츠의 특성과 최종 목표에 따라 결정됩니다.
만약 면접을 준비하고 있다면 Selenium 인터뷰 질문 관련 글을 참고하는 것이 도움이 될 수 있습니다.