안녕하세요. SmartEditor BE 파트의 주니어 개발자 김일구입니다.
최근에 SmartEditor BE 파트의 테스트 코드 중 통합 테스트 부분을 Postman으로 옮기고 Jenkins로 자동화하는 작업을 진행하고 있습니다. 아직 작업이 완료되지는 않았지만, Postman과 Jenkins를 이용하여 어떤 작업을 하고 있는지에 대한 경험담과 적용하면서 만날 수 있는 문제와 해결 방안에 대해서 공유드리고자 합니다.
Postman을 적용하려는 이유
Postman 소개
Postman은 구동 중인 서버의 API 기능을 테스트하기 위해, 요청을 보내고 그에 따른 응답을 받을 수 있는 기능을 제공합니다. 요청에 필요한 URL, 파라미터, 헤더, 쿠키와 body를 설정할 수 있고, 요청에 따른 응답도 쉽게 확인할 수 있습니다. 또한 아래 그림처럼 JavaScript로 Postman의 테스트 코드를 작성하면, 요청을 보낸 후 받은 응답이 의도한 응답인지 아닌지에 대한 테스트를 할 수 있습니다.

Postman을 사용하게 된 계기
API 테스트는 MockMvc를 이용한 컨트롤러 테스트를 통해 충분히 할 수 있었지만, 실제 배포된 환경에서 모든 기능을 간편하게 테스트하기는 쉽지 않았습니다. Postman의 팀 워크스페이스에 테스트 코드를 작성해두면 팀 내의 모든 구성원들이 클릭 한 번으로 모든 테스트를 할 수 있다는 장점이 있습니다.
SmartEditor는 아래 그림에서처럼 네이버의 다양한 서비스 API를 이용하여 사용자에게 여러 가지 기능을 제공하고 있습니다. 이 모든 기능의 상태 체크가 간편해지면 혹시 모를 문제를 빠르게 파악할 수 있을 것입니다.

또한 Postman의 환경 변수를 아래 그림에서처럼 다양하게 지정할 수 있는데, 이 기능을 이용하면 개발 환경뿐만 아니라 QA, 스테이지, 리얼 환경에 대한 테스트도 간단히 진행할 수 있는 장점이 있습니다.

이러한 편리한 점으로 인해 Postman을 적용해 보기로 했습니다.
Jenkins로 테스트 자동화하기
Postman에서 작성한 테스트 코드는 Postman에서 간단히 실행할 수 있지만, 특정 시간에 자동으로 통합 테스트가 실행되고 테스트 결과를 기록하기 위해 Jenkins를 이용했습니다. Jenkins를 이용하면 개발 작업에 자동화 기능을 추가해 주기 때문에 반복 작업을 줄일 수 있습니다.
SmartEditor BE 파트에서는 아래 그림에서처럼 GitHub의 webhook과 Jenkins를 이용하여 특정 상황에서 Jenkins의 여러 스테이지가 실행되도록 구성되어 있습니다. 여기에 Postman 통합 테스트를 실행하는 명령어를 추가하여 하루에 한 번 통합 테스트가 Postman에서 실행되도록 할 예정입니다.

Postman에서 테스트를 실행해 주는 쉘 명령어는 Newman CLI라 불리며 Postman에서 제공하는 기능입니다. Jenkins에 원하는 옵션의 Newman 명령어를 추가하면 Postman에서 테스트를 실행할 수 있고, 테스트 결과도 기록할 수 있습니다. 아래 코드는 Newman 명령어의 예시입니다.
newman run /collections/project-collection
--environment /environments/project-dev-environment
--reporters cli,junit --reporter-junit-export 'newman/result.xml'
Jenkins를 적용하면서 만날 수 있는 문제와 해결 방법
Jenkins를 학습하고 자동화 기능을 추가하는 과정에서 여러 가지 문제를 만났습니다. 다음은 Postman 통합 테스트를 Jenkins 스테이지에 추가하면서 마주할 수 있는 문제와 해결 방법을 소개하겠습니다.
1. GitHub webhook 트리거 문제
GitHub의 webhook을 이용하면 특정한 이벤트가 있을 때 Jenkins가 실행되도록 할 수 있는데, 가끔 어떤 이벤트의 경우 webhook이 작동했음에도 Jenkins가 실행되지 않는 경우가 있을 수 있습니다. 특히 PR이 머지되는 상황에서는 의도대로 Jenkins가 실행되지 않는 것을 발견하여 해결 방법을 찾아보았습니다. 해결 방법 중 하나로 GitHub Action을 사용하는 방법이 있습니다. GitHub Action은 트리거 되는 조건을 상세히 설정할 수 있는 기능을 제공해서, 트리거 되는 상황이 복잡하거나 Jenkins가 실행되지 않는 상황에 사용할 수 있습니다.
on:
pull_request:
branches:
- develop
types: [closed]
jobs:
build:
name: Build
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- name: trigger single Job
uses: appleboy/jenkins-action@master
with:
url: "https://url.com"
user: "ilgoo"
token: ${{ secrets.TOKEN }}
job: "multibranch-test/test-jenkins"
GitHub Action은 위의 코드처럼 yaml 파일에 상세한 설정을 할 수 있기 때문에, PR이 머지되는 경우에만 Jenkins가 실행되도록 요청을 보낼 수 있습니다.
2. HTML 테스트 결과 리포트 생성 시 문제
두 번째로, Postman의 통합 테스트의 결과 리포트를 HTML 페이지로 제공해 주는 newman-reporter–htmlextra를 사용할 때 문제가 생길 수 있습니다. 리포트 기능은 아래 코드에서처럼 Newman 명령어로 Postman 테스트를 실행할 때 옵션으로 붙여서 사용할 수 있는 기능입니다.
newman run /collections/project-collection
--environment /environments/project-dev-environment
--reporters htmlextra
위 코드가 실행됐을 때 테스트 결과가 아래 왼쪽 그림처럼 생성되어야 하지만, 실제 페이지는 오른쪽 그림처럼 생성됩니다.


Jenkins 가이드 문서에 따르면, Jenkins는 XSS 방지를 위해 엄격한 Content-Security-Policy가 적용되어 있어서 Jenkins 플러그인을 이용한 HTML 리포트 생성 시 스타일 적용이 안되도록 설정되어 있습니다. 이를 해결하는 방법 중 하나는 Jenkins가 보내는 응답 헤더의 Content-Security-Policy를 완화해서 Javascript와 CSS가 동작하도록 허용해 주는 방법이 있는데, Jenkins의 보안 수준을 낮추는 작업이어서 권장되지 않는 방법입니다. 다른 방법은 resource root URL을 이용하는 방법으로 Jenkins 서버에 다른 도메인 이름을 추가해서, 추가된 도메인 주소로는 테스트 결과 리포트 만을 허용하도록 하는 방법이 있습니다. 또 다른 방법은 대시보드 형태의 결과 리포트를 사용하지 않고 JUnit 테스트 결과 리포트를 사용해서 간단히 테스트 결과만 확인하는 방법이 있습니다.
3. JUnit 테스트 결과 리포트 생성 시 문제
테스트 리포트 생성 시 Jenkins에서 JUnit 플러그인을 사용하면 Newman CLI로 생성되는 XML 형식의 테스트 리포트를 아래 그림과 같은 모습으로 출력해 주어 테스트 결과를 쉽게 확인할 수 있습니다.

이 과정에서 아래와 같은 에러가 발생하고 XML 테스트 리포트도 생성되지 않는 문제가 발생할 수 있습니다.

이는 Postman의 컬렉션 명이나 테스트 명에 XML 1.0 버전에서 허용하지 않는 문자가 들어있을 때 생길 수 있는 에러입니다. Newman에서 사용하는 JUnit 테스트 결과는 XML 1.0을 사용하고 있었고, 이 때문에 유니코드 #x20
보다 작은 control codes와 같은 문자가 있을 때 위와 같은 에러가 생길 수 있습니다. XML 1.0에서 허용하고 있는 문자는 아래와 같이 정의하고 있습니다.
Char ::= #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
/* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF. */
위의 정의에 따르면 #x20
보다 작은 유니코드 문자 중 일부를 제외하고 모두 허용되지 않는 문자이기 때문에 XML 1.0 리포트가 생성되는 과정에서 에러가 생길 수 있습니다. 특히 Mac OS에서 한글을 입력할 때 이러한 control codes 문자가 자주 발생할 수 있기 때문에 주의가 필요합니다. XML에서 허용하지 않는 control codes에 대한 자세한 내용은 W3C 표준의 문서에서도 확인하실 수 있습니다.
느낀 점
통합 테스트를 Postman으로 옮기고, 자동화 기능을 추가하면서 Postman과 Jenkins에 대해 자세히 살펴볼 수 있었습니다. 특히 통합 테스트 과정을 구상하고 적용해나가며 현재 구축되어 있는 지속적 통합에 대해 더 파악할 수 있었던 시간이었습니다. 적용 과정에서 에러를 만나면서 Postman과 Jenkins와 같은 기술의 새로운 부분을 추가로 배울 수 있었고, 이 기술의 한계점에 대해서도 알아볼 수 있었습니다.
이후에도 SmartEditor 서버 영역의 통합 테스트를 Postman의 통합 테스트로 전환하는 작업을 계속할 예정이며, 지속적 통합 시 테스트를 더 가볍게 만들 수 있는 방법과 더 편한 통합 테스트를 위해 추가적인 요구사항에 대해 논의해 보고 적용해나갈 계획입니다.