클라우드 시장이 점점 발전하면서 이젠 많은 것들을 클라우드 상에서 간편하게 처리 할 수 있게 되었다. 예전처럼 자기가 스스로 서버를 구축하고 설정하고 관리를 해야하는 수고로움이 많이 없어졌다.

서버의 구축과 관리가 간편해졌다고는 하지만, 여러가지 서비스를 구축하다 보면 굳이 24시간 내내 서버를 돌리고 있을 필요가 없는 경우가 있다. 일반적인 업무 자동화 같은 경우 하루에 한번 특정시간에 실행하기만 하면 되는 케이스도 많을 것이다.

이번 포스팅에서는 그런 고민을 해결해 줄 수 있는 서버리스 컴퓨팅 서비스인 Google Cloud Functions의 사용법을 간단하게 알아본다.


#서버리스 컴퓨팅의 이점

클라우드 서비스가 다양하게 활성하기 되기 전엔 웹사이트든 앱이든 어떠한 서비스를 운영하기 위해서는 개발자가 서버를 구축하고 API, DB등을 서버상에 직접 설치하고 운영해야 했다. 하지만 요즘엔 PaaS, DBaaS 등의 서비스가 활성화 되면서 필요한 것들을 필요한 만큼만 간단하게 사용할 수 있게 되었다. 서버관리는 클라우드 서비스 플렛폼 측에서 알아서 해주니, 개발자는 조금 더 개발에만 집중 할 수 있는 환경이 조성된 것이다.

서버리스 컴퓨팅은 개발자가 서버를 구축 할 필요없이 API 서비스를 개발 할 수 있게 해준다. 해당 API 서비스에 필요한 코드들만 미리 설정해두면, 나머지는 API End Point에 Request를 보내는 것 만으로 서비스를 실행할 수 있게 된다. 물론 다른 클라우드 서비스들과 연계하여 사용하는 것도 가능하다.

어마어마한 컴퓨팅 파워가 필요한 경우, 아주 사소한 부분까지 컨트롤 해야하는 경우등, 직접 서버를 구축하고 관리해야 하는 경우도 아직까진 많다.

나는 GCP를 사용하고 있어서 Google Clound Functions를 이용했지만, AWS에도 Lamda라는 비슷한 기능이 있다.


#함수 만들기

GCP에 로그인 한 다음, Google Cloud Functions를 선택한다. 한번도 사용해보지 않은 경우에는 API를 활성하라고 나오니 API를 활성화 해 준다.

활성화 했으면 "함수 만들기"를 클릭하여 새로운 함수 작성 화면으로 넘어간다.

이번 포스팅에서는 HTTP 엔드포인트로 실행되는 함수를 작성한다. 우선 함수 이름과 리전을 설정해 준다. 함수 이름이 엔드포인트 이름이 된다. 인증에 대한 설정은 우선은 "인증 필요"로 설정한다.

"변수, 네트워킹, 고급 설정"은 크게 따로 설정해야 할 건 없다. 만약에 실행하려는 함수가 무거운 경우 할당 메모리를 늘려주는 것이 좋고, 함수가 연산을 많이 하는 등 실행이 끝날 때까지 시간이 걸리는 경우는 제한 시간을 늘려주는 것이 좋다. 참고로 제한 시간의 상한선은 540초 (9분) 이기 때문에, 함수가 9분 이상 실행되는 경우는 함수를 분할하여 연계해서 사용해야 한다.

사용할 수 있는 언어는 Python, NodeJS, Java, Go 이다. 왠만한 서비스는 다 구축 할 수 있다. 런타임에서 원하는 걸 골라주면 된다. 이번 포스팅에선 Python을 사용한다.

진입점에는 HTTP 엔드포인트로 Request가 왔을 때 실행 할 함수 이름을 지정해주면 된다.

라이브러리를 사용하고 싶은 경우는 requirements.txt에 한줄씩 라이브러리 이름을 적어주면 된다.

google-cloud-storage
pandas>=1.0
numpy==1.0

이런 식이다. 특정 버전의 라이브러리를 사용하고 싶은 경우는 ==, 특정 버전 이상의 라이브러리를 사용하고 싶은 경우는 >=를 이용해서 지정할 수 있다. 이미 처음부터 설치되어 있어서 따로 설치 할 필요가 없는 라이브러리의 리스트는 공식 페이지에 기제되어 있다.

모든 설정이 끝났으면 "배포"를 눌러준다. 코드와 라이브러리의 양에 따라서 준비되는 시간이 달라질 수 있다.

가장 왼쪽에 초록색 체크마크가 나오면 성공적으로 배포가 된 것이다.


#인증 설정

API에는 누구나 실행해도 되는 것과 특정한 사람들만 실행 할 수 있는 것이 있을 것이다. 후자의 경우는 API Request에 제대로 된 인증 토큰이 Request에 포함되었을 때만 실행이 된다. 앞선 과정의 "인증" 설정을 "인증 필요"로 했기 때문에, 해당 함수를 실행하기 위해서는 Request에 Token을 붙여야 한다. 이제 토큰을 발행하는 방법을 알아본다.

서비스 계정 만들기

우선 GCP 메뉴 -> "IAM 및 관리자" -> "서비스 계정" 을 클릭한다. 그리고 "서비스 계정 만들기"를 클릭.

서비스 계정 이름을 넣어주고 "만들기" 클릭.

두번째 설정인 프로젝트에 대한 액세스 권한 부여 설정에서는 "역할 추가"로 역할을 추가해주고 역할은 "Cloud Functions 호출자"를 선택해 준다.

세번째 설정은 따로 하지 않고 완료를 눌러주면 서비스 계정이 완성된다.

토큰 생성

처음 서비스 계정을 만들면 "키 없음" 이라고 나온다. 오른쪽의 옵션을 눌러서 "키 만들기"로 키를 생성 해 준다. 그러면 키 유형을 고르라고 나오는데 그냥 기본 값인 JSON으로 만들면 된다. "만들기"를 누르면 키 정보가 포함되어 있는 JSON 파일이 자동으로 다운로드 된다.

이제 Cloud Shell을 실행해주자. GCP상에서 사용할 수 있는 터미널 기능이다.


실행이 되었다면 "파일 업로드"로 이전 과정에서 생성한 키 정보가 들어있는 JSON 파일을 업로드 해 준다.

업로드가 다 됐다면 다음 커맨드를 실행하여 서비스 계정을 활성화 한다.

gcloud auth activate-service-account --key-file=키파일이름.json

커맨드 실행 후 "Activated service account credentials for: [xxxx@xxxx]" 같은 식으로 메세지가 뜨면 활성화가 제대로 된 것이다.

그럼 이제 다음 커맨드를 실행하여 토큰을 발행 해 준다.

gcloud auth print-identity-token

뭐 승인하라고 나오는데 승인 클릭해주면 토큰 값이 나온다. 이제 이 토큰 값을 HTTP Request Header의 Authorization에 포함해서 Request를 보내면 이전 과정에서 만든 함수가 실행된다. 헤더에 포함 할 땐 값을 'Bearer 토큰값'으로 설정해주어야 한다.

기본적으로 구글의 인증은 OAuth를 이용하고, 생성된 토큰 (Access Token)의 유효시간은 한시간이다.

매번 이런식으로 토큰을 발행하는 건 매우 비효율적이다. 실제로 사용할 때는 Request를 보내기 전에 토큰을 생성하는 코드를 실행하고, 생성 된 토큰 값을 더하여 Request를 보내는 식으로 코드를 구성해야 한다. Java나 Python은 구글에서 제공하는 라이브러리를 이용하면 쉽게 토큰을 생성 할 수 있고, HTTP/REST의 경우는 JWT를 이용하여 토큰을 생성 할 수 있다. 자세한 정보는 공식 페이지를 참조하자.

JWT 생성에 필요한 정보

Java나 Python은 공식 라이브러리를 사용하면 되고 공식 페이지에 방법이 잘 기술 되어 있기 때문에 여기선 설명을 생략. JWT는 설정이 필요하기 때문에 설정 방법만 간략하게 설명하려고 한다.

JWT Header는 {"alg":"RS256","typ":"JWT"}
Google OAuth2.0은 RS256으로 사인 된 것만 인정한다.

JWT Claim Set 정보로는 iss, scope, aud, exp, iat가 필요.
iss => 서비스 계정 이메일 주소
scope => 실행하려 하는 Cloud Functions HTTP End Point 주소
aud => https://oauth2.googleapis.com/token
iat => JWT 생성시간. 유닉스 타임스템프로 지정
exp => 토큰 유효기간. iat부터 최대 한시간 후의 시간까지 지정가능

JWT Signature를 생성하는데 필요한 키 정보는 서비스 계정의 키 정보가 들어있는 JSON 파일 안에 "private_key" 값을 사용하면 된다.

마지막으로 payload 생성시 grant_type은 urn:ietf:params:oauth:grant-type:jwt-bearer로 지정해준다.


인증 없이 실행하기

인증 설정을 변경하고 싶은 함수를 선택한 후, 오른쪽 위에 "정보 패널 표시"를 클릭하고 "구성원 추가"를 클릭한다.

allUsers를 구성원으로 추가하고 역할은 "Cloud Functions 호출자"로 지정한 후 저장한다.

이것으로 인증없이 HTTP Request를 보내서 실행 할 수 있다.


잘만 활용하면 간단한 웹사이트/앱/서비스는 이제 서버 없이 구축 할 수 있을 거 같다. Pub/Subs와 같은 기능과 연계하면 실행 스케쥴에 맞춰 자동으로 실행 시킬 수도 있다. 여러모로 활용 방안을 연구하여 이용해보자!