QA 테스트 도구를 Go로 만들어 보면서…

이찬희
타운컴퍼니 기술블로그
8 min readApr 8, 2018

타운컴퍼니에서 R&D 파트는 매일 데일리 미팅(Daily Meeting)을 진행합니다. 미팅에서는 주로 전날 무엇을 했는지, 오늘은 어떤 일을 중점으로 진행할 것인지 그리고 업무 외로 서로 알아야 할 사항이 있다면 공유하여 업무를 더욱 유연하게 할 수 있도록 합니다.

얼마 전 미팅에서 기획자(이며 굉장히 많은 일을 하고, 적극적으로 다른 파트와 소통하기 위해 노-력하는) 하람님의 업무로 QA 코어 테스트 시나리오 작성이 있는 것을 알게 되었습니다. 업무의 요지는 기존에 작성된 시나리오는 모든 기능을 체크하기 위해 작성되어, 배포 후 점검을 위해 수행하기에는 볼륨이 상대적으로 컸습니다. 스모크 테스트(Smoke Test)로서 수행하기에 부적합했습니다.

기존 QA 시나리오를 수행하는 것보다 일찍 끝나겠지만, 사실 스모크 테스트를 위한 시나리오가 만들어지더라도 그것을 수행하기 위해 시간을 들여야 하는 것에는 변함이 없었습니다. 배포 후에는 테스트 외에도 할 일이 많고, 테스트가 오래 걸리면 개발 팀으로 피드백 되기까지의 시간이 길어집니다. 물론 하람님은 이것 말고도 할 일이 많고 또 많은 기획자(느님)입니다.

자동화 테스트 도구를 만들어야겠다.

그런 생각이 들고 나서, 어떻게 만들어야 할까 고민 하기 시작했습니다.

고민보다 Go

만약 제가 이전 회사에서 업무를 마무리 하는 동시에 Go를 배우지 않았다면, 그리고 여전히 관심이 없는 상태였다면. 아마도 높은 확률로 Node.js를 이용하여 툴을 만들었거나, 이번 기회에 파이썬을 공부하기 시작했을 수도 있습니다.

Go에 대해서 잠깐 적어보자면 굉장히 재밌는 언어입니다. 조금 과장을 섞으면 잠깐 관심을 줘버린 사이에 배워버리게 됩니다. 기본적인 개발 지식에 대한 이해가 뒷받침 되어 있다는 전제가 깔려있지만 그걸 감안하더라도 Go는 다른 언어들에 비해 확실히 배우기 쉬웠습니다.

하지만 Node.js는 개인적으로 자동화 프로그램을 만들어 본 경험에 비추어 볼 때, puppeteer나 PhantomJS 등 개발 경험은 좋았지만 다른 사람에게 배포, 특히 개발 환경이 구성되어 있지 않은 대상으로 배포하는 것이 늘 어려웠습니다. 내가 만든 프로그램을 이용하기 위해 Node.js를 설치하도록 유도하는 것이 늘 좋지 않았습니다. 퍼포먼스는 정확한 비교는 못하지만 그래도 인터프리터 보다는 빌드 된 바이너리가 나오는 Go가 더 빠르다는 생각을 갖고 있습니다.

백엔드에서 사용하는 파이썬을 고려하지 않은 이유는 장기적으로 배울 목적은 있지만 지금 당장 공부해서 사용하기에는 많은 어려움이 따를 것이라 예상됐습니다. 대표적으로는 지금 사용하고 있는 자바스크립트로 만들어도 많은 고민을 해야 할 텐데 언어의 이해까지 얹어서 가기는 좀 힘들 것 같았습니다. 파이썬은 그렇게 다시 인생의 과제로 돌려놓았습니다. 무엇보다 테스트를 진행 하시는 하람님은 어떤 생각을 하실지 모르겠지만 저는 빠르게 결과물을 보고 싶었습니다.

(출처: MBC 무한도전 캡쳐. 스스로에게 재촉을 좀 했습니다.)

만들자! 만들자!

‘그래서 어떤 걸로 만들까?’에 대한 고민은 굉장히 빠르게 접었습니다. 그때부터는 ‘어떤 것을 알아야 Go로 만들 수 있을까?’에 대해 고민하고 리서치하기 시작했습니다.

puppeteer나 PhantomJS의 유사한 라이브러리가 있는지 찾기 시작했습니다. Selenium을 먼저 찾았지만 Selenium과 Webdriver를 설치해야 해서 좀 더 찾아보았습니다. PhantomJS를 사용할 수 있는 라이브러리도 찾았습니다. 근데 왠지 사용하고 싶지 않았습니다. 이것도 설치하고자 하는 PC에 PhantomJS가 설치되어 있어야 했습니다.

그러다가 Chrome의 디버깅 프로토콜을 이용하는 chromedp 라는 라이브러리를 찾았습니다. 예제도 굉장히 잘 정리되어 있었고, 무엇보다 Chrome만 깔려 있다면 된다는게 퍽 좋았습니다. 기존에 사용하고 있는 프로그램이 있다면 사용 할 수 있다니. 저는 협소한 저장공간에 더 이상 새로운 무언가를 용납할 수 없습니다. 이것이 128GB 용량의 SSD가 달린 맥북 사용의 폐해입니다.

아무튼, 라이브러리를 받아온 뒤 기본 예제를 참고하여 코드를 작성했습니다.

emailLogin()에서는 아래와 같이 chromedp.Tasks를 반환합니다.

예상 한 대로 잘 작동 해 줄까요?

뭐야… 왜 안돼…

(출처: MBC 무한도전 캡쳐. 아니 진짜 뭐야?)

일단 ‘안된다’라는 표현의 뜻은 예상한대로 작동하지 않는다로 사용했고, 코드로 작성한 바와 같이 로그인 페이지로 이동 한 뒤 폼을 채우고 로그인 버튼을 클릭하는 게 안됩니다. 그리고 SendKeys()를 이용하여 입력을 하면 크롬 버전 페이지가 새 탭으로 나타납니다.

(니가 왜 거기서 나와…?)

왜 안되는 걸까요. 정확히는 왜 자꾸 버전 페이지가 나타나는 걸까요? chromedp 저장소에 Issue로 올라온 게 없는지 검색해 봤습니다. settings로 검색 해 보니 제가 겪은 문제와 정확히 일치하는 이슈를 찾았습니다. 해당 이슈를 올린 사람도 뭐만하면(…) 새로운 탭이 열리고 그 탭은 크롬 버전 페이지를 표시한답니다.

(출처: https://github.com/chromedp/chromedp/issues/130)

그리고 코멘트 목록 중에 지금 당장 해결 할 수 있는 방법도 적어주신 분이 있었습니다. Monkey-See-Monkey-Do, 크로미움 소스의 변경점을 참고하여 chromedp의 소스를 수정하면 잘 작동한다는 것입니다. 그래서 실제로 바꿔보고 다시 코드를 실행 해 보니 잘 됩니다. 다만 왜 잘되는지에 대해 이해할 수가 없어서 아쉬웠습니다. 찾아보니 Selenium 쪽에도 동일한 문제가 발생하는 듯 했습니다.

어쨌든 코드가 정상적으로 작동하기 시작했고, 일단은 시나리오의 일부를 코드로 작성하기 시작했습니다.

그런데 말입니다.

제가 지금 만들고자 하는 것은 ‘지금의 QA 시나리오’를 바탕으로 코드로 작성 하는 일입니다. 근데 QA 시나리오는 언제라도 변경 될 가능성을 지니고 있습니다. 지금도 타운컴퍼니는 타운어스의 UI/UX 개선을 위해 사용자 여정 지도를 정리 하고 있고, 이를 바탕으로 개선안이 나오면 새롭게 퍼블리싱이 진행 될 수도 있습니다. 그러면 QA는 또 다른 내용으로 변경되겠죠?

(출처: MBC 무한도전. 정말로 지끈 지끈…)

QA 시나리오가 그렇게 자주 변경되지는 않겠지만 바뀔 때 마다 다시 코드를 변경하는 작업할 수 있을까? 그리고 변경한다고 하면 시나리오대로 작동 할 때 까지 빌드 후 체크, 빌드 후 체크… 생각만 해도 지끈지끈합니다.

그래서 저는 코드. 즉 테스트를 진행하는 프로그램 시나리오는 의존적이지 않게 해야겠다고 생각했습니다. 시나리오에 대한 정보를 담은 파일을 프로그램에서 읽고, 그것을 토대로 chromedp.Tasks를 만들어서 수행하도록 하는 것이죠. 그렇다면 QA 시나리오가 변경되거나 또는 추가되거나 하더라도 개발자가 코드를 작업하는 대신 기획자가 수정할 수 있게 됩니다.

그렇다고 해서 기획자에게 Go 코드를 수정하라고 할 만큼 나쁜 사람은 아니지만 자연어 처리를 할 역량이 있는 사람은 아닙니다. 중간 타협을 위해 선택한 방법은 JSON… 이 아니고 YAML입니다.

JSON 대신 YAML을 선택 한 이유는 JSON보다 상대적으로 쓰기 쉬워서 입니다. 그리고 사실 이전에 YAML은 알기만 했었지 써본 적은 없어서 생각난 지금이 한 번 써보기에 제일 적합하겠다 싶었습니다. 그리고 YAML이라면 기획자가 수정하기 더 수월할 것이라고 생각했습니다. 그리고 주석을 사용할 수 있다는 점. 같은 내용을 JSON으로 쓴다면 주석을 사용할 수 없기 때문에 가독성이 매우 떨어집니다.

그래서 위와 같이 시나리오를 어떻게 수행해야 하는지 기술하는 파일을 만들었습니다. 이 파일을 파싱하여 각각 chromedp.Action 으로 만들어주고 하나로 묶어서 chromedp.Tasks 으로 만들어 반환하도록 했습니다.

이렇게 하니 원래 의도대로 프로그램과 시나리오가 독립적인 상태가 되었습니다. 샘플로 작성한 내용도 잘 작동합니다.

마치며

사실은 아직 실제로 사용하지 않아서 개발 이후에 발생할 수 있는 다른 이슈에 대해서 기록하지 못하는게 아쉽습니다. 그런 부분에 대해서는 나중에 다시 정리해 보도록 하겠습니다.

빌드 후 용량에 대해서 생각도 들었습니다. Go를 사용해 본 경험은 역시 재밌는 언어이지만 빌드 후 용량이 확실히 가볍다고는 못할 것 같습니다. 그러나 런타임을 포함하고 있느냐 아니면 (예를 들어) 닷넷 프레임워크처럼 분리되어 있느냐의 차이 인 것 같습니다.

앞으로 타운컴퍼니의 개발 조직에서 Go를 얼마나 더 활용할 수 있을지 모르겠지만 그럴 때 마다 블로그에 경험을 남기도록 해보겠습니다. 그리고 Angular에 대해서도 꼭 기술할 수 있도록 노력하겠습니다.

--

--