이번 포스팅에서는 뉴스 api를 가져와 파싱한 후, Amazon Translate를 사용해 번역한 뒤, DynamoDB에 저장하는 Lambda 함수를 생성하고 EventBridge와 연결하는 과정까지 진행해보았다.
즉, 뉴스 데이터를 저장하는 파이프라인까지 구축해보았다.
먼저 API는 News API를 활용했다. 매일 100개의 뉴스를 가져올 수 있는데, Translate나 DynamoDB의 프리티어 한도를 고려해서 일단은 40개씩 가져오는 것으로 설계했다.
로컬 vscode에서 정상적으로 작동하는 것을 확인한 후, AWS콘솔에서 테스트를 진행 해보았다. 먼저 테스트 진행을 위해 아래와 같이 함수를 생성했다.
함수 이름은 NewsCollector로 하였고 기본적인 Lambda권한을 가진 새 역할을 생성해주고 함수를 생성하였다. 파이썬 버전은 3.13으로 설정해주었다.

콘솔에 기존에 작성한 코드를 업로드하고 테스트를 했는데 오류가 발생했다.
"Unable to import module 'lambda_function' : No module named 'lambda_function' "
-> 코드의 시작 지점에서 lambda_function이라는 파일이나 모듈을 발견하지 못했다는 의미
이 오류의 대부분의 경우는
- 파일명이 lambda_function이 아님
- 파일 내부의 함수명이 lambda_handler가 아님
위의 원인으로 콘솔에서 인식을 하지 못해 발생하는 오류라고 한다. 근데 확인 결과 이 부분엔 문제가 없었다.
뭐가 문제일지 계속 생각을 해보았는데, 전에 GithubAction을 구현하다가 deploy.yml파일이 루트경로에 있지 않아 파일이 인식되지 않았던 문제가 생각나 lambda_function파일의 경로를 확인해보았다.
기존 프로젝트 구조
올바른 구조
경로문제가 맞았다. 좌측의 사진을 보면 루트 파일이 news-lambda디렉토리이고 lambda_function파일이 디렉토리 내부에 있음을 알 수 있다. 경로를 수정해 zip파일을 Lambda에 재업로드하여 이 문제는 해결하였다.
경로를 올바르게 수정한 뒤 다시 테스트를 진행했는데 또 오류가 발생하였다.
" Unable to import module 'lambda_function : No module named 'lxml.etree' "
-> 이 오류는 Lambda 함수에서 lxml 모듈을 사용하려고 했지만, 해당 라이브러리가 포함되어 있지 않아 발생한 문제다.
뉴스의 본문 추출을 위해 사용한 lxml모듈과 trafilatura라이브러리의 의존성 파일을 zip파일에 포함하여 사용하였는데, 이상하게 Lambda에서 인식을 하지 못하고 있는것이다. lxml모듈 사용은 처음이라 원인을 짐작하기 어려워 이 부분은 생성형AI의 도움을 받아 해결하였다.
AWS Lambda의 실행환경
먼저 오류의 원인을 파악하기 전에 Lambda의 기본적인 구성에 대해 짚고 넘어가자. Lambda는 Amazon Linux기반 실행환경에서 코드(여기선 Python)를 실행하며, 기본적인 표준 라이브러리만 제공한다.
내가 사용하려는 trafilatura라이브러리는 C확장자에 의존하는 라이브러리로써, Lambda에서 제공하는 Python표준 라이브러리에 해당하지 않는 것이었다.
근데 왜 관련 의존성 파일들을 zip파일에 압축하여 함수를 생성하였는데도 오류가 날까❓
현재 내가 쓰고 있는 운영체제는 Window이고, Lambda는 Amazon Linux기반으로 작동한다.
때문에 내가 압축한 의존성 파일들은 Window운영체제에 맞게 컴파일되어 패키징된 것이기 때문에 컴파일 방식이 다른 Lambda에서는 인식을 하지 못하고 오류가 발생했던 것이다.
그래서 이 문제는 Lambda함수 최상단에 직접 trafilatura라이브러리 설치하는 코드를 추가하여 해결하였다. 아래는 Claude의 도움을 받아 추가한 코드이다.
def install_trafilatura():
if not os.path.exists("/tmp/trafilatura"):
install_cmd = [sys.executable, "-m", "pip", "install", "trafilatura", "-t", "/tmp/"]
subprocess.check_call(install_cmd)
# /tmp 경로를 Python 경로에 추가
sys.path.insert(0, '/tmp/')
print("trafilatura 설치 완료")

상태코드 200이 반환되었지만 오류가 발생했다. 크게 두 가지 문제가 발생했는데
" User is not authorized to perform: translate:TranslateText because no identity-based policy allows the translate:TranslateText action "
-> Lambda에서 Amazon Translate에 TranslateText 액션을 수행하려고 하는데, 수행할 권한이 없어 발생한 문제
" User is not authorized to perform: dynamodb:PutItem on resource: arn:aws:dynamodb:ap-northeast-2:481665130730:table/NewsArticles "
-> Lambada가 DynamoDB의 NewsArticles테이블에 접근하여 PutItem 액션을 수행할 권한이 없어서 발생한 문제
위 문제는 Lambad 함수를 생성할 때 기본 Lambada권한을 가진 역할만 생성하고, 해당 역할에 함께 연동할 AWS서비스인 Translate나 DynamoDB에 접근할 수 있는 정책을 부여하지 않아 발생한 문제다. NewsCollector-role-wasjdujy역할에 아래와 같이 인라인 정책을 새로 생성하고, 추후 연결할 EnventBridge까지 정책에 추가하여 해결했다.
참고로 인라인 정책은 사용자 지정 정책과 다르게 해당 정책과 연결된 리소스가 삭제되면 같이 삭제되는 정책이다.
위에서 부터 순서대로
- "dynamodb:PutItem"
- Dynamodb 테이블에 새 아이템(한 행)을 삽입할 수 있는 권한
- "dynamodb:GetItem"
- Dynamodb 테이블의 단일 아이템(한 행)을 기본 키로 조회할 수 있는 권한
- "dynamodb:Query"
- 파티션 키나 정렬키 기준으로 여러 아이템을 조건 검색할 수 있는 권한
- "dyanmodb:Scan"
- 먼저 테이블을 전체적으로 훑고 필터를 사용해 특정 데이터를 탐색할 수 있는 권한
- "translate:TranslateText"
- 텍스트 번역 요청을 보낼 수 있는 권한
- "events:PutRule"
- EnventBridge에 새 스케줄을 생성할 수 있는 권한
- "events:PutTargets"
- 특정 스케줄에 대해 실행 대상(Lambda나 SNS 등)을 연결하는 권한
- "events:DescribeRule"
- 특정 스케줄의 상세 정보를 조회할 수 있는 권한
- "events:ListRules"
- 모든 스케줄을 조회할 수 있는 권한
위의 과정을 해결하고 나니, 드디어 테스트에 성공했다. 성공했으니 DynamoDB에 데이터가 저장돼있어야 한다.
시간 초과로 데이터가 일부 누락됐지만 데이터를 가져와서 저장하는데 성공
위의 모든 과정을 EventBridge를 통해 24시간마다 실행될 수 있도록 스케줄링 했다.
뉴스 데이터를 수집하는 Lambda함수를 완성했으니, 이후엔 Amazon API Gateway를 통해 API요청을 처리하는 Lambda함수를 생성할 예정이다.
또한 Translate와 DynamoDB의 프리티어 한도를 고려하여 매일 수집하는 기사의 양과 TTL값을 조절하고, 최종적으로 완성된 API를 vue를 사용해서 완성한 뒤, s3에 배포 할 예정이다. 예상보다 빨리 완성이 된다면 일부 리소스에 대해 Terraform 까지 간단하게 실습을 진행해보겠다.