얼굴 한 번 뵌 적 없지만 본 내용은 JS 내용을 많이 다루신 ZeroCho님의 책인 Node.js 교과서의 내용을 일부 참고해 작성했으며, 책의 일부 내용이 업데이트가 안된 부분이 있어 오류나는 부분들을 제가 개인적으로 해결한 내용을 담은 방법으로 개정해 작성되었습니다.
나는 평상시에 당근 마켓 기술 블로그를 참고해서 개발과 관련한 내용들을 많이 배워보는 편이고, 당근마켓 Medium 블로그를 가면, Lambda Edge와 S3를 활용한 블로그 글이 있다.
대부분의 많은 서비스들은 방대한 양의 데이터 (특히, 이미지)를 다루는 것에 대해 비용이나 용량에 대한 문제를 많이 직면하는 것 같고, 그에 대한 여러가지 해결책을 제시한다.
아직도 어설픈 개발자지만, 책과 영상을 보면서 다양한 시도를 해보고 있고, 최근에는 ZeroCho님의 Node.js 교과서를 보면서 해시태그나 실시간 채팅, 구글 지도의 다채로운 활용법 등을 꽤 많이 참고해본 것 같다.
본론으로 넘어와서, 배운 내용을 풀어보자면 크게 3가지로 나눠진다.
- AWS S3
- AWS Lambda
- 내 코드
1,2 번 내용의 경우 코드를 직접 입력하는 것보다 AWS GUI에서 세팅하는 내용들이 훨씬 많은데, 내가 직접 입력한 코드를 다루는 상황이 아니다 보니, 얘기치 못한 에러들이 좀 많이 발생했다.
그 “얘기치 못한 에러” 때문에 4일이라는 시간이 걸렸고, 대부분의 에러는 AWS Lambda에서 발생했다. (내가 Lambda를 그 만큼 모르고 있다는 것도 팩트)
좀 웃긴 말이긴 하지만, 코드를 작성하다보면 내가 짠 코드에 버그가 없다는 걸 10000% 확신하는 순간이 종종 있다. 항상 그 순간을 느끼면 보통 클라우드나 코드 외적인 환경 설정에서 에러를 발견하는 내 모습을 본다.
오늘 글을 남기는 목적은 이 글을 읽으시는 분들이 나와 같이 시간 낭비를 하지는 않았으면 하는 마음에… 조금이라도 참고하십사 하고 시도했던 내용들을 로그처럼 남겨보고자 한다. (다 만들어 놓고, 회고해보니 1시간 이내로 Image Resizing 로직을 만들 수 있을 것 같다…)
어찌보면 당연한 말이긴 하겠지만, 운용하는 서버 내부에 Image 등 높은 용량의 데이터를 저장하는 공간을 만들지 않고, 클라우드나 사설 서버 등에 해당 데이터들”만” 전문적으로 다루는 공간을 만든다.
그리고 S3같이 파일 객체를 다루는 공간에도 업로드 횟수, 조회 수에 따라 요금을 부과하기 때문에 용량을 줄이려는 시도는 곧 비용을 감소시키려는 시도와 동일시 된다.
1. AWS S3에 접속한다.
접속해서 우선 Bucket을 만들어보자.
버킷 생성하기 완료!
버킷을 만들고 나면 Permission에서 버킷 정책을 생성해준다.
하단에 정책 생성기가 있다.
여기서 주목할 부분은 Actions라는 부분이다. 가져와야할 값은 2개인데,
- getObject
- putObject
이 2개를 클릭한다. 각각 의미하는 바는 S3에서 데이터를 가져오고 수정할 수 있는 권한을 제공하겠다는 뜻이다.
2. 우선 S3 업로드가 내 코드에서 잘 작동하는지 확인하기
AWS key는 dotenv로 관리할 수 있게 .env 파일에 모아서 사용했다.
3. Lambda 사용하기
진짜 엄청 쉬운데 사용법을 모르면 나처럼 4일 동안 삽질한다. 별의 별 시도를 다해본 것 같은데, 그래도 제일 효과 있던 건 S3-내 코드-Lambda를 다시 처음부터 만들어본… 것..?
추후에 이 폴더를 압축해서 Lambda에 업로드 할텐데 반드시 해당 폴더 디렉토리 내부로 들어가서 압축해줘야한다 (경로 문제 발생한다)
위의 이미지를 보면 gm을 설치하게 되었는데 (Node.js 교과서에도 명시되었으나 해당 모듈로는 도저히 실행이 안된다… 결국 sharp로 모듈 대체했다)
업로드할 코드 (index.js에 입력될 코드)는 아래의 이미지와 같다.
코드 입력이 다 되었으면 압축해서 업로드 한다.
놓치기 쉬워서 에러가 자주 발생하기 때문에 명심할 것은 Lambda에서 이렇게 코드 업로드하고 나면 기본설정이라는 란에 Handler라는 내용이다.
여기는 우리가 업로드한 <파일명>.<exports.함수명> 이렇게 작성해줘야한다. index.js라는 파일 내에 handler라는 함수명을 나는 사용했으니, 아래와 같이 표기했다.
여기 세팅이 끝나면, S3를 Lambda에 Trigger로 연동한다 (S3에 파일 업로드 발생할 시, 자동 Lambda 실행)
S3를 Lambda와 연결했다.
Lambda 세팅이 끝나면 반드시 Test Event를 사용해봐야 하는데, 안그러면 내 프로젝트 코드와 Lambda 에러가 같은 에러 코드를 반환한다.
테스트 코드 실행을 안해보면 Cloud Watch에서 반환하는 에러값을 아무리 봐도 이해 못한다. test 코드 보는 게 훨씬 낫다.
여기가 내가 결정적으로 이해 못한 부분인데, Lambda 압축 파일을 올려도 각 변수나 객체가 무엇을 의미하는지 모르면 말짱 도루묵이다.
그래서 테스트 코드 이벤트 설정할 땐 반드시 S3와 내 코드에서 Lambda와 어떻게 연결되는지를 잘 알아야 하고, 제대로 이해하고 테스트를 진행하면 아래와 같이 성공한 결과를 반환한다. 아래 코드가 나오면 프로젝트 코드에도 이상없이 잘 작동하는 것을 볼 수 있다.
성공 화면
에러 화면
Lambda로 이미지 크기가 변환 될 때마다 새로운 폴더인 thumb에 저장이 된다.
이렇게 변환하면 이미지 카테고리별로 폴더에 모아 관리하는 것이 매우 수월해진다.
프로젝트 코드 전체를 보여주기는 어렵지만, Lambda는 쉽게 말해
S3에 이미지 업로드 → 이벤트 발생으로 간주 → Lambda 실행 (이미지 변환 후 S3에 업로드 — Put 메소드) → 사용자는 변환된 이미지를 서비스에서 보게 된다.
찾아보니 이미지 크기를 줄이는 행위는 생각보다 컴퓨팅 자원을 많이 잡아먹는 행위라고 한다. 프로젝트가 진행되는 서버에서 자체적으로 이미지 크기를 줄이려고 하면 많은 양의 CPU를 잡아먹게 되어 버린다.
때문에 Lambda와 같은 서비스로 (이걸 서버리스 — Serverless — 라고 부른다) 서버 없이 이미지 변환이 필요한 순간에만 기능을 사용하게끔 해놓으면 자원을 많이 아낄 수 있다.
Lambda의 IAM 설정에서 몇 번이나 설정을 변경하고 삭제했는지 모르겠다. 4일 동안 별거 아닌 것에 힘쓴 느낌이지만, 이렇게 기록해놓으면 Lambda를 또 응용해서 다양한 프로젝트에 활용할 수 있다.
나도 내가 쓴 블로그를 보면서 프로젝트 진행할 때가 있다. 개발자에게 기록하는 습관은 단순한 일기가 아니라 미래에 있을 수 있는 프로젝트를 대비하는 행위로도 사용된다.
모쪼록 많이 부족한 글이지만, 많은 사람들에게 필요한 문서가 되면 좋겠다
언제든 Q&A를 남겨서 개발에 대한 다양한 얘기를 공유하면 좋겠다.
Ryan Kim
참고 도서
조현영 : Node.js 교과서