
이번에는 인텔리제이가 제공하는 api 테스트 플러그인인 http client를 사용해보겠습니다.
기존에는 IDE 를 Visual Studio Code 를 사용하면서 http yac 플러그인으로 http 테스트를 했었는데요. 이번에 IntelliJ Ultimate 버전을 쓸 수 있게 되면서 내부 플러그인인 http client 를 통해 테스트 하는 방식으로 바꾸게 되었습니다. (커뮤니티 버전은 http client 를 사용할 수 없어요)
http yac 과 구분하기 위해서 최상위 디렉토리/https-intellij/로 설정했습니다.host 정보 등이 들어갈 수 있습니다. 세부 설정은 아래 env 변수 파트에서 추가로 확인해보세요!.http 나 .rest 로 끝나는 파일을 작성합니다. 

http-client.env.json 이라는 파일이 필요합니다. http 파일을 관리하는 디렉토리 내에 위치시키면 되고, 직접 파일을 만들거나 http 파일 상단의 기능을 통해 추가할 수 있습니다.

public 과 private 으로 파일을 나눌 수 있고, private 의 경우 http-client.private.env.json 이라는 파일로 생성이 됩니다.
IDE 상에서 gitignore 를 시켜준다고는 하는데 그것보다는 .gitignore 내에 명시적으로 푸시를 막는게 좋아보이긴 해요!
전 public, private 파일 외에 _http-client.private.env.json 이라는 파일을 추가로 작성하고, private 을 위한 틀을 담아뒀어요. 다른 사람들도 이 형식으로 private 파일을 작성해둬야 기능을 쓸 수 있거든요. 이렇게 틀을 만들고, README에 파일명을 바꾸고 내부 정보를 바꿔서 사용하라고 안내했어요.
{
"dev": {
"loginId": "testId1",
"loginPassword": "password1"
},
"prod": {
"loginId": "testId2",
"loginPassword": "password2"
}
}
private 과 public 둘다 작성 양식은 똑같고, 위처럼 각 환경(dev, prod 등)마다 각 변수를 어떻게 쓸 지 정의하면 돼요.
만약 둘 다 같은 변수가 정의되어 있다면, 최종적으로 private 의 값이 사용되게 되니 참고하세요!
http 파일 내에서는 {{변수명}} 으로 값을 가져다 쓸 수 있어요.
### 로그인
# @name: login
POST {{host}}/login
Content-Type: {{requestContentTypeJson}}
{
"id": "{{loginId}}",
"password": "{{loginPassword}}"
}
참고로 http 파일 내에 지역 변수를 선언할 수도 있는데요, 만약 env 와 같은 변수가 아래처럼 정의될 경우에는 지역 변수가 최종 적용됩니다.
#@loginId = testId3
지역 변수는 특정 http 파일 내에만 적용되는 변수를 의미합니다.
@변수명 = 값 형식으로 선언할 수 있고, env 변수로 선언한 값과 동일한 변수가 있다면, 지역 변수로 덮어씁니다.
한 가지 유의할 점은 지역 변수끼리는 override 가 되지 않아서, 동일한 변수를 같은 이름으로 같은 파일 내에서 사용할 수가 없더라고요. 이게 좀 불편했어요. http yac 에서는 override가 되서 동일한 변수명을 다른 API 에서도 사용할 수 있었는데, 여기서는 안되서 무조건 다른 변수명으로 바꿔줘야 했어요.
@loginId = testId3
@loginPassword = testPassword3
### 로그인
POST {{host}}/login
Content-Type: {{requestContentTypeJson}}
{
"id": "{{loginId}}",
"password": "{{loginPassword}}"
}
# 다른 변수명 사용
[X] @loginId = testId4
[O] @loginId1 = testId4
### 어떤 다른 API
POST {{host}}/login/test
Content-Type: {{requestContentTypeJson}}
{
"id": "{{loginId}}",
"password": "{{loginPassword}}"
}
어떻게 보면 env 변수도 글로벌 변수라고 볼 수 있을 것 같은데, 여기서 말하는건 env 변수 는 아니고요. 전체 http 파일에서 적용되는 글로벌 변수를 선언하고 사용할 수 있어요.
http 파일 내에서 > {% javascript 코드 %} 형식으로 자바스크립트 코드를 사용할 수 있는데요. 요청 후의 response 를 읽어서 그 값을 활용한 후 처리를 할 수 있습니다.
일반적으로 로그인 인증을 위한 토큰을 사용하고 싶을 때 글로벌 변수를 활용할 수 있는데요. 다른 API 를 호출하기 전에 로그인 API 를 먼저 실행시키고, 리턴 받은 토큰을 글로벌 변수에 저장합니다.
### 로그인 - 2차인증
# @name login_2fa
POST {{host}}/login/2fa
Content-Type: {{requestContentTypeJson}}
{
"id": "{{loginId}}",
...
}
> {%
if (response.body && response.body.accessToken) {
client.global.set("accessToken", response.body.accessToken)
} else {
client.global.set("accessToken", "")
}
%}
그리고 나서 다른 API 에서 아래처럼 다른 변수들처럼 불러와 사용할 수 있어요. 참고로 다른 파일에서도 아래처럼 변수를 불러와 사용할 수 있는데요, 인텔리제이가 현재 파일 내에 변수를 선언하지 않았다고 밑줄을 그어버립니다.
### 조회 API
@pk_no=1
GET {{host}}/asset/{{pk_no}}
Authorization: bearer {{accessToken}}
그래서 전 밑줄이 보기 싫어서 env 변수에 동일한 글로벌 변수를 디폴트로 선언해놔서 밑줄을 제거 했어요. 이런 방법도 있다는거 참고해보세요!
{
"dev": {
...,
"accessToken": "디폴트세팅용"
}
}
아마 대부분의 API 호출에는 인증 로직이 들어갈텐데요, 호출 전에 로그인 로직을 한 번은 실행해야 토큰이 글로벌 변수에 저장되기 때문에 매번 이 과정을 거쳐줘야 합니다. 토큰 유효시간 내에는 유효하긴 하지만, 그 사이에 로직이 변할 수도 있고, 등등의 사유로 매번 로그인을 새로 해주는게 좋긴 한데요.
http yac 에서는 @forceref 기능으로 매 request 마다 강제로 실행할 로직을 선언할 수 있는 걸 제공해서 편했는데, 인텔리제이는 코드상의 기능은 제공하지 않더라고요.
# http yac
# @forceRef login
# @forceRef login_2fa
@pk_no=1
GET {{host}}/asset/{{pk_no}}
Authorization: bearer {{accessToken}}
다행히 방법은 있었어요.
Run/Debug Configuration 을 활용하는 방법인데요. 일단 login 에 필요한 1차 인증, 2차 인증 request 를 login.http 라는 파일에 모읍니다.
그 후 전체 실행을 통해 로그인 로직을 한 번 실행합니다. 그러면 인텔리제이 맨 오른쪽 최상단에 login.http 의 모든 것을 실행했다는 All in login 이 노출됩니다.

그 이후 edit > Edit configuration templates 로 진입합니다.


여기서는 HTTP Request 에 공통으로 적용시켜줄 템플릿을 정할 수 있는데요. Run Another Configuration 을 각 요청 실행(launch) 전에 실행할 수 있도록 설정하려고 합니다.

버튼을 누르고 나면, 실행할 수 있는 항목 리스트가 노출되는데요, 우린 방금 로그인 로직을 실행했어서 해당 configuration 이 노출되고 있습니다.

All in login 을 클릭하면 설정이 완료되고요.

그리고 나서 다른 request 를 실행하면 로그인 로직이 실행된 후 요청한 request 가 실행되는 걸 볼 수 있습니다.
전체 적용이 싫다면, 개별적으로 Before launch 부분에 원하는 사전 설정을 넣어주면 됩니다.
아래처럼 # @name login 코드를 작성하면, login 이라는 이름으로 request 가 지정됩니다. 지정하지 않으면 로그인 으로 지정됩니다.
### 로그인
# @name login
요런식으로 결과를 노출할 때 파일명 | name으로 노출해 줄 때 사용됩니다. configuration 에서 리스트 출력할 때도 사용되고요.

http client 기준으로 얘기해볼게요.
...
POST {{host}}/login/2fa
Content-Type: {{requestContentTypeJson}}
{
"id": "{{loginId}}",
...
}
//abcdef
# yac
request_rejectUnauthorized=false
# http client
{
"dev": {
"request_rejectUnauthorized": false
}
}
{{host}} 를 지정해줘야함# yac - host 명시 안해도 env 에서 읽어서 앞에 넣어줌
POST /login/2fa
# http client
POST {{host}}/login/2fa
# yac -- js 없이 아래와 같이 선언
{{
$global.loginId = 'testId1'
$global.loginPassword = 'testPassword1'
}}
# http client - js로 선언
> {% client.global.set("accessToken", response.body.accessToken) %}
# yac - 사전 request 지정해서 호출 가능
# @forceRef login
# @forceRef login_2fa
POST {{host}}/login/2fa
# http client
Run/Debug Configuration 으로 설정
그 외 생략
인텔리제이 ultimate 을 사용한다면 postman 대용으로 사용하기 좋습니다. js 코드를 통해 assert 등의 키워드로 테스트도 일부 가능하다고 하나, http client 를 이용하기보다는 테스트 코드를 따로 작성하는게 케이스 관리나 더 다양한 테스트가 용이해 보입니다.