🧐인턴 생활 마지막 글🧐
정말 재미있게 일했고, 그만큼 아쉬움도 크지만 좋은 경험이 되었다고 생각한다
그리고 중요한 건 내가 스스로 생각해서 문제를 해결한 경험이 생겼다는 것 !
[문제 상황]
AWS의 SES로 메일을 보낼 때 유독 naver메일만 open 로그가 찍히지 않는 현상 발생
SES는 기본적으로 메일 열람 여부, 메일 내 링크 클릭 여부, 반송 여부 등을 추적하는 시스템이 내장되어 있다
(구성세트라고 하고, 더 자세한 내용은 https://velog.io/@joshua_1203/AWS-SES 이 포스팅을 참고하면 된다 !!)
그런데... 어째서인지 네이버 메일은 메일 열람 여부가 작동하지 않았다.
아무래도 네이버 클라이언트가 보안 상 1x1 픽셀 이미지를 tracker로 간주하고 차단하는 모양이었다.
이 문제를 어떻게 해결할 것인가에 대해 기획자분과 이야기를 나누었다.
[문제 해결 방법 모색]
1. AWS 담당자와 연락하기
2. AWS의 다른 서비스를 이용하여 직접 로그 추적 구축하기
3. 메일을 보낼 때 naver메일은 받지 않기
1번의 경우 가장 확실했지만 담당자가 누구인지, 또 AWS는 글로벌 서비스이기 때문에 과연 이 문제를 바로 해결할 수 있을 지에 대한 의문이 있었다. 이 해결 방법은 같은 사무실에 인프라 담당자 분이 계셔서 그 분께 맡겼다.
그렇다고 가만히 손을 놓을 수도 없는 일이었다. 메일을 보내는 수신자의 절반 이상이 네이버 메일을 사용하고 있었다. 메일링의 지표로 오픈율과 클릭률을 보려고 했는데 절반이상의 정보가 없다니, 앞 뒤가 맞지 않았다. 그래서 생각해낸게 2번이었다.
2번은 메일링 대시보드를 담당하고 있었고, 아이디어를 낸 내가 자연스럽게 맡게 되었다.
"이렇게 했는데도 안되면 어쩌지? AWS 담당자가 처리하면 쉽게 해결되는거 아닐까?"
새로운 분야를 공부하는 걸 좋아하는 편임에도 막상 업무가 되니 리스크와 마감이 따라오는 상황이라 더 불안했다.
하지만 손 놓고 가만히 있는 것도 직성에 맞지 않는지라, 한번 해보기로 했다
처음 한 일은, 물론 AWS와 친해지는 일이었다
opensearch와 SES를 사용한 경험이 있어서 콘솔에는 좀 익숙한 편이었다.
그러나 괜히 무서운(?) Lambda와 API Gateway를 처음부터 알아가야 한다고 생각하니 왠지 막막했다🤣
그래서 내 로직을 먼저 아키텍처로 정리해봤다
몇 개의 프로젝트를 진행하면서 왜 그렇게 아키텍처를 만들라고 하는 걸까 했는데 지금와서 보면 아키텍처만큼 직관적으로 잘 설명해주는 것도 없다👍
여기서 잠깐 ! 메일 열람 추적은 어떤 식으로 진행될까?
메일 열람은 1x1의 투명 이미지를 메일에 삽입한다.
수신자가 메일을 열게 되면 이 이미지를 로드하게 되는 데, 이 때 메일을 열었다고 간주하는 것이다.내가 구축한 2번 방법은 여기에서 차용한 것이다.
메일을 보낼 때 회사 로고를 html에 넣게 되는데, 이 로고를 외부 이미지로 심어놓고 이 로고를 요청할 때마다 로그를 찍는 방법이다.
아래에 가려둔 mail body의 로고 부분을 요청으로 받아올 것이다 !!
그렇다면 Lambda, API Gateway를 사용해서 이메일에 이미지를 표시할 수 있도록 설정한 과정을 정리해보자.
Lambda 함수는 이미지 URL을 반환하고,
CloudWatch 로그를 사용하여 요청 및 응답을 추적할 수 있도록 구성된다.
이 Lambda 함수는 API Gateway에서 호출된다.
먼저Lambda에 들어와서 함수를 만들어준다.
만든 함수에 접속하면 아래와 같이 나온다.
(지금은 API Gateway에 연결되어 있지만 원래는 아무것도 안나온다)
그리고 코드 부분에 작성해주면 된다.
🔗 Lambda 함수 코드
import logging
# 로깅 설정
logger = logging.getLogger()
logger.setLevel(logging.INFO)
def lambda_handler(event, context):
# 이미지 URL 설정 (예시)
image_url = "https://www.img/picture/common2/logo.png"
# 로그에 이미지 URL 기록
logger.info(f"Returning image URL: {image_url}")
# URL 반환
return {
"statusCode": 200,
"headers": {
"Content-Type": "text/plain",
"Cache-Control": "no-store, no-cache, must-revalidate, max-age=0"
},
"body": image_url # 이미지 URL 반환
}
이런식으로 원래 코드를 작성했던 것처럼 해주면 된다.
lambda에서는 배포(deploy)라고 표현하는데, 이게 코드 활성화라고 생각하면 된다.
성공하면 아래와 같이 성공적으로 업데이트 되었다고 나온다
lambda는 서버리스이기 때문에 바로 배포 상태를 확인할 수가 없는데, 그래서 아래 있는 test를 사용한다.
한번도 안했다면 test 환경을 만들라고 나온다. 그냥 이름 지어주고 만들면 된다.
만들고 나서 test를 클릭하면 내가 만든 환경이 나온다.
test하면 성공여부와 결과값을 확인할 수 있다.
보통 웹 페이지는 이미지를 계속 로드하지 않기 위해 이미지를 캐시하게 되는데,
로그 추적은 열 때마다 이미지가 로드되어야 하므로 캐시 데이터로 저장하지 않게 해야 한다.
이미지를 캐시하지 않고 매번 새로 요청하게 만들기 위해 Cache-Control
헤더를 설정하여 매번 이미지를 로드하도록 유도했다.
lambda는 필요할 때만 켜지는 인스턴스라고 생각하면 쉽다.
그렇기 때문에 내가 필요한 라이브러리를 폴더 내에 저장해두어야 한다.
AWS는 .ZIP 파일로 업로드할 수 있게 만들어 두었음 !!
나같은 경우는 URL만 반환하면 되기 때문에 따로 넣지는 않았다.
API Gateway에서 GET 메서드를 설정하여 Lambda 함수를 트리거한다.
API Gateway에 들어가면 이렇게 생겼다.
지금은 다 만들어놔서 뭔가 있지만 원래는 최상경로"/"만 있다.
API Gateway에서 리소스를 먼저 생성하고, 메서드를 생성하면 된다
메서드를 생성할 때 꼭 !! 꼭 프록시 통합을 활성화 해야 한다.
그렇지 않으면.... 큰일납니다.... 저도 알고싶지 않았어요
Lambda 프록시 통합을 사용하여 API Gateway가 Lambda 함수를 호출하고 반환된 URL을 그대로 반환할 수 있게 해야 한다!
위에서 람다 함수를 미리 정의해두었기 때문에, lambda를 선택하면 자동으로 보이게 된다.
GET 메서드를 생성하였다면 아래와같이 생성된다!
그 다음 API 배포 버튼을 눌러 스테이지에 올리면 된다.
스테이지도 별거 없이 그냥 새 스테이지를 만들면 된다.
나는 이미 mail 이라는 스테이지를 생성해놔서 그걸로 선택했다.
그렇게 스테이지로 가게 되면 내가 만들어 놓은 스테이지에 GET 메서드가 있는 걸 확인할 수 있다.
GET 메서드에 보면 URL 호출이 있는데, 이게 최종 HTML에 삽입 될 URL이다.
이 URL에 접속하면 lambda 함수와 연결되면서 로고 이미지가 뜨게 된다.
Lambda 함수에서 CloudWatch 로그를 사용하여 요청 및 응답을 기록할 수 있다. 이를 통해 이미지 URL 및 함수 호출을 추적할 수 있다.
logger.info()
를 사용하여 Lambda 함수 내에서 정보를 기록하고, 로그 그룹과 로그 스트림을 CloudWatch에서 확인할 수 있다.
Lambda 함수는 요청을 처리하고 이미지 URL을 반환한다. 이 URL을 사용하여 이메일 본문에 이미지를 삽입할 수 있다.
이메일 본문에 이미지를 삽입하려면, Lambda가 반환한 이미지 URL을 <img>
태그의 src로 사용하기 위해 endpoint url을 작성하면 된다.
<a href="https://www.example.com/" target="_blank">
<img src="https://XXXXXX.execute-api.ap-northeast-2.amazonaws.com/MY-ENDPOINT-URL/mail/mail-open" border="0" width="200" height="auto">
</a>
이제 수신자가 메일을 열람할 때마다 Lambda 함수가 실행되고, 로그가 CloudWatch에 기록된다. 이를 통해 요청된 URL, 반환된 이미지 URL, 오류 발생 여부 등을 추적할 수 있다.
cloudwatch의 로그 그룹에 가면 lambda 함수가 모여 있다.
나의 람다 함수로 들어가보자
이렇게 요청이 올 때마다 로그가 찍히게 된다.
로그에는 다양한 정보가 찍히게 된다. 이 중 하나를 대시보드에 올리면 된다.
cloudwatch의 대시보드에 접속해서 지표 중 API Gateway나 lambda에서 확인하면 된다.
결국 구축한 나의...... 대시보드 !!!!!!!!!!!!!
- Lambda 함수는 이미지 URL을 반환하고, CloudWatch 로그를 통해 이미지 URL을 추적.
- API Gateway에서 Lambda 프록시 통합을 활성화하여 Lambda 함수를 HTTP 엔드포인트로 호출.
- 이 때 Cache-Control 헤더를 설정하여 이미지를 캐시하지 않고 매번 로드하도록 유도.
- 이메일 HTML에 Lambda에서 반환된 이미지 URL을 삽입하여 이메일 본문에 이미지를 표시.
- CloudWatch 로그에서 Lambda 실행을 추적하고 디버깅.
처음 로그가 성공적으로 찍혔을 때, 그리고 그 로그를 cloudwatch에 옮겼을 때
정말 사무실에서 소리지를 뻔했다(물론 지르진 않았다)
그리고 내가 의지만 있다면 문제는 반드시 해결할 수 있다는 걸 알았다.
로그 로직을 전부 완성하고 나서 반신반의했던 주변 동료 분들도 정말 본인 일처럼 기뻐해주셨다!
그렇게 큰 시스템은 아니지만 혼자 생각해서 혼자 만들었다는 점이 정말 짜릿했다. 이래서 개발자 하는건가!(아닙니다)
이런 점을 좋게 봐주셔서 인지, 인턴 끝나고 마지막 인사를 할 때
"문제를 해결하시는 모습을 보고 대단하다고 느꼈어요. 조슈아님은 어디가서든 정말 잘할거에요."
"사실 정말 하실지 몰랐는데, 의지가 남다르신 것 같아요"
"조슈아님 너무 아까운데 ㅠㅠ 매일 13~15시간 씩 회사에 남아 일하고, 관련 공부를 하시는 걸 보고 저도 열심히 정진해야겠다고 반성했어요."
내가 내 칭찬을 받아적자니 좀 부끄럽긴 하지만 ^^;;ㅎㅎ
3개월의 인턴 기간 동안 남는 것이 하나도 없지 않았을까 절망하고 있었는데 이런 피드백을 들으니 헛되이 보내진 않았구나, 많이 노력했구나, 하는 생각이 들었다.
그만큼 이번 AWS를 이용해 만든 로그 추적은 나에게도 큰 의미로 남았다.
앞으로 어디에서 일을 하던 이 모습 그대로 있고 싶다
어려운 부분이 있어도 공부하면서, 모르면 물어보면서, 늘 의구심을 가지면서, 그렇게 조금씩 성장하면서 !
PS. 이자리를 빌어 로그 추적을 구축하기 위해 AWS 보안 권한 요청만 10번 넘게 했는데 흔쾌히 받아주신 팀원 분께 감사드립니다... 정말 죄송한 마음 뿐....(_ _ )