About
home
미션 & 비전
home

AWS Step Functions를 사용해 콘텐츠 데이터를 동기화 해보자

안녕하세요. 매쓰플랫 프로덕트 백엔드 개발자 이승현입니다. AWS Step Functions(이하 Step Functions)를 사용해서 콘텐츠 데이터 동기화 프로세스를 개발하는 과정과 발생한 이슈를 소개해 드리려 합니다.

# 동기화가 필요해

매쓰플랫이 성장하는 과정에서 무수히 많은 콘텐츠 데이터가 생기기 시작했고 그로 인해 Dev 환경과 Production 환경 간에 미묘한 데이터 차이가 발생했습니다. 그러던 중 QA팀에서 콘텐츠 데이터 관련 이슈가 발생했다는 연락을 받고 해결하고자 했지만 Dev 환경과 Production 환경 간에 존재하는 미묘한 데이터 차이로 인해 Dev 환경에서 바로 확인을 못했고 데이터를 복제한 후에야 해결이 가능했습니다.
계속 이러한 상항이 계속되면 이슈 처리가 지연되고 QA 기간에 데이터 간 차이를 바로잡지 못하게 됩니다. 그렇게 된다면 사용자의 신뢰 저하 뿐만 아니라, 개발팀은 QA팀에게 짊어지지 않아도 되는 짐을 건네는 상황이 반복하게 될 수도 있습니다.
그래서 저는 이를 해결하기 위해 여러가지 방법들을 모색하기 시작했고, Dev 환경과 Production 환경 사이 발생하는 미묘한 데이터 차이를 해결하는 여정을 시작하였습니다.

# 어떻게 해결할 것인가

동기화 프로세스 개발을 위해 내부적으로 선정된 조건들을 나열해 보자면 다음과 같습니다.
콘텐츠 데이터 구조의 변경 및 추가가 발생할 때마다 동기화 프로그램을 수정할 수 없다.
테스트로 사용할 데이터는 보존되어야 한다.
동기화 작업은 특정 시점에 한 번 진행해도 된다.
사용자에게 영향을 미치면 안 된다.
DB, S3를 동기화해주어야 한다.
S3는 S3 Sync(Source Directory와 Destination 간 변경된 파일만 감지하여 데이터만 옮길 수 있는 AWS CLI 명령어)를 통해 해결 가능하니 DB 동기화를 어떻게 해결할 것인가를 주로 고민했습니다.

DB 동기화

DB 동기화하면 가장 먼저 떠오르는 것은 Migration이 있기에 Migration을 어떻게 할 것인가를 위주로 모색해 보았습니다. 그리고 AWS에서 제공하는 서비스 중 AWS Database Migration Service(이하 DMS) 사용을 고려해 보았습니다. 하지만 AWS DMS의 경우 추가적인 비용이 발생하고 데이터를 복제하는 과정에서 DB에 부하를 발생시키기에 사용자에게 영향을 미칠 수 있습니다. (Capture Data Change, CDC 방식을 사용한다 해도 상대적으로 부하가 적은 것일 뿐 존재합니다. 그렇기에 AWS DMS를 선택하지 않았습니다.
이 외에도 매쓰플랫 2.0 프로젝트에서 사용한 방식으로 Trigger를 통한 데이터 변경 추적 후 사용률이 적은 시간에 복제하는 방식도 존재하지만 해당 작업은 Trigger 생성으로 인해 DB 부하가 발생하고 트랜잭션이 길어지기에 사용자 영향도가 높아 진행하지 않았습니다.
추가로 위 시스템을 개발하기 위해선 콘텐츠 데이터 구조를 변경하고 추가가 발생할 때마다 동기화 프로그램을 수정해야 하기에 완벽하게 개발할 수 있는 공수가 없었습니다. 그래서 적은 공수와 동기화 작업이 실시간이 아닌 특정 시점에 한 번 진행되어도 괜찮다는 것을 기반으로 다른 방법을 모색해 보았고 제 머릿속엔 하나의 아이디어가 떠올랐습니다
매쓰플랫에서 데이터 안전성을 위해 매일 생성하고 있는 Snapshot을 사용해서 Dev DB를 생성하면 큰 공수 없이 데이터가 완전히 동일하다는 보장이 가능하며, 고객에게 어떠한 영향도 없이 동기화 작업이 가능해진다!
그래서 저는 별도의 Migration 방식을 사용하는 것이 아닌 Production DB Snapshot을 사용해서 Dev DB를 생성하는 방식을 진행하기로 했습니다

# 무엇을 사용해서 해결할 것인가

무엇을 사용할 것인가를 결정할 때 주로 고민했던 부분은 다음과 같습니다.
적은 리소스로 개발할 수 있다.
AWS 서비스를 사용함에 있어 최적화되어있다.
AWS 서비스를 사용함에 있어 최적화되어있어야 하는 이유는 Production DB Snapshot을 사용해서 Dev DB를 생성하면 고려해야 하는 부분이 추가로 생깁니다. 대표적인 예로
생성한 후 기존 DB를 지워주지 않을 경우 동기화 시마다 계속 DB가 쌓인다.
Route53에 Record값을 변경하지 않을 경우 서버 입장에선 새롭게 생성한 DB와 커넥션을 맺지 못한다.
위 이슈들을 해결하기 위해선 RDS AWS 서비스를 추가적으로 이용해야 하고, Route53의 경우도 Route53 AWS 서비스를 추가적으로 이용하는 등 이를 관리하기 위해선 추가적인 AWS 서비스들이 필요합니다. Batch 같은 Code를 작성해서 사용하는 서비스를 사용할 시 관리해야 하는 SDK가 많고 그렇다고 AWS CLI를 Shell Script로 생성해서 관리하는 것 모두 관리하기 힘들며, 다른 개발자가 추가 작업 진행 시 알아야 하는 러닝 커브가 높다 판단하여, Step Functions를 사용하기로 했습니다.

Step Functions?

Step Functions가 무엇인지는 AWS Docs를 통해 알 수 있습니다
Step Functions는 AWS Lambda 함수와 자체 AWS 서비스들(Amazon States Language를 사용합니다)을 통합하여 business-critical application을 만들 수 있게 해주는 serverless orchestration 서비스입니다. 종합하자면 아래의 이유들로 저는 Step Functions를 선택했습니다.
적은 리소스로 개발할 수 있다. - 이는 Step Functions의 Workflow Studio를 통해 Code 기반이 아닌 Graphic 기반
AWS 서비스를 많이 쓴다.
특정 주기에 한 번 작동하기에 서버리스가 비용 최적화되어 있다.
시각화를 기본적으로 지원한다.
그렇게 저는 Step Functions를 기반으로 여러 AWS 서비스들로 DB 동기화 프로그램 개발을 시작하였습니다.

# 개발 중 발생한 문제들

개발이 순탄하게 완료되면 좋았지만 그렇지 않기에 재밌는 것이 개발 아닙니까!? 개발하면서 몇 가지 문제가 발생했고 그 중 기억나는 부분들을 공유 드립니다

Step Functions는 요청만 보낸다

테스트를 진행하던 중 동기화가 완료되었음에도 서버가 변경된 DB와 커넥션을 맺지 못하는 이슈가 발생했습니다. 그 이유를 찾아보니 아직 DB는 생성이 완료되지 않은 상태에서 Route53 Record 값을 변경하면서 발생한 이슈였습니다. 저는 단순하게 해당 DB의 상태를 Polling 하면서 DB가 생성 완료되었는지 확인 후 완료되었을 때 다음 스텝으로 넘어가도록 세팅하였습니다
참고로 Wait for task to complete(콜백 대기)란 옵션으로 위 작업을 대체할 수 없습니다 관련 설명은 AWS Docs를 통해 확인 가능합니다 [Docs]

S3 Sync

Amazon States Language에 존재하는 명령어들은 대부분 AWS CLI에 존재하여 Amazon States Language에도 S3 Sync 기능이 있을 것이라 생각했습니다. 이 부분은 억울하게도 Amazon States Language의 명령어들은 AWS CLI 명령어의 Naming conversion을 Pascal case로 변경만 한 것인가라고 생각할 정도로 동일하게 되어있습니다. 하지만 Amazon States Language에서는 S3 Sync라는 기능이 없습니다. 그렇다고 S3 Copy를 사용하게 되면 모든 데이터를 옮기게 되고 그러면 동기화 시간이 오래 걸릴 뿐 아니라 비용 또한 상당히 증가하게 됩니다. 이를 해결하기 위해선 Step Functions를 통해 S3 Sync를 구현했으며, 동일한 파일 여부는 S3 Sync에서 비교하는 항목인 수정 일자와 파일 사이즈를 기반으로 체크하였습니다. 추가로 GetObjectAttributes 진행 시 파일이 없으면 에러가 발생하므로 Catch를 작성해 주어야 합니다.
위 방식으로 Step Functions를 생성 후 데이터 동기화 Step Functions에서 필요한 버킷을 호출해서 사용할 수 있도록 세팅하였습니다.

관제 및 에러 대응

작업의 진행도를 파악하는 것은 어렵지 않습니다. 매 작업 종료 시 Slack에 메시지를 발신하도록 세팅하면 쉽게 해결할 수 있습니다.
하지만 만약 작업을 진행하는 중 에러가 발생하여 작업이 마무리되지 않았다면?.. 테스트 환경에 마비가 발생할 수 있기에 에러를 빠르게 파악하고 만약 에러가 발생했다면 자동 롤백이 이뤄질 수 있는 환경을 구성해야 했습니다.
그렇기에 DB 데이터 동기화와 S3 Sync를 별도의 Step Functions로 개발 후 상위 Step Functions에서 호출하면서 에러 발생 시 Slack에 메시지 전송 후 롤백 프로세스를 실행하도록 세팅하였습니다

# 조금은 아쉬운 포인트

완전하지 않은 시스템

완전한 시스템이란 무엇인가?
저는 완전한 시스템이란 근본적인 이슈를 해결해서 추가 요구사항이 없어도 그 후에도 해당 프로세스에 대해 수정이 이뤄지지 않는 것을 완전한 시스템이라 생각합니다.
그 측면에서 이번에 진행한 프로젝트는 완전하지 않은 시스템이라 생각합니다. 그 이유로는 돌아가는 주기가 일정하지 않아 현재는 개발자가 직접 콘솔에 접근하여 수동으로 동기화를 실행시켜 주고 있어 이를 자동화 시키기엔 실행 주기가 일정하기 때문입니다.
이로 인해 휴먼에러가 발생할 수 있어서 현재 AWS System Manager Change Calendar를 통해 내부적으로 사용하고 있는 Google Calendar와 연동해서 동기화일 공유 및 미리 세팅할 수 있는 환경을 만들고자 하는 중입니다.

# 후기

어떻게 하면 적은 비용으로 누구나 쉽게 유지 보수할 수 있을까에 대해 고민하다 보니 Step Functions도 사용해 보고 정말 흥미 있고 재밌는 프로젝트였습니다. 위 프로세스를 개발하면서 이슈를 파악하거나 테스트를 진행하는 과정에서 더욱 매끄럽게 진행이 가능해졌고 테스트 및 개발하면서 발생하는 더미 테이블 등의 관리들도 보다 수월해진 것이 진행하기 전보다 더욱 개선되었다고 느껴졌습니다.
비록 근본적인 이슈를 해결하지 못해 완전하지 못하다 생각하지만 새로운 기능에 대해 알고 경험하고 현재 문제없이 사용하고 있기에 만족스러운 프로젝트였습니다. 만약 이 글을 보는 당신! 빠르게 개발해야 하며, AWS 서비스들을 복합적으로 사용하는 프로젝트가 있다면 Step Functions 한 번 고려해보는 것이 어떨까요? 추가적으로 이 글에 사용된 순서도 이미지들은 전부 Step Functions의 Workflow Studio에서 생성했습니다.
물론 Step Functions로 개발하는 순간 AWS 의존성이 상당히 커지게 됩니다. 어느 한 곳에 의존성이 커지면 그만큼 단점 또한 존재하기에 이 부분도 고려해 보기를 추천드립니다. 저는 매쓰플랫 프로덕트 백엔드 개발자 이승현이었으며, 이 글이 당신에게 도움이 되었길 바라며 이만 물러가겠습니다.