2024년 7월 15일부터 2024년 8월 3일까지 3주 동안 ACC에서 여름방학 프로젝트(+ 해커톤)을 진행했다.
저희 팀은 8월 31일까지 추가적으로 인프라 및 기능들을 다듬었다.
프로젝트를 진행하며 느낀 점을 간단히 회고해 보려 한다.
깃허브는 아래 링크를 통해 확인할 수 있다.
https://github.com/aws-cloud-clubs/ACC-hotsix
GitHub - aws-cloud-clubs/ACC-hotsix
Contribute to aws-cloud-clubs/ACC-hotsix development by creating an account on GitHub.
github.com
ACC란?
ACC는 AWS Cloud Clubs의 약자로, AWS의 공식적인 대학생 커뮤니티이다.
AWS Student Community Day와 같은 세션부터 다른 커뮤니티에서는 겪어보기 힘든 인프라 해커톤까지 함께 하며 큰 발전을 할 수 있었다.
2024년 ACC에서 한 활동들이 궁금하다면 아래 링크를 참고하면 좋을 것 같다.
https://www.awscloudclubs.kr/posts/recap-2024/
ACC Korea 2024년 돌아보기 - ACC Korea
ACC Korea는 2024년에 어떤 활동들을 해 왔을까요? 한 해 동안의 여정을 되돌아 보아요.
www.awscloudclubs.kr
해커톤 1주차 (7/15 - 7/21)
1주차에는 팀원 매칭, 멘토-멘티 매칭, 주제 선정, 팀원 역할 분배를 진행했다.
우리 팀은 황성찬 멘토님과 함께하게 되었다.
그리고 또 특이한 점이라면 우리는 동덕여자대학교, 이화여자대학교, 숙명여자대학교의 3여대와 공학 대학 여자분까지 총 5명이 전부 여자로 구성되었다.
ACC 해커톤의 주제가 정해지고, 캡틴분들께서 "가상 면접 사례로 배우는 대규모 시스템 설계 기초" 책에서 주제를 가져오셨다고 말씀해주셔서 난 해당 책을 구매해 참고했다.
7월 15일 월요일
첫 번째 회의에는 각자 자기소개를 하고 역할 분담을 진행했다.
팀장은 어쩌다 보니 내가 맡게 되었고, 팀명은 6조에서 따와 "핫식스"라고 지었다.
나와 예린님이 인프라를 맡았고 민정님, 예림님, 지민님이 서버를 맡아주기로 하셨다.
그리고 "가상 면접 사례로 배우는 대규모 시스템 설계 기초" 책에서 주제에 해당하는 부분의 구조 등을 공유하며 1순위와 2순위 주제를 정했다.
우리 조의 1순위 주제는 채팅 시스템 설계, 2순위 주제는 파일 공유 시스템 설계로 정해졌다.
결국 주제는 "파일 공유 시스템 설계"로 정해졌는데 돌이켜보면 오히려 파일 공유 시스템이 채팅 시스템보다 더 구현하기 쉬웠던 것 같다.
채팅 시스템은 동시성이나 웹소켓 등 기술적으로 고려해야 할 점이 많았기 때문이다.
주제 세부 내용은 다음과 같다.
7월 20일 토요일
주제가 정해지고, 멘토님과 첫 번째 회의를 진행했다.
멘토님과 회의를 진행하기에 앞서 멘티들끼리 모여서 가볍에 아이스 브레이킹을 가지고 주제에 대해서 논의했다.
프론트엔드 인원이 존재하지 않는 것에 대해 의견이 많았는데, 해커톤의 주제 참고 사항 중 다음과 같은 내용이 있었다.
프론트엔드 페이지를 구현하는 것과 기능적인 요구 사항을 충족하는 것은 중요하지 않습니다.
핵심은 ‘좋은 아키텍처를 얼마나 잘 구현하는가’ 입니다.
멘토님께서도 요구사항을 만족하는 인프라 구축이 우선이 되어야 하고, 아키텍처를 이용하면 서비스를 이용할 수 있게끔 하는 것이 좋겠다고 피드백을 남겨주셨기 때문에 최종 시연에서는 API를 보이는 것으로 결정하고 넘어갔다.
다음으로는 프로젝트에서 고려해야 할 기능과 비기능 사항에 대한 이야기를 나눴다.
파일 공유 시스템에서 고려되어야 할 기능 사항으로는 다음과 같은 이야기가 나왔다.
- 파일 업로드
- 파일 다운로드
- 파일 동기화
- 파일 접근 권한 링크 공유
- 파일 히스토리 볼 수 있는 기능
- 1단계 : 파일 링크로 접근만 가능, 메타데이터에 접근 관련 기록만 추가 ← 목표
- 2단계 : 파일 링크로 수정 권한 부여, 메타데이터에 접근, 수정, 삭제 기록 추가
파일 공유 시스템에서 고려되어야 할 비기능 사항으로는 다음과 같은 이야기가 나왔다.
- 파일 용량
- 파일 제한 : 10MB
- 사용자 제한 : 1GB → 소유자 기준
- 사용 인원 : 10,000
- 파일 암호화
- 1단계 : 암호화 없음
- 2단계 : 파일 암호화 기능 구현
- 추후 비용 & 안정성 간 고려가 필요할 것
- 에러 대응 → 리소스가 다운되었을 때 어떻게 대응할 것인지 (인프라)
- 백업
- 로그 확인 및 담당자 알림
- 가용성
- 안정성
또한 멘토님께서 단순히 컨펌을 받고 싶어서 질문하는 것은 지양하고, 조사한 내용을 바탕으로 결정을 내리고, 결정을 내린 근거와 함께 보고를 달라고 하셨다.
이 내용이 정말 이번 해커톤에서 크게 성장할 수 있었던 원동력인 것 같다.
해커톤 2주차 (7/22 - 7/28)
2주차에는 인프라/서버 별로 회의를 진행하고 주간 회의를 통해 진행 상황을 동기화했다.
7월 22일 월요일
지금 보면 정말 귀여운 1차 아키텍처가 완성되었다.
서버 팀이 작성한 유저 시나리오를 바탕으로 아키텍처와 싱크를 맞추는 시간을 가졌고, 파일 접근 / 검색 / 파일 업로드 / 파일 다운로드 / 파일 조회 / 파일 공유 기능에 각각 어떤 AWS 서비스가 사용되어야 하는지를 논의하였다.
해당 내용을 바탕으로 인프라 팀은 추가 회의를 진행했다.
가용성을 높이기 위해 RDS Multi az, EC2 Auto Scaling 도입을 논의했다.
멘토님께서는 로드 밸런서는 public subnet에, EC2는 private subnet에 두어 보안을 고려할 것, SG와 NACL로 인스턴스와 서브넷을 제어할 것, NAT Gateway와 Bastion Host에 대한 내용과 CI/CD 파이프라인에 대한 내용을 말씀해주셨다.
7월 23일 화요일
멘토님의 피드백 내용을 바탕으로 2차 아키텍처를 그렸다.
이때부터 예린님과 나는 각자 회의 전 자료 조사를 진행하고, 내용을 공유한 뒤 아키텍처를 결정했다.
우리가 회의를 잘 진행하고 궁금한 점을 작성해두면 종종 멘토님께서 읽고 댓글을 달아 주시기도 했다. 이번 회의를 바탕으로 public subnet에 Load Balancer를 두고, private subnet에 EC2를 두어 EC2의 보안을 고려했고, EC2에서는 Gateway Endpoint를 이용해 S3에 접근할 수 있도록 아키텍처를 구상하여 3차 아키텍처를 작성했다.
지금 와서 보면 AZ 표시도 없고 Public Subnet은 하나이지만 나름 필요한 내용들은 다 담겨 있는 것 같다.
그리고 우리는 멘토님께 보고할 때 꼭 다음과 같이 이전 아키텍처에서 변경된 사항과 그 이유, 다음 회의에 진행할 내용을 작성했다. 정말! 이 덕분에 많이 성장할 수 있었다.
[@황성찬](https://aws-cloud-clubs.slack.com/team/U07C7LVR5LN) 안녕하세요 멘토님! 3번째 아키텍처가 완성되었습니다.
이전 아키텍처에서 변경된 사항은 다음과 같습니다.
1. 회의 결과 ALB를 통해서 private subnet에 있는 EC2와 통신할 수 있다는 결론을 도출했고, 아키텍처에 적용했습니다.
2. AZ에 EC2가 있는 private subnet 하나씩만 남아 AZ 표시를 지웠습니다. 해당 부분은 확실하지 않아 다음 회의까지 각자 AZ를 표시하는 이유와 역할에 대해서 공부한 뒤 수정될 수 있을 것 같습니다.
1. 현재 AZ를 지우게 된 계기는 Public Subnet을 지우게 되면, EC2가 존재하는 Private Subnet이 하나씩만 존재하기 때문에 AZ 구별이 없어도 된다는 이유 때문이었습니다.
3. S3와 EC2의 통신을 Gateway endpoint를 사용하기로 결정했고, 해당 내용을 반영했습니다.
4. 메타데이터를 저장하는 SQL DB 서비스로 AWS RDS를 사용하기로 결정했습니다.
다음 회의 때는 이러한 내용들을 추가해보려고 합니다.
1. 서버 회의를 통해 동기화 방법이 확정되면 필요한 AWS 서비스 찾아오기
2. AZ를 표시하는 이유와 역할에 대해서 공부한 뒤 아키텍처에 필요한지 논의하기
3. 파일 업/다운로드 지연 시간은 1분 이내 ← 해당 조건을 만족하는 아키텍처인지 생각해오기. 만족하지 않는다면 어떤 서비스를 도입하면 될지 찾아오기
4. Well-architected 원칙 공부
- 은소 : 운영 우수성 원칙, 보안 원칙, 안정성 원칙
- 예린: 성능 효율성 원칙, 비용 최적화 원칙, 지속 가능성 원칙
- 회의 중 - 정리해 온 내용 공유, 현재 아키텍처 평가→ 수정 필요시 수정
오늘 논의된 모든 내용을 회의록에 정리해 두었습니다. 필요하실 때 참고해 주시면 감사하겠습니다.
[https://www.notion.so/aws-cloud-clubs/7-23-34ae76f1505c4a2e8545d0a4848db70a?pvs=4](https://www.notion.so/7-23-34ae76f1505c4a2e8545d0a4848db70a?pvs=21)
7월 25일 목요일
멘토님의 피드백을 바탕으로 고가용성 측면에서 AZ의 역할에 대해 논의해 다시 아키텍처에 넣기로 결정했다.
또한 파일 업/다운로드 지연 시간을 줄이기 위해 CloudFront(글로벌 서비스를 하지 않기 때문에 유의미하지 않다고 판단), S3 Multipart 업로드(대용량 파일을 여러 개로 나눠 업로드), 스토리지 최적화 EC2, RDS Read Replica 등의 서비스 도입을 고려하였다.
해당 내용들을 포함하여 4차 아키텍처가 완성되었다.
먼저 RDS에 대해 master-slave라고 쓴 점에 대해서 피드백을 받았다. 다음부터는 꼭 Primary-standby로 작성하기...!
7월 26일 금요일
토요일이 멘토님과 진행하는 주간 회의이기 때문에 하루 전인 금요일에 서버 팀과 모여 진행 중인 작업의 싱크를 맞췄다.
또한 인프라에서 논의한 사항에 따라 S3 multipart를 사용하기로 결정하고, 파일 동기화 기능 구현 여부에 대해서도 마지막까지 의견을 나눴다.
7월 27일 토요일
CloudFront 도입에 앞서 비용 계산을 진행했다.
계산 결과 CloudFront 비용만 총 $123.9 달러가 나와 해당 서비스는 포기하기로 했다.
또한 파일 동기화 기능에 대해서 많은 의견을 주고받았다.
파일 동기화 기능을 파일 수정 시, 수정하는 동안 제 3자가 수정 내용을 화면에서 확인하는 경우 필요하다.
따라서 제 3자가 수정이 반영되기 전에 URL에 접속하거나 접속한 상태라면 버전 이슈가 필요해 동기화가 필요해진다.
해당 내용에 대해 전체 회의에서 논의하기로 했다.
또한 RDS Read-Replica와 standby RDS의 역할 차이에 대해서도 얘기를 나눴다.
조사한 내용 중 Read Replica RDS의 경우에도 Primary DB 장애 상황이 발생했을 때, primary RDS로 승격되어 read/write 기능을 모두 수행할 수 있다고 하여 Read Replica만 남기고 standby RDS를 삭제하기로 했다.
나중에 알게 되었지만 Read Replica는 I/O 처리 속도를 올려주는 용도일 뿐 장애 대응은 하지 않는다고 한다.
마지막으로 아키텍처에서 서브넷의 IP 대역이 포함되지 않아 해당 내용을 포함해 5차 아키텍처를 그렸다.
위의 내용을 바탕으로 멘토님과 회의를 진행하였고, 기능 구현에는 충실했으니 개발자가 개발에만 집중할 수 있는 파이프라인(CI/CD)을 구성하면 좋겠다는 피드백을 받았다.
해커톤 3주차 (7/29 - 8/3)
3주차에는 진행 상황을 마무리한 뒤 8월 2일부터 3일까지 무박 2일 해커톤을 진행했다.
7월 29일 월요일
3차 아키텍처부터는 우리의 EC2가 전부 private subnet으로 내려왔다.
그래서 EC2 관리를 위한 구성이 필요해졌다.
후보군으로 1. Bastion host 2. SSM Session Manager를 고려하게 되었다.
Bastion host는 SSH 키 관리가 필요하고, EC2 인스턴스 비용이 발생하며, 인바운드 포트 개방 등 추가적인 설정이 필요하다. 이는 필요로 하는 기능에 비해 관리해야 하는 것이 많다고 생각이 들었다.
그래서 IAM 권한으로 관리할 수 있는 Session Manager를 도입하여 EC2를 관리하기로 하였다.
또한 마지막까지 파일 동기화 기능에 대해서 논의했다.
마지막 멘토님과의 회의에서 UI가 없이 서버-인프라만 연결해서 배포하기로 결정했기 때문이다.
UI가 없는 환경에서는 실시간으로 화면에서 동기화를 확인하지 않기 때문에 파일 동기화의 필요성이 낮아진다고 생각했다.
따라서 버전 관리 시스템과 백업을 이용해서 파일 동기화 기능을 대체하기로 했다.
이 경우 유저 시나리오는 다음과 같이 작성했다.
- 만약 예린이 S3에 저장이 되어있는 A 문서의 공유 링크로 접속했다고 하자.
- 1 과정 중, 은소가 A 문서를 수정하였고 수정 API를 통해 해당 내용은 S3와 RDS로 저장이 되는 중이다.
- S3와 RDS로 새로운 내용의 A’ 문서가 저장이 되었다. 이때 예린은 계속 공유 링크로 접속해 A 문서를 보고 있다.
- 이때 예린이 해당 파일을 다운로드하려고 한다. → 이때 최신 버전의 파일인지 확인을 하고 새로 고침을 하라는 alert를 받음 (물론 지금은 프론트엔드 alert가 없기 때문에, 서버의 json 형태의 response msg로 대체 예정)
- 예린은 갱신 된 버전의 파일(A’)를 다운로드할 수 있음
그리고 사용자 구분을 위해 비밀번호 기능을 도입하기로 했다.
비밀번호를 사용하는 경우의 유저 시나리오는 다음과 같다.
- S3 읽기/쓰기 권한이 있는 IAM(A)과 S3 읽기 권한이 있는 IAM(B) 생성
- 비밀번호를 입력해 일반 조회를 한 사용자에게는 (STS로) IAM(A) 임시 발급
- 공유 링크로 접근한 사용자에게는 (STS로) IAM(B) 임시 발급
우리의 최종 유저 시나리오는 다음과 같이 완성되었다.
또한 해커톤 기간 동안 구축을 완료할 수 있도록 NACL과 SG를 포함하여 문서화 작업을 시작했다.
한번 제대로 문서화를 하면 비밀번호라던지, 이름을 확인하기 참 좋은 것 같다.
7월 31일 수요일
해커톤 시작을 앞두고, 마지막 구성 요소인 CI/CD 파이프라인에 대해 논의했다.
처음에는 CI/CD가 각각 무엇을 뜻하는지도 몰랐다.
CI는 Continuour Integration, CD는 Continuous Deployment로 지속적인 통합과 배포를 말하는 것이다.
이러한 지속적인 통합과 배포를 간편하게 하기 위해 자동화 파이프라인을 작성한다.
https://dev.classmethod.jp/articles/create-aws-code-pipeline-ci-cd-environment-kr/
초보자도 이해하는 AWS Code Pipeline CI/CD 환경 만들어보기 | DevelopersIO
AWS Code 시리즈를 이용하여 Code Pipeline으로
dev.classmethod.jp
해당 글을 참고해서 CodeDeploy를 이용한 CI/CD 파이프라인을 구성하기로 했다.
파이프라인의 흐름은 application developer → github → code pipeline(codebuild → s3에 아티팩트 저장 → deploy) → EC2 서버에 배포로 생각했다.
29일에 Session Manager 도입에 대한 이야기를 나누었는데, 원래 흐름은 EC2에 SSH 접속 → Bastion Host → Session Manager 순으로 업그레이드 되는 것이라고 멘토님께서 말씀해주셨다.
그래서 우리도 "공부하는" 프로젝트인 만큼 Bastion Host를 도입해 보기로 하였다.
마지막으로 완성된 아키텍처는 다음과 같다.
이때 CI/CD 과정에서 Prod/Dev 환경을 나누는 것에 대한 논의가 있었다.
하지만 우리가 해커톤이고, 실제로 서비스를 하는 것이 아니기 때문에 하나의 파이프라인만 구성하는 것으로 결론이 났다.
마지막으로 서버 팀과 진행 상황 공유를 한 뒤 8/1 - 8/2 동안 진행될 해커톤을 위해 기운을 비축하기로 하며 헤어졌다.
사실 인프라 팀은 남아서 아키텍처 설계 문서를 작성했다.
약간만 가져와보자면
Public Subnet 1
- ALB 들어갈 Public Subnet
- CIDR 범위 : 10.0.0.0/24
- AZ : ap-northeast-2a
- acc6-s-prd-an2-pub-az1
- 태그: public-subnet
EC2 1
- Springboot 배포할 EC2
- AZ : ap-northeast-2a
- 서브넷 : acc6-s-prd-an2-pri-az1-ec2
- 이미지 : ubuntu
- 인스턴스 : t3.micro
- acc6-ec2-prd-an2-az1
- 태그: ec2
이런 식으로 생성할 모든 요소에 대해 정리했다.
해커톤 진행 (8/1 - 8/2)
해커톤 당일에는 인프라 팀 / 서버 팀 나누어져서 정신없이 구현을 진행했다.
정말 구현하면서 알 수 없는 오류들이 많이 나서 멘토님께도 SOS를 요청했는데 멘토님조차도 알 수 없는 오류들이 엄청나게 많이 났다.
그리고 우리가 구성한 Nacl, SG가 매우 세세하게 접근 통제를 한다고 하셨다. (현업에서도 이렇게까지 하지는 않는다고...)
급하게 시연이 가능할 정도로 구현을 마쳤다.
새벽에는 신재현 멘토님께서 전반적인 AWS 인프라에 대한 강연을 해주셨다.
밤을 새서 비몽사몽했지만 최대한 열심히 들었다.
발표가 끝나고, RDS Read-replica는 가용성 용도로 사용되지 않는다는 것과, S3 presigned url을 사용하지 않았다는 것, url 생성 과정에서 취약점이 발행한다는 아쉬운 피드백을 받았다.
해커톤이 끝나고, 아쉬운 사람들끼리 모여 추가적으로 아키텍처를 업그레이드 하기로 했다.
해커톤 이후
해커톤이 끝나고, 인프라 2명 서버 1명이 남아서 추가적으로 아키텍처를 업그레이드했다.
각 분야에서 디벨롭 진행 우선순위를 작성하고, 대략적인 데드라인을 정했다.
인프라
- Multi AZ RDS 추가
- S3 Glacier 도입
- EC2 private subnet 이동
- EC2 Auto Scaling Group 도입
- AWS Session Manager 도입
- Security Group 및 NACL 접근 제어
서버
- CI/CD 파이프라인 수정
- Presigned url 사용
- url 링크 생성 시 취약함 - 보안 조치 필요
- 예외 처리 전략 생성
기타
- Route53을 이용해 도메인 붙이기
- 부하테스트 진행
그렇게 우리의 찐_최종_정말_마지막 아키텍처가 완성되었다.
아키텍처도 아키텍처지만 정말 CI/CD 파이프라인을 구성한 것이 자랑스러워서 따로 이미지도 만들었다.
이렇게 한번 배포를 하고 나니 ECR을 사용해서 이미지로 배포를 하는 것이 정말 편리하다는 것을 깨달았다.
이때부터는 개발도 개발이지만 정말 매일마다 모여서 트러블슈팅을 했다. 하나 고치면 하나가 죽고, 그거 살려놨더니 저게 죽는 문제가 계속 발생했다.
이것도 전부 다 문서화해서 다시는... 발생하지 않도록 했다.
같은 주제로 진행한 옆 팀에서 부하 테스트를 진행했는데, 그게 좋아 보여서 마지막으로 우리도 부하테스트를 진행했다.
해커톤 후기
해커톤 동안 진짜 이보다 더 열심히 할 수는 없겠다 싶을 정도로 열심히 했다.
이틀마다 회의하고, 회의를 위해 정보를 찾고, 정보를 찾는데 확신은 없으니까 이게 맞나? 하면서 계속 찾고...
그런데 오히려 아는 게 없을 때 멘토님이라는 든든한 정신적 지주가 있었던 게 큰 축복이었다.
멘토님께서 정답을 알려주시지는 않더라도, 방향성을 알려주시기 때문이다!
그리고 멘토님의 입장에서는 우리가 잘해봤자 병아리다. 그래서 맘 편히 틀렸다. 열심히 했다는 어필을 하면 멘토님께서도 '아 그래 모르는 것일 뿐이구나...' 하면서 피드백을 남겨주셨기 때문이다.
나는 3차 아키텍처에서 AZ 빼놓기도 했는데, 이것보다 더 할 리가...
마음 맞는 팀원이 있었던 것도 큰 도움이 됐다.
나 혼자 열심히라면 기운 빠지는데, 둘 다 이틀에 한번씩 회의 하면서도 서로를 배려하면서 열심히 으쌰으쌰했기 때문이다.
해커톤이 끝나고 디벨롭을 진행한 팀도 우리밖에 없는 것으로 아는데, 이것도 다 팀원을 잘 만난 덕분인 것 같다.
서버 팀원들도 각자 역할대로 멋있게 개발해주시고, 인프라 에러 터지면 같이 확인해주셔서 해커톤 때 시연도 잘 하고 마지막 추가 디벨롭까지 잘 할 수 있었다.
올해 가장 후회 없는 활동이었다!