유플러스 수료를 하루 앞두고 적는 Filmeet의 인프라 구축기입니다.
프론트와 백엔드의 CI/CD 파이프라인을 구축하고, 테스트 환경을 팀원 모두 동일하게 가져가기 위해서 인프라를 설정한 경험은 매우 값지고, 어려운 경험이었습니다.
진정으로 데브옵스는 백엔드의 2차 전직 같은... 느낌을 받았습니다.
네트워크 전공 시간에 배운 내용을 인프라를 우선 돌아가게 구축하고 추후에 공부하면서 깨닫는 부분이 많았던 것 같습니다.
아키텍처
우선 제가 크게 3가지로 나누어서 진행했습니다.
1. 프론트엔드 CI/CD 파이프라인 구축
2. 백엔드 CI/CD 파이프라인 구축
3. 배포 환경과 테스트 환경을 분리
또한 사용한 스택은 정리하자면
- 백엔드: ECS (Fargate) + Amazon ECR + ALB
- 데이터: Amazon RDS (MySQL)
- 이미지 저장소: AWS S3
- CI/CD: GitHub Actions
- 모니터링: AWS CloudWatch
- 프론트엔드: Amplify
각 파트에 대해서 설명하면서 자세하게 어떤 이유에서 해당 스택들을 선택하게 되었는지 설명드리겠습니다.
프론트엔드 CI/CD 파이프라인 구축
순서상 프론트엔드 CI/CD 파이프라인 구축을 마지막에 했지만, 제일 처음으로 소개하게 됐네요.
우선 CI/CD란 무엇일까요?
바로 'Continuous Integration(지속적 통합) & Continuous Deployment(지속적 배포) '를 의미합니다.
이를 풀어서 설명하면,
- 지속적 통합 : 코드 변경 사항을 자주 통합, 자동화된 빌드와 테스트를 통해 코드 품질 보장
- 지속적 배포 : 코드 변경 사항이 자동으로 배포
를 의미합니다.
왜 CI/CD를 구축할까요?
그 이유를 찾기 위해선 우선 DevOps라는 개념부터 알아야 합니다.
DevOps란 개발(Development)과 운영(Operation)의 합성어로,
소프트웨어 개발과 운영 팀 간의 효율적인 협업을 목표로 하는 문화를 지칭합니다.
이는 결론적으로 효율적인 협업을 목표로 하며, 기업의 거대화했을 때 나타나는 팀 간의 벽인 사일로와 정반대의 개념입니다.
이런 '효율적인 협업'이라는 목표를 달성하기 위해서 DevOps는 크게 4가지 원칙을 지킵니다.
- 자동화 : 빌드, 테스트, 배포와 같은 작업을 자동화하여, 반복 작업을 줄입니다.
- CI/CD : 코드 변경 사항을 자동으로 통합하고 테스트해서, 배포 과정에서의 오류를 줄입니다.
- 모니터링과 피드백 : 서비스 상태를 실시간으로 모니터링하고, 문제를 해결합니다.
- 협업과 소통 : 개발과 운영 팀이 공통의 목표를 달성하기 위해서 소통합니다.
아무튼 돌고 돌아서 설명한 효율적인 협업을 지향하는 DevOps라는 문화를 정착시키기 위해서 쓰이는 도구가 바로 CI/CD입니다.
이를 통해서 코드 변경 사항이 자동으로 통합되고 테스트되기 때문에 팀원 간의 협업이 쉬워지고, 이를 통해 빠르게 배포하여 서비스에 빠르게 적용할 수 있습니다.
그래서 결론적으로 프로젝트의 목표 달성을 위한 팀 전체의 생산성을 극대화할 수 있습니다.
프론트엔드의 경우, AWS Amplify와 S3+CloudFront를 사용해 직접 하는 방법 두 가지 중에서 고민했습니다.
사실 Amplify 역시 S3 기반의 환경에 정적 리소스를 업로드하고, CloudFront를 통해 배포하는 것 똑같지만 이를 직접 설정하지 않고 자동으로 처리해 준다는 차이가 있습니다.
S3와 CloudFront에 대해서 간략히 설명하자면,
S3는 Simple Storage Service의 약자로, 이미지, 동영상 그리고 HTML/CSS/JS와 같은 정적 리소스를 저장하고 관리합니다.
또한 특정 버킷을 웹 호스팅 용도로 설정하고 퍼블릭 액세스를 허용하면 HTTP/HTTPS를 통해 웹 콘텐츠를 제공할 수 있습니다.
그리고 CloudFront는 AWS의 CDN으로, CDN는 콘텐츠 전송 네트워크를 의미하며 S3와 같은 origin에서 데이터를 가져와 사용자와 가장 가까운 엣지 서버를 통해 콘텐츠를 제공함으로써 latency를 최소화하는 기능을 합니다.
또한 캐싱도 하여 자주 액세스 되는 콘텐츠를 엣지 서버에 저장하여 원본 서버에서 I/O 하는 작업 자체를 줄여 성능 또한 향상합니다.
아무튼! Amplify를 통한 방법과 직접 S3+CloudFront를 설정하는 방법 각각의 장점은
- Amplify의 경우 CI/CD 파이프라인이 내장되어 있어 Git 레포지토리만 연동하면 코드 변경 사항이 자동으로 빌드되고 배포되어 큰 설정 없이 진행될 수 있다는 장점이 있습니다.
- 그리고 S3+CloudFront의 경우 좀 더 배포 환경을 세부적으로 설정할 수 있고, 비용을 좀 더 절약할 수 있다는 장점이 있습니다.
결론적으로 프론트엔드는 Amplify를 통해서 구현했습니다.
그 이유는, 백엔드의 경우 첫 주차에 Github actions + docker + ECR + ECS + Route53 등등을 통해서 CI/CD 구축을 완료했었는데, 프론트엔드의 경우 프로젝트 마지막 주에 CI/CD 구축을 하자는 팀원 간의 합의가 있었습니다.
마무리하면서 발표도 하고 다양한 것들을 함께 해야 하는 팀장의 역할도 하면서 했던 거라, 최대한 빠르게 배포가 가능한 Amplify를 선택했고, 비용의 경우도 현재는 Ureka에서 팀에게 105만 원을 지원해 줘서 편하게 사용이 가능한 상황이라
비용 < 시간이라는 조건이라고 생각이 들어 Amplify를 선택했습니다.
또한 AWS에서 도메인 구매와 호스팅까지 해주는 Route53을 통해서 filmeet.me 도메인을 통해서 접속할 수 있게 구현을 했습니다.
링크 : https://filmeet.me/
(하지만 여러분이 이 글을 볼 때는, 이미 Ureka의 지원이 끝나 링크가 안 열릴 가능성이 높습니다. 하하)
어려웠던 점
인프라를 세팅하면서, 팀 전체 관리를 하면서, API 개발과 연동, 테스트까지 짧은 프로젝트 기간 내에 진행하느라 우선 기능이 돌아갈 수 있게 구현하고 추후에 학습을 하며 이해하였습니다.
근데 제가 넉넉하게 지원해 주는 지원금 덕분에 백엔드만 배포가 되어있는 환경에서도 filmeet.net에 배포를 하여
api 요청을 https://filmeet.net/~ 이렇게 하게끔 했는데, 나중에 프론트엔드 배포할 때 제대로 이해하지 않고 사용자 지정 도메인을 구매하고 연결하는 과정에서 꼬여서 한참 씨름했던 경험이 있습니다.
또한 실제 프론트엔드 분들의 로컬 환경에서는 import문의 대문자와 소문자가 다르더라고 배포가 되는 반면,
Amplify의 경우 하나라도 철자가 다르면 빌드 에러가 발생해 컨벤션을 지키지 않은 프론트엔드 개발자 분들의 레거시가... 저에게 돌아와... 하나하나 수정하고 빌드하고 하는 과정을 거의 50번은 한 것 같습니다.
그래도 백엔드 CI/CD 구축할 때와 비교해서는 비교적 수월하게 구축한 것 같습니다.
백엔드 CI/CD 파이프라인 구축
처음 사용해 본 AWS라, 첫 주차에 바로 CI/CD 구축을 하기 위해서 목차를 정해서 진행했습니다.
- IAM 사용자 생성 및 권한 관리
- S3 버킷(이미지 저장용) 생성 및 설정
- 애플리케이션 컨테이너화 및 ECR 설정
- AWS RDS 및 ElasticCache(Redis) 설정
- ECS(Fargate) 설정
- 대상 그룹 및 ALB 설정
- 오토스케일링 설정
- CI/CD 파이프라인 구축
- 모니터링을 위한 CloudWatch 설정
1. IAM 사용자 생성 및 권한 관리
우선 첫째로, CI/CD 작업 및 AWS 리소스 관리를 위해 전용 IAM 사용자를 생성했습니다.
또한 최소 권한 원칙에 따라, 아래와 같은 권한을 부여했습니다.
(근데 사실 개발할 때는 AdminFullAccess로 다 풀어놓고 나중에 배포할 때 세팅했던 건 안비밀입니다 😊)
- AmazonEC2ContainerRegistryFullAccess: ECR 접근
- AmazonECS_FullAccess: ECS 및 클러스터 관리
- CloudWatchFullAccess: 로그와 모니터링 데이터 관리
- RDSFullAccess: RDS 관리
- S3FullAccess: 이미지 파일 저장 및 관리
2. S3 버킷(이미지 저장용) 생성 및 설정
그다음으로는, 애플리케이션에서 사용하는 용량이 큰 이미지 파일을 저장하고 실제 RDS에서는 url 형태로 저장하기 위해서 S3 버킷을 생성했습니다.
3. 애플리케이션 컨테이너화 및 ECR 설정
그 이후, 애플리케이션을 Docker 컨테이너로 빌드하고,
자바 프로젝트의 경우 간단하게 빌드 및 푸시할 수 있는 라이브러리인 Jib 플러그인을 통해 ECR로 푸시했습니다.
그리고 AWS의 ECR 레지스트리를 생성하여, Jib 플러그인을 통해 푸시한 Docker 이미지를 저장하고,
ECR에 최신(LATEST) 이미지 파일이 업로드되면 자동으로 ECS에 정의한 태스크가 배포되도록 설정했습니다.
4. AWS RDS 및 ElasticCache(Redis) 설정
또한 팀원들과 동일한 DB를 사용하기 위해서 AWS에 RDS(MySQL) 인스턴스와 ElasticCache(Redis)를 생성했습니다.
그리고 거기에 추가로, 로컬에서도 지속적으로 ElastiCache를 확인할 수 있게 확인용 EC2를 SSL 터널용으로 열어 연결했습니다.
왜냐면, ElastiCache는 AWS의 인스턴스에서만 접근이 가능하기 때문에 로컬에서 바로 접근하면 연결이 되지 않았기 때문입니다.
5. ECS(Fargate) 설정
이후에 ECS 클러스터를 생성하여, Fargate를 사용해 서버리스 컨테이너 실행 환경을 구성했습니다.
배포하는 다양한 방식이 있지만 ECS 그리고 Fargate를 선택한 이유는
프론트엔드 배포할 때 언급한 시간이 가장 중요한 자원이었기 때문인 게 첫 번째 이유였고,
실제 유저들에게 배포되는 서비스가 아니기 때문에 사용량에 따라 비용이 결정되는 ECS의 Fargate 모드가 오히려 고정적으로 비용이 지출되는 EC2보다 비용 절감에 이득일 거라 생각한 점이 두 번째 이유였습니다.
각설하고, 태스크 정의에서 Docker 이미지를 설정하고 새 컨테이너 배포 시 무중단 배포(Blue/Green) 방식 설정하였습니다.
무중단 배포(Blue/Green) 방식이란?
기존 버전(Blue)과 새로운 버전 (Green)을 동시에 운영하여 서비스 중단 없이 배포를 진행하는 방식입니다.
마치 과거에 DB 관점에서 고가용성을 보장하기 위해서 제가 Master-Slave 아키텍처로 DB를 구성한 적이 있는데, 이와 비슷하게 서버 관점에서 고가용성을 보장하기 위한 전략입니다.
(Master-Slave 아키텍처 관련글)
https://jun10920.tistory.com/43
6. 대상 그룹 및 ALB 설정
추가로, 로드밸런싱을 위한 ALB 설정과, ALB에서 트래픽을 ECS의 컨테이너로 전달하기 위한 대상 그룹을 설정했습니다.
구현 당시에는 블로그와 AI를 통해서 로드밸런싱이라는 목적 달성을 위해 급하게 구현했는데, 추후에 직접 손으로 그려가며 학습하니 이해가 되었습니다.
위 필기를 요약하자면 아래와 같습니다.
- Route 53은 도메인 요청을 ALB로 전달.
- ALB는 트래픽을 다중 서브넷(AZ)으로 분산.
- 대상 그룹(Target Group)은 헬스 체크를 통해 정상 서버를 식별.
- 트래픽은 정상 서버로만 전달되어 안정성을 유지.
또한 SSL 인증서를 통해서 HTTPS를 활성화시켜서 사용하였습니다.
7. 오토스케일링 설정
그다음으론, 오토 스케일링을 설정하여 트래픽에 따라 컨테이너를 자동으로 확장/축소하였습니다.
스케일링 조건으론 CPU 사용률을 70%가 초과하면 컨테이너를 2개로 확장하게 설정하였습니다.
사실 꼭 필요한 설정은 아니었지만, 유레카에서 오토스케일링을 배웠으니 이를 사용해 보는 것에 의미를 두며 설정했습니다.
8. CI/CD 파이프라인 구축
이후엔 CI/CD 파이프라인 구축을 위해서 workflow 파일 작성을 했습니다.
이때 GitHub Actions를 활용해 코드를 빌드, 테스트, 배포를 진행했습니다.
name: Deploy on PR Merge to Main
on:
pull_request:
types: [closed] # PR이 닫힐 때 실행
branches:
- main # main 브랜치에 머지될 때 작동
jobs:
deploy:
if: >
(github.event_name == 'push') ||
(github.event_name == 'pull_request' && github.event.pull_request.merged == true)
runs-on: ubuntu-latest # GitHub Actions 실행 환경 설정
# 작업 디렉토리 기본값 설정
defaults:
run:
working-directory: filmeet # 'filmeet' 디렉토리에서 명령 실행
# 전역 환경 변수 설정
env:
AWS_REGION: ap-northeast-2 # AWS 리전 설정
steps:
# 1️⃣ 저장소 체크아웃
- name: 소스 코드 체크아웃
uses: actions/checkout@v3
# 2️⃣ AWS 자격 증명 설정
- name: AWS 자격 증명 구성
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} # AWS Access Key ID (GitHub Secrets에서 가져옴)
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} # AWS Secret Access Key (GitHub Secrets에서 가져옴)
aws-region: ${{ env.AWS_REGION }} # AWS 리전 설정
# 3️⃣ Java 17 설치
- name: Java 17 설정
uses: actions/setup-java@v3
with:
java-version: '17' # 사용하려는 Java 버전
distribution: 'temurin' # Java 배포판 설정
# 4️⃣ Gradle 실행 권한 부여
- name: Gradle 실행 권한 설정
run: chmod +x ./gradlew # Gradle Wrapper에 실행 권한 부여
# 5️⃣ Amazon ECR에 로그인
- name: Amazon ECR 로그인
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1 # ECR에 로그인하여 인증 토큰 획득
# 5️⃣ Docker 이미지 빌드 및 푸시
- name: Docker 이미지 빌드 및 푸시
run: ./gradlew jib --no-build-cache
env:
AWS_ECR_PASSWORD: ${{ steps.login-ecr.outputs.ecr-login-password }}
SPRING_DATASOURCE_URL: ${{ secrets.SPRING_DATASOURCE_URL }}
SPRING_DATASOURCE_USERNAME: ${{ secrets.SPRING_DATASOURCE_USERNAME }}
SPRING_DATASOURCE_PASSWORD: ${{ secrets.SPRING_DATASOURCE_PASSWORD }}
SPRING_DATA_REDIS_HOST: ${{ secrets.SPRING_DATA_REDIS_HOST }}
SPRING_DATA_REDIS_PORT: ${{ secrets.SPRING_DATA_REDIS_PORT }}
SPRING_CLOUD_AWS_S3_BUCKET: ${{ secrets.SPRING_CLOUD_AWS_S3_BUCKET }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_ID: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_ID }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_SECRET: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_GOOGLE_CLIENT_SECRET }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_ID: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_ID }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_SECRET: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_KAKAO_CLIENT_SECRET }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAVER_CLIENT_ID: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAVER_CLIENT_ID }}
SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAVER_CLIENT_SECRET: ${{ secrets.SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_NAVER_CLIENT_SECRET }}
KOBIS_APIKEY: ${{ secrets.KOBIS_APIKEY }}
KMDB_APIKEY: ${{ secrets.KMDB_APIKEY }}
OMDB_APIKEY: ${{ secrets.OMDB_APIKEY }}
FIREBASE_CONFIG: ${{ secrets.FIREBASE_CONFIG }}
JWT_SECRET: ${{ secrets.JWT_SECRET }}
JWT_VALIDITY_ACCESS: ${{ secrets.JWT_VALIDITY_ACCESS }}
JWT_VALIDITY_REFRESH: ${{ secrets.JWT_VALIDITY_REFRESH }}
FRONT_REDIRECT_URL: ${{ secrets.FRONT_REDIRECT_URL }}
# 6️⃣ ECS 서비스 업데이트
- name: ECS 서비스 업데이트
run: |
aws ecs update-service \
--cluster filmeet-cluster \
--service filmeet-service \
--force-new-deployment \
--deployment-configuration maximumPercent=200,minimumHealthyPercent=75 \
--health-check-grace-period 300
workflow 파일은 구체적으로 설명하자면,
(1) 이벤트 트리거 설정
- on: pull_request: PR(Pull Request)이 닫히고 main 브랜치에 병합되었을 때 워크플로우가 실행
(2) AWS 자격 증명 구성
- AWS 서비스와 상호작용하기 위해 aws-actions/configure-aws-credentials를 사용하여 AWS Access Key와 Secret Key를 설정
- 리전은 ap-northeast-2 (서울 리전)으로 설정하여 지연 시간을 최소화
(3) Java 17 및 Gradle 설정
- Java 17: 애플리케이션은 최신 Java LTS 버전인 Java 17을 기반으로 작성
actions/setup-java를 통해 실행 환경에 필요한 Java 버전을 설치 - Gradle Wrapper 권한 부여: Gradle 명령 실행을 위한 권한을 추가하여 워크플로우가 원활히 진행되도록 설정
(4) Docker 이미지 빌드 및 푸시
- Amazon ECR: Docker 이미지를 Amazon ECR에 업로드해 ECS에서 사용할 수 있도록 설정
- Gradle Jib 플러그인: ./gradlew jib 명령을 사용해 Docker 이미지를 빌드
- 환경 변수(Secrets)를 활용하여 민감한 정보를 안전하게 관리
(5) ECS 서비스 업데이트
- force-new-deployment: 기존 컨테이너를 교체하여 새 이미지로 배포
- maximumPercent=200, minimumHealthyPercent=75: 배포 중 최소 75%의 컨테이너가 가용 상태를 유지하도록 설정
- health-check-grace-period=300: 새로운 컨테이너가 시작된 후 5분간 상태를 확인할 유예 시간 설정
초반에 헬스 체크를 할 유예 시간을 너무 짧게 줬더니, 계속 배포 실패가 나와서 정말 한참을 배포했던 것 같습니다...
결론적으로 수많은 설정 변경과 노가다를 하였지만,
단순히 5분간 상태를 확인하는 설정 하나만 하였더니 멀쩡하게 배포를 성공하였습니다.
9. 모니터링을 위한 CloudWatch 설정
마지막으로 CloudWatch에 배포한 ECS 서비스의 로그를 전송하여 실시간을 애플리케이션 상태를 확인하도록 설정했습니다.
성과
결론적으로, 위와 같은 과정을 통해서 세 가지 성과를 얻었습니다.
- 무중단 배포: Blue/Green 방식과 ALB를 통해 사용자에게 끊김 없는 서비스 제공
- 트래픽 최적화: 오토스케일링과 ALB로 성능과 비용을 모두 최적화
- 자동화와 안정성 강화: GitHub Actions와 CloudWatch로 CI/CD와 모니터링이 완벽히 통합
배포 환경과 테스트 환경을 분리
마지막으로, 성능테스트를 위해서 배포 환경과 테스트 환경을 분리했습니다. 자세한 내용은 아래 글을 참고해 주시면 감사하겠습니다.
https://jun10920.tistory.com/48
이때 docker를 통해서 쉽게 pinpoint를 설정하려고 했지만, 오히려 정확하게 docker를 이해하지 못한 채 디버깅을 하려 하니 계속 먼 길을 돌아가는 기분이었습니다.
그래서 그냥 ec2 인스턴스에 pinpoint web, collector, hbase 등등을 직접 다운로드하여 세팅하였더니 훨씬 빠르게 세팅을 완료했던 경험이 있습니다.
역시 제대로 이해하지 않고 사용하면, 에러가 발생했을 때 대응을 못하는 경우가 생겨 오히려 비효율적인 경우가 있는 것 같습니다.
마무리하며
이번 Filmeet 프로젝트를 통해 단순히 기술을 사용하는 것을 넘어 서비스를 운영하는 데 필요한 인프라 구축과 DevOps의 중요성을 몸소 경험할 수 있었습니다. 특히, AWS의 다양한 서비스를 활용하면서 클라우드 기반의 아키텍처 설계와 CI/CD 파이프라인 구축이 얼마나 서비스의 생산성을 높이는지 깨달았습니다.
배운 점
- DevOps와 협업의 중요성:
- 개발과 운영이 긴밀히 연결된 DevOps 문화를 실천하면서, 팀원들과의 협업이 얼마나 중요한지 실감했습니다.
- CI/CD 파이프라인을 통해 인당 배포 시간을 1시간 -> 5분 내로 줄이면서 얼마나 효율적인지 체감했습니다.
- 기술 이해의 깊이:
- 처음에는 "작동하는 것"에 초점을 두었지만, 시간이 지날수록 "왜 그렇게 작동하는지"를 이해하는 것이 중요하다는 것을 깨달았습니다.
- 특히 디버깅을 하는 과정에서 이해하지 못하고 사용한 대가를 톡톡히 치렀습니다.
- 물론 시간이 여유롭지 못한 상황에서 어쩔 수 없는 선택이라고 생각하지만, 조금이라도 여유를 가질 수 있다면 확실하게 이해를 하고 사용을 하는 것을 목표로 하려고 합니다.
- 처음에는 "작동하는 것"에 초점을 두었지만, 시간이 지날수록 "왜 그렇게 작동하는지"를 이해하는 것이 중요하다는 것을 깨달았습니다.
- 실수로부터의 학습:
- 잘못된 설정으로 인해 수차례 배포가 실패했지만, 이 과정에서 문제를 진단하고 해결하는 능력을 키울 수 있었습니다.
- "실수는 성장의 기회"라는 말이 얼마나 사실인지 다시 한번 느꼈습니다.
아쉬운 점
- 짧은 프로젝트 기간 동안 많은 것을 구현하려다 보니, 기술의 깊이 있는 학습보다는 "작동하게 만드는 것"에 초점이 맞춰졌습니다.
- 프론트엔드 CI/CD 구축 과정에서 Amplify를 선택하며 시간은 절약했지만, S3와 CloudFront를 직접 설정하는 경험을 놓친 점은 조금 아쉽습니다.
앞으로의 계획
- 프로젝트를 통해 경험한 AWS 서비스와 DevOps 프로세스를 더 깊이 학습하고, 배운 내용을 정리하여 다른 사람들에게도 공유하고 싶습니다.
- 이후 프로젝트에서는 기능 구현을 넘어, 코드 품질과 아키텍처의 최적화까지 신경 쓰는 개발자로 성장하고 싶습니다.
Filmeet 프로젝트를 함께한 팀원들에게도 감사의 마음을 전하고 싶습니다.
각자의 역할을 충실히 해낸 덕분에 프로젝트를 성공적으로 마무리할 수 있었습니다.
프로젝트를 진행하며 수많은 도전과 장애물을 만났지만, 그 모든 과정이 성장과 배움의 계기가 되었습니다.
이 글을 통해 AWS 서비스와 DevOps를 처음 접하거나 CI/CD 파이프라인을 구축하는 분들에게 참고 자료가 되었으면 합니다. 제가 겪었던 어려움과 해결 과정이 다른 분들에게 도움이 되길 바랍니다. 😊