이번에 진행하는 프로젝트에서 크롤링 API가 필요했는데, 백엔드 서버에서 처리하다 보니까 상대적으로 오래 걸리는 크롤링 API 때문에 다른 서비스에도 영향을 미치는 것을 확인했습니다. 이때 눈에 들어온 것이 Serverless 였습니다.
크롤링은 특히 따로 DB와 연결하지 않아도 되므로 서버리스로 구성하면 로직에 대해서만 고민 할 수 있어 빠르게 API를 구성하는데 적합해 보였고, 이를 통해 메인 서버의 부하를 줄일 수 있을 것이라 기대했습니다.
tool: aws lambda, API Gateway, layers
런타임: Node.js
aws lambda를 구성하는 과정과 그 과정에서 접한 에러를 해결하는 것을 정리하였습니다.
먼저 CLI를 통해 serverless 서비스를 이용하는 방식도 있지만, 따로 aws config 설정과 yml파일 설정하는 과정이 있어서 간단하게 aws 페이지를 통해 lambda를 구성했습니다. (시간이 된다면 serverless 서비스를 이용해보세요)
먼저 aws에 접속하여 lambda 서비스 화면으로 갑니다.
함수 생성을 통해 Lambda를 생성 할 수 있습니다.
저는 새로작성을 통해 아예 함수를 새로 작성하였습니다.
함수 이름을 crawlingData로 정의하고 Node.js를 사용하기 위해 런타임을 지정하였고,
권한은 기존의 권한을 사용할 것이 없기 때문에 기본제공하는 권한을 사용했습니다.
고급 설정에서는 따로 서명이나, vpc 설정을 하지 않아서 건너띄웠습니다.
함수를 생성하면 나오는 처음 화면입니다.
현재 코드는 함수를 호출하면 status:200과 "hello form Lambda" 메세지를 반환하는 함수가 작성되어 있습니다. 테스트를 통해 코드 결과를 확인 할 수도 있습니다.
함수는 작성되었지만 이 함수를 호출하기 위한 EntPoint가 필요했습니다.
여기서 API Gateway를 이용하여 이 함수가 필요한 URL을 할당하였습니다.
여기서 바로 "트리거추가" 버튼을 통해 API Gateway를 추가 할 수 있지만, 그러면 GET, POST, DELETE 등 모든 method에 대해 호출되는 문제가 있었습니다. 이 문제를 해결하기 위해 API Gateway 서비스에서 직접 생성하여 크롤링에 맞지 않는 POST, DELETE, PATCH는 보낼 수 없도록 설정하였습니다.
API Gateway에서 HTTP API 생성을 선택하면 나오는 화면입니다.
우리가 생성한 Lambda 함수를 통합 추가를 통해 등록합니다.
여기서 method를 GET으로만 받겠다고 지정하여, 크롤링 목적과 다른 method를 거절하도록 설정합니다.
stage 설정을 넘기고 API Gateway를 생성하면 다음과 같이 Endpoint가 할당된 것을 확인 할 수 있습니다.
정상적으로 Lambda 함수가 실행 됨.
셋팅이 끝난 후 크롤링을 위한 코드를 작성하고 배포하였습니다.
코드를 작성한 다음 테스트를 했더니 에러가 발생했습니다.
axios 모듈을 찾을 수 없다고 합니다.
우리가 Node.js에서 axios를 사용하려면 npm install을 하듯이 Lambda에서도 따로 module을 추가해야 작동하는 것이었습니다.
코드소스에 바로 node_module 폴더를 추가하는 방법도 있지만, 나온지 꽤 된 Layer 기능을 이용하면 다른 Lambda에서도 재사용 할 수 있기 때문에 Layer를 사용하기로 했습니다.
위처럼 nodejs 라는 파일을 zip 형태로 저장해서 layer에 저장해야 합니다.
nodejs
├── node_modules
│ ├── axios
│ └── ...
├── package-lock.json
└── package.json
python, node에서 모듈을 저장하는 방식은 aws 공식 홈페이지에 공개되어 있습니다. 그 중, Node.js는 위의 형식을 맞춰 파일명을 nodejs로 해야 정상적으로 작동합니다.
계층 생성을 통해 아까 생성한 nodejs.zip 파일을 등록하면 됩니다.
그러면 해당 layer에 대한 고유 ARN번호가 있고, 이것을 layer에 추가하면 됩니다.
모든 준비가 끝났습니다. 다시 함수를 호출하겠습니다.
테스트는 정상적으로 작동하는데 curl을 통해 호출하면 에러가 납니다. 여기서 애를 좀 먹었는데 aws에서 CloudWatch를 통해 log를 확인하여 해결 할 수 있었습니다.
"Task time out 3.00 seconds." 즉, 3초가 넘어가서 오류가 발생했고, 함수 제한시간이 3초라는 것 이었습니다. 크롤링이 꽤 오래 걸리는 작업이어서 3초가 넘어갔는데 이를 넉넉하게 10초정도로 주기 위해 설정을 바꿨습니다.
구성 - 일반구성에서 설정을 바꾸고 다시한번 호출했습니다.
오류가 나지 않는 것을 확인할 수 있습니다.
마지막으로 parameter를 queryString으로 받고, 크롤링 결과를 바로 result에 담아서 반환하도록 수정 한다음 호출하면 다음과 같은 결과를 얻을 수 있습니다.
위의 과정으로 Lambda를 통해 크롤링을 위한 serverless 함수를 구성하였고, API Gateway로 해당 함수를 호출하는 Endpoint를 지정하여, 별도의 서버 구성 없이 쉽게 API를 만들었습니다.
단순한 문자를 받기 위해 위와 같이 queryString을 이용했지만, momentjs나 parsing을 이용하면 최적화 할 수 있을 것 같습니다.
+ 추가 할 내용이나 부족한 부분이 있다면, 댓글 작성 부탁드립니다! :)