들어가는 글

안녕하세요 최근 정말 좋은 일이 있었는데요 백엔드 포지션으로 가비아에 합류하게 됐습니다.
이번글은 합류의 과정과 제 개인적인 생각을 작성하려 합니다.

서비스 회사에 가고싶다

블로그에 따로 포스팅하거나, 이력서에 기재하지는 않았지만 SI 회사에서 인턴근무를 한 경험이 있습니다.
SI의 특성상 프로젝트의 생명주기가 짧으며 기한을 맞추는것이 핵심이기 때문에 일을 배우면서 성장하기에는 어려운 환경으로 느껴졌습니다.

생각했던것 보다 성장에 대한 욕심이 크다는걸 알게됐고 "나는 무조건 서비스회사에 가야겠구나" 다짐했던 기억이납니다.
이력서또한 SI/SM 서비스를 주로하는 기업에는 작성하지 않았으며 흥미를 느끼고 성장할 수 있겠다 생각되는 기업의 공고에만 작성했습니다.

작년에는 광탈 올해는 합격

가비아에는 작년 겨울에도 이력서를 접수했었는데요 서류에서 바로 탈락했던 기억이 납니다.
이때는 이력서를 작성하는 방법과 직무적합성을 나타내는 방법에 대한 이해가 많이 부족했습니다.

이력서란 기본적으로 나 자신을 세일즈 하는 것인데 그런 부분들이 들어나지 않았거든요
다만 표현의 방법을 바꾸고 강조하고 싶은 부분만을 보여줌으로써 다른 결과를 만든 것 같습니다.

동일한 프로젝트를 설명하는 이력서

첫 출근 후 느낀점

서로가 서로를 존중한다는 느낌을 받았습니다.
이 느낌이 굉장히 중요하다 생각하는데요, "돈 받으니까 일해야지" 당연히 맞는 말이지만 좋은 방식은 아니라 생각합니다.

"나의 일이 아닌 남의 일을 돈받았으니까 해준다" 라는 인식이 생기는 순간 동기부여가 되지 않습니다.
회사는 내것이 아니고 회사에서 처리하는 일또한 회사의 일이지만 마치 나의 일인것 처럼 생각하게 만드는 것이 좋은 회사의 덕목이라 생각하거든요

저는 자취를하며 월세를 살고있는데요, 이 집은 제 것이 아니기 때문에 방치하고 더럽게 살아도 아무런 문제가 없습니다.
하지만 대부분의 사람들이 마치 "나의 집" 처럼 청소도하고 꾸미기도 하며 내가 속해있는 환경을 나의 마음에 맞게끔 가꾸고 아껴주려고 노력합니다.

회사의 일도 비슷한 것 같습니다.
평생직장은 무의미해졌고 회사는 나의 소유가 아니지만, 그 울타리 안에서 일을 하는 동안에는 서로를 존중하며 열심히 일하는것이 서로에게 좋은 것 아닐까요?

많이 물어보시는 질문 - 개발자도 어학성적, 자격증 필요한가요?

서비스 회사는 없어도 되는 것 같습니다만, 보다 전통적인 산업의 기업 혹은 SI/SM 을 주로하는 경우에는 필요합니다.
개인적으로는 정보처리기사 정도만 필수로 취득하시면 될 것 같습니다.

마무리하며

제 블로그를 방문해주시는 대부분의 분들은 개발자 직무를 희망하거나 취업을 준비중이신 대학생 분들이 많은 것 같습니다.
특히나 NHN Academy , Univ 의 지원 시즌이 되면 조회수가 폭발적으로 나오는데 상당히 기쁩니다.

누군가에게 도움이 된다는 사실이 참 좋은 것 같아요, 감사합니다.

 

조금 늦은 2024년 회고

설 전까지는 2025 BETA 버전이기 때문에 정식 릴리즈된 지금 시점에 회고를 작성합니다.
2024년은 아쉬운 부분도, 만족하는 부분도 공존하지만 나름의 성과를 이뤄냈던 시간인 것 같습니다.

2024, 개발자스러운 것들

2024년은 새로운 도전의 연속이었습니다.

NHN Academy 프로젝트 과정 수료후 개발에 대해 자신감이 생겼고, 이를 토대로 어떤 활동이든 도전해보자! 라는 목표가 생기게 됐습니다.
특히나 개발자스러운 것에 굉장히 많은 도전을 했습니다.

 

2024년 , 성장을 만든 IT 활동 | Notion

SIPE 3기

sprinkle-place-c1a.notion.site


처음으로 컨퍼런스도 참석해 내심 부러웠던 스티커도 받아서 붙여보고… 해커톤을 수상하고, 발표도 하고, 오픈소스에 기여하는 등
좋은 개발자란 무엇이고 어떻게 하는 것이 가파른 성장을 이끌 수 있는진 모르겠으나 그냥 개발자스러운 것을 하면 그게 좋은 개발자 아닌가?라는 생각으로 달려온 것 같습니다.

한마디로 2024년은 개발자스러워지기 위한 과정이었습니다. 개발에 대해 아무것도 몰랐기 때문에, 역설적으로 정말 가파르게 성장할 수 있었습니다.

2025, 새로운 키워드 ‘꾸준함’

2025년은 뛰어난 개발자가 되는 과정이고 싶습니다. 개발자스러운 사람 말고… 그냥 뛰어난 개발자 말이죠.
그러기 위해서 가장 필요한 것은 꾸준함인 것 같습니다.

개인적으로 단기간에 몰입하고 성과를 내는것은 잘하지만 꾸준하게 이어나가는 뒷심은 부족하다 생각합니다.

깃허브 내역만 봐도.. 커밋을 많이 한 기간과 하지 않는 기간이 확연히 차이 나는 것처럼요

그래서 나름의 규칙을 세웠습니다.

  1. 1일 1커밋
  2. 1일 1산책
  3. 2주 1포스팅
  4. 1달 1강의
  5. 1달 1독서

이 규칙들을 잘 지키는지는 계속해서 기록해 나가겠습니다.

마무리하며

처음 블로그를 시작했을 때 아무도 봐주지 않아 친구들한테 링크를 보내면서 겨우겨우 조회수를 올렸던 기억이 납니다.

지금은 친구들이 방문해주지 않아도 꽤나 많은 분들이 방문해 주시는 것 같습니다.
어쩌면 첫 번째 꾸준함은 블로그였나 봅니다.

내가 작성하는 글들이 누군가에게 정보가되고 경험을 공유할 수 있다는 것이 정말 큰 힘이 됩니다.
모두 행복하세요

GPT 요약

My-Music-Note 프로젝트에서 AWS 기반 고가용성 아키텍처를 설계하고, Auto Scaling Group, Application Load Balancer, CodeDeploy를 활용해 검증을 진행했습니다.
성능 테스트 도구로 JMeter를 시도했으나 자원 소모와 불필요한 기능으로 Artillery로 전환하여 소규모 부하 테스트를 성공적으로 수행했습니다.
테스트 결과, 단일 EC2 환경에서는 부하 증가로 많은 실패가 발생했지만, My-Music-Note 아키텍처에서는 100% 성공과 낮은 레이턴시를 보여 고가용성을 입증했습니다.

My-Music-Note 프로젝트에서의 경험을 다룬 글입니다.

My-Music-Note 프로젝트에서 유일한 백엔드 개발자로서 AWS 기반 인프라 구축에 집중하였습니다.
이번 글에서는 제가 구현한 AWS 기반 고가용성 아키텍처를 검증하고 테스트한 과정을 공유하려 합니다.

고가용성 아키텍처 설계

이전 포스팅에서 고가용성 아키텍처를 설계할 때 고려했던 3가지 기준을 소개했습니다.

https://masiljangajji-coding.tistory.com/88

이 기준을 바탕으로 Auto Scaling Group(ASG), Application Load Balancer(ALB), 그리고 CodeDeploy를 사용하여 인프라를 구축했습니다. 그러나 설계하고 배포하는 것만으로 고가용성이 보장된다고 할 수는 없습니다.

따라서 실제로 고가용성을 충족하는지 검증이 필요했고 이를 위해 성능 테스트를 진행하기로 했습니다.

성능 테스트 툴 선택 - JMeter에서 Artillery로 전환

JMeter의 도입과 한계

처음에는 널리 알려진 성능 테스트 툴인 JMeter를 선택했습니다.
JMeter는 실무에서도 많이 사용되는 도구로 자바 개발자들 사이에서는 표준이 되는 툴이라 생각했기 때문입니다.

하지만 실제로 사용해보니 우리 서비스에는 적합하지 않다 판단했습니다.

  1. 무거운 자원소모
    • JMeter는 JVM 기반 특성상 상당한 메모리를 소모
  2. 대규모 부하 테스트의 불필요성
    • 테스트 환경의 EC2 인스턴스(t4g.nano)는 고성능 서버가 아니었기에 JMeter의 장점인 대규모 부하 테스트 또한 불필요
  3. 결과 시각화가 제한적
    • 분석이 필요한 경우 별도로 CSV를 내보내서 분석해야 함

켜놓기만해도 RAM을 엄청 잡아먹는다..

Artillery로의 전환

따라서.. 보다 가볍고 소규모 테스트에 적합한 대안을 찾아봤으며 최종적으로는 Artillery로 전환하게 됐습니다.

Artillery는 소규모 부하 테스트에 적합하며 자원 소모가 적은 경량 툴입니다. YAML 파일로 테스트 작성이 가능한데 이는 Spring Boot 프로젝트에서 properties를 관리할 때 사용하던 방식과 유사해 익숙하게 느껴졌습니다.

Locust와 K6 같은 다른 경량 테스트 툴도 검토했지만 각각 Python과 JavaScript로 테스트 스크립트를 작성해야 한다는 점에서 Artillery를 선택했습니다.

테스트 환경과 시나리오 설정

테스트 환경

테스트는 다음과 같은 AWS 리소스를 기반으로 진행되었습니다

  • EC2 : t4g.nano
  • RDS : db.t4g.micro

테스트 시나리오

사용자가 인덱스 페이지 방문 후 로그인하는 시나리오를 작성했으며 트래픽 부하에 따라 Auto Scaling Group과 Application Load Balancer가 요청을 적절히 분산시키는지를 확인하기 위해 5분간 점진적으로 요청을 증가시킨 후 1분간 유지하도록 설정했습니다.

동일한 시나리오에 대해서 target만 EC2 , ALB로 변경해 테스트

테스트 결과

단일 EC2 환경에서 테스트를 수행한 결과는 다음과 같았습니다.

Artillery Metric
요청이 증가함에 따라 time out 발생
AWS Metric , 요청이 증가함에 따라 Network I/O 증가

타임아웃 오류 : 전체 요청의 37.6%(14,766건)
작업 실패율 : 가상 사용자의 54.7%(14,766명)

시간이 갈수록 늘어나는 요청에 따라 부하가 걸리는 것을 볼 수 있습니다.

My-Music-Note 아키텍처에서의 결과

ASG, ALB, CodeDeploy로 구성된 My-Music-Note의 고가용성 아키텍처에서는 다음과 같은 결과를 얻었습니다.

Artillery Metric
99% 요청에 대해 레이턴시 25.8ms
AWS Metric , ASG에 의해 트래픽이 분산돼 Network I/O 하락

타임아웃 오류: 0%
작업 실패율: 0%
99% 요청에 대해 레이턴시 25.8ms

이 결과는 My-Music-Note 아키텍처가 실제로 고가용성 기준을 충족하고 있음을 입증했습니다.

마무리

이번 성능 테스트는 고가용성 아키텍처를 검증하는 데 성공적이었지만 매우 간단한 시나리오에 대해서만 테스트해 API 레벨에서의 병목은 확인할 수 없었습니다.

이 부분에 대해서 개선할 여지가 남아있으며 앞으로도 지속적으로 배움과 개선을 이어나가겠습니다.

같이 보시면 좋은 발표 영상입니다.

 

GPT 요약

My-Music-Note 프로젝트에서 SonarCloud와 GitHub Actions 같은 SaaS 도구를 활용해 서비스 비용을 절감했습니다.
Bastion Host 대신 AWS Systems Manager를 도입해 보안을 강화하고 네트워크 비용을 줄였습니다.
이러한 선택으로 비용 효율성과 운영 효율성을 모두 확보할 수 있었습니다.

My-Music-Note 프로젝트에서의 경험을 다룬 글입니다.


이전 프로젝트들은 교육기관이나 회사에서 제공한 환경에서 진행되었기 때문에 서버 비용 같은 것은 크게 신경 쓰지 않았습니다.

그러나 이번 프로젝트는 직접적으로 돈이 나가는 상황이었기 때문에 자연스럽게 비용을 줄이면서도 효율성을 높이는 방법에 대해 고민하게 되었습니다.

서비스 비용 절감 - SonarCloud와 GitHub Actions 선택

My-Music-Note 이전에 진행했던 My-Books 프로젝트에서는 SonarQube로 코드 품질을 관리하고 CI/CD 도구로는 Jenkins를 사용했습니다.
My-Books는 NHN Academy에서 진행한 것으로 인프라 관리비용을 NHN측에서 전액 부담해주었기 때문에 비용 고민이 없었습니다.

하지만 이번 프로젝트는 제 돈으로 운영해야 했기 때문에 별도의 서버 관리가 필요하지 않은 도구를 찾아야 했으며
결과적으로 SonarCloudGitHub Actions라는 SaaS 기반 도구를 선택하게 되었습니다.

SonarCloud - SaaS형 코드 품질 관리 도구

SonarCloud는 SaaS(Software as a Service)로 제공되며 SonarQube처럼 별도의 서버를 설치하거나 관리할 필요가 없습니다.GitHub 공개 저장소에 한해서 전체 기능을 무료로 제공받을 수 있어 규모가 작은 스타트업이나 팀 프로젝트의 경우에는 매우 적합하다 생각합니다.

물론 SonarQube에 비해 부족한 부분도 존재합니다.

  • 제한된 언어 지원 언어지원과(C,Objective-C,PL/SQL...)
  • 타사 플러그인의 부재
  • 모노레포등 복잡한 프로젝트 구조에 대한 지원 부족

다행히 My-Music-Note 서비스는는 이러한 제약 조건과 관련이 적었기 때문에 SonarCloud를 사용하는 데 만족했습니다.

SonarCloud Review

GitHub Actions - 클라우드 기반 CI/CD

GitHub Actions도 SaaS로 제공되며 SonarCloud와 동일하게 GitHub 공개 저장소에 한해서 무료로 사용할 수 있습니다.

Jenkins와 달리 서버 비용이 필요하지 않으며 GitHub Actions Marketplace 활용시 AWS, Google Cloud , Docker 등 다양한 Actions를 쉽게 추가하여 CI/CD 파이프라인을 확장할 수 있습니다.

개인적으로는 이 부분이 매우 강력하다고 느꼈으며 Jenkins와 비교해도 기능이 제한적일 것 같다는 생각은 들지 않았습니다.

특히나 국내 빅테크에서도 GitHub Actions를 사용하는 사례가 있는만큼 대규모 조직에서도 충분히 활용 가능해보입니다.

네트워크 비용 절감 - Bastion Host에서 Systems Manager로 전환

AWS 기반 인프라에서는 프라이빗 서브넷의 EC2 인스턴스에 접근하는 방법 또한 비용 절감 요소중 하나 입니다.
기존에는 Bastion Host를 사용했지만 이 방식에는 몇 가지 한계가 있었습니다.

Bastion Host - 작동 방식과 한계

Bastion Host는 퍼블릭 서브넷에 배치된 EC2 인스턴스로 외부에서 접근 가능한 경로를 제공합니다.
이를 통해 프라이빗 서브넷의 EC2 인스턴스에 접근할 수 있지만 다음과 같은 문제점이 발생합니다.

  1. 보안 취약점:
    • Bastion Host는 외부 인터넷에 노출되어 보안 위협이 존재
  2. PEM 키 관리의 복잡성:
    • 여러 프라이빗 인스턴스의 PEM 키를 Bastion Host에 복사하고 관리해야 함
  3. 추가 비용 발생:
    • Bastion Host 자체가 EC2 인스턴스이기 때문에 유지비용이 발생

Bastion Host 목적의 추가적인 EC2 자원 필요

Systems Manager - 더 안전하고 효율적인 네트워크 접근 방식

이러한 문제를 해결하기 위해 AWS Systems Manager를 도입했습니다.

Systems Manager는 AWS 내부 네트워크를 활용하기 때문에 인터넷 연결 없이도 EC2 인스턴스에 안전하게 접근할 수 있으며
PEM 키를 관리하지 않아도 되는 편리함 , Bastion Host와 같은 EC2 인스턴스를 유지할 필요가 없어 비용이 절감되는 등 다양한 장점이 존재합니다.

실제로 사용해보니 일반적인 터미널 환경과 유사했으며 기존 Bastion Host 방식보다 간편하고 효율적이였습니다.

SSM을 이용한 Private Subnet EC2 접속

My-Music-Note 프로젝트에서 SaaS 기반 도구(SonarCloud, GitHub Actions)와 Systems Manager를 도입한 결과 서비스 비용과 네트워크 비용을 모두 절감할 수 있었습니다.

같이 보시면 좋은 발표 영상입니다.

GPT 요약

My-Music-Note 프로젝트에서 AWS 기반 인프라를 구축하며 고가용성 아키텍처를 설계하고, ASG와 ALB로 트래픽 분산을 구현했습니다.
CodeDeploy와 Docker를 결합해 배포 프로세스를 자동화했으며, Docker 이미지를 활용한 컨테이너 기반 환경으로 전환하여 개발 생산성과 효율성을 높였습니다.
이 경험을 바탕으로 SAA 자격증을 취득하며 AWS와 컨테이너 기술에 대한 깊은 이해를 확립했습니다.

My-Music-Note 프로젝트에서의 경험을 다룬 글입니다.

My-Music-Note 프로젝트에서 유일한 백엔드 개발자로서 AWS 기반 인프라 구축에 집중하였습니다.
처음 AWS를 사용하며 겪었던 어려움과 SAA(Solutions Architect Associate) 자격증 취득, 실제 운영 환경에서의 개선 과정을 공유하고자 합니다.

AWS 첫 경험과 비용 관리

이전에 진행한 My-Books 프로젝트에서는 주로 API 기능 구현과 인증/인가 프로세스 구축을 담당했기 때문에인프라 설계 및 구현 경험은 부족했습니다. 따라서.. My-Music-Note 프로젝트에서는 이러한 부분을 보완하고자 AWS를 활용하여 인프라를 구축하였습니다.

AWS 프리 티어(Free Tier)를 활용할 수도 있었지만 실제 과금 모델을 경험하는 것이 중요하다고 판단하여 유료 서비스를 사용했습니다.
실제로 주머니에서 돈이 빠져나가는 경험을 하니 어떻게하면 비용을 줄일 수 있을까? 고민 하게 됐으며
NAT 게이트웨이, 퍼블릭 IP, ALB(Application Load Balancer) 등의 예상치 못한 비용에 대해서도 학습할 수 있었습니다. 

새로운 목표 - 고가용성 아키텍처 구축

프로젝트를 시작할때 목표로 잡은것은 고가용성 아키텍처를 구축하는 것이었습니다.
고가용성은 서비스가 지속적이고 안정적으로 운영될 수 있는 능력을 의미하며 이는 모던 아키텍처에서 필수적인 요소라 생각합니다.

따라서 다음의 기준을 세우게 됩니다.

  1. 트래픽을 자동으로 분산시킬 수 있을 것
  2. 장애 감지 시 새로운 리소스를 자동으로 생성하고 교체할 것
  3. 무중단 배포가 가능할 것

트래픽 분산 - ASG와 ALB

트래픽 분산을 위해 AWS의 ELB(Elastic Load Balancer)를 조사하면서 공식 문서를 참고해 ASG(Auto Scaling Group)와 연계하여 사용하는 방법을 학습했습니다.

Elastic Load Balancing 로드 밸런서를 Auto Scaling 그룹에 연결 - Amazon EC2 Auto Scaling
이 문서를 통해 ASG와 ELB의 연계로 트래픽을 효율적으로 처리하는 방법을 이해할 수 있었습니다.

ASG와 ELB를 연계해 사용하는 이유는 간단합니다. ASG를 통해 새로운 인스턴스를 생성하더라도 요청이 해당 인스턴스로 분배되지 않으면 무용지물이기 때문입니다.

ASG는 트래픽 증가나 장애 발생 시 인스턴스 수를 동적으로 조절하여 확장성가용성을 높여줍니다. 또한, 대상 추정 정책(Target Tracking Policy)을 사용하면 CPU 사용률과 같은 지표를 기반으로 자동 조정이 가능합니다.

ASG(Auto Scaling Group)

ELB는 생성된 인스턴스로 트래픽을 효율적으로 분배하며, 이를 통해 트래픽 부하 분산과 확장 작업이 자동화됩니다.

ELB에는 ALB(Application Load Balancer)와 NLB(Network Load Balancer)가 존재하지만 My-Music-Note는 REST API 기반의 웹 애플리케이션이므로 HTTP/HTTPS 트래픽 처리를 지원하는 ALB를 사용했습니다.

무중단 배포와 자동화 - CodeDeploy의 도입

트래픽을 분산시키고 ASG로 새로운 리소스(EC2 Instance)를 생성했지만 한 가지 문제가 있었습니다.
"배포는 어떻게 하지?"라는 고민이 생긴 것이죠.

기존의 ASG와 ALB 스택에 연계할 수 있는 배포 도구를 조사하던 중 AWS의 CodeDeploy를 도입하게 되었습니다.

EC2/온프레미스 컴퓨팅 플랫폼의 배포 - AWS CodeDeploy
CodeDeploy를 통해 무중단 배포와 자동화된 배포 프로세스를 설정할 수 있었습니다.

CodeDeploy를 활용하려면 S3에 업로드된 아티팩트AppSpec 파일이 필요합니다.
이를 위해 초기에는 소스 코드와 Gradle 빌드 산출물(JAR), 설정 파일, 배포 스크립트를 모두 압축하여 S3에 업로드하는 방식을 사용했습니다.

초기 배포 프로세스

하지만.. 배포 과정에서 새로운 EC2 인스턴스가 프로비저닝되었지만 애플리케이션이 설치되지 않는 문제가 발생했습니다.
이는 CodeDeploy 에이전트가 EC2 인스턴스에 설치되어 있지 않아서 발생한 문제였습니다.

이를 해결하기 위해 EC2 템플릿의 사용자 데이터(User Data)를 활용했습니다. 사용자 데이터는 EC2 인스턴스가 처음 시작될 때 실행되므로, CodeDeploy 에이전트를 자동으로 설치하고 배포 프로세스를 완성할 수 있었습니다.

배포 완료


문제점 - 비효율적인 zip파일 & 환경 구성의 어려움

그러나 또 다른 문제가 있었습니다. 프론트엔드 개발자가 백엔드 개발 환경을 구성하는 과정이 복잡했습니다.
AWS에 로그인해서, S3에 접근해서, zip파일 다운받고 jar실행시키고.. JRE도 있어야하고.. 이는 많은 번거로움을 주었습니다.

또한 S3에 필요한 소스코드,빌드결과물 등을 담은 zip파일이 배포마다 생기는 것 또한 비효율적으로 느껴졌습니다.

컨테이너 기반 환경으로의 전환

이 문제를 해결하기 위해 Container 기반 애플리케이션으로 마이그레이션하기로 했습니다.
컨테이너화를 위해 Docker를 사용하고, EC2 인스턴스에는 Docker가 설치된 상태로 프로비저닝되도록 설정했습니다.

CodeDeploy 에이전트의 경우 크기가 크지 않았기 때문에 사용자 데이터를 기반으로 설치했지만 모든 배포마다 Docker 설치를 반복하는 방식은 부담스럽게 느껴졌기 때문에 CodeDeploy와 Docker를 설치한 AMI를 만들어 사용해주었습니다.


배포 프로세스또한 개선했습니다.

  • S3에 zip 파일을 업로드하던 방식 -> Docker 이미지를 Docker Hub에 올리고 EC2 인스턴스에서 이를 실행
  • AppSpec.yml과 스크립트를 포함한 deployment.zip 파일을 미리 준비해 배포 과정에서 재활용

이 과정을 통해 프론트엔드 개발자는 단순히 Docker와 PostMan을 활용해 백엔드 환경을 손쉽게 구성할 수 있게 되었으며
배포마다 생성됐던 zip파일을 최소화 할 수 있었습니다.

프로젝트 당시 Notion 문서

완성된 아키텍처와 SAA 자격증 취득

완성된 아키텍처는 다음과 같습니다.

  • ASG와 ALB를 활용한 트래픽 분산
  • CodeDeploy와 Docker를 결합한 효율적인 배포 프로세스
  • NAT Gateway를 통한 Private Subnet의 네트워크 연결

My-Music-Note 프로젝트는 익숙하지 않았던 AWS와 컨테이너 기술에 몰입할 수 있었던 프로젝트였습니다.
또한 배운 것을 검증하고 더욱 Deep Dive하기위해 AWS Certified Solutions Architect - Associate 자격증 취득했으며
백엔드 개발자로서 역량을 키울 수 있었습니다.

AWS Solutions Architect Associate(SAA)합격 후기


같이 보시면 좋은 발표 영상입니다.

 

GPT 요약

My-Books 프로젝트에서 로그인 절차를 설계하며, 평문 비밀번호 전송 문제를 해결하기 위해 고민했습니다.
기존에 Back Server에서 비밀번호를 암호화하던 방식을 Front Server에서 해싱 후 전달하는 방식으로 변경해 보안성을 강화했습니다.
로그인 요청은 호출 빈도가 낮아 추가적인 서버 호출 비용보다 보안성을 우선시하는 선택이 이루어졌습니다.

My-Books 프로젝트에서의 경험을 다룬 글입니다.

My-Books 프로젝트에서 제가 맡은 역할은 인증/인가 프로세스를 설계하고 구현하는 것이었습니다.
특히 로그인 절차(인증)를 구현하면서 가장 큰 고민은 평문과 비문의 사용과 이를 어떻게 안전하게 처리할 것인가에 대한 것이었습니다.
이번 글에서는 이러한 고민의 과정과 최종적으로 내린 선택에 대해 공유하려 합니다.

BCrypt를 어디에 사용할 것인가?

로그인 설계에서 가장 중요한 고민 중 하나는 BCrypt를 어디에서 사용할 것인가 하는 점이었습니다.

초기 설계

초기에는 프론트에서 평문 비밀번호를 받아 이를 백으로 넘긴 후 BCrypt로 암호화하고, 데이터베이스와 비교해 검증하는 방식으로 설계했습니다.
이는 일반적으로 많이 사용하는 방법으로, 간단하고 직관적이라는 장점이 있었습니다.

최종 설계

하지만 최종적으로는 프론트에서 사용자가 입력한 이메일을 백으로 전달해 검증하고 DB에 저장돼있는 비문과 입력한 비밀번호를 BCrypt를 통해 검증한 뒤 로그인 절차를 완료하는 방법을 선택했습니다.
이로 인해 로그인 절차는 다소 복잡해졌고, 백서버 호출도 기존 1번에서 2번으로 증가하게 되었습니다.

BCrypt를 사용하기 위한 Dependency 변경

왜 변경했을까?

이건 정말 단순한 이유인데요, 저는 평문 비밀번호가 통신 과정에서 평문으로 전송되는 것 자체가 너무 찝찝했습니다.
물론 HTTPS를 사용하면 암호화된 통신을 보장할 수 있지만 비밀번호 같은 민감한 데이터는 단 한 번이라도 평문으로 노출될 가능성을 없애는 게 중요하다고 생각했습니다.

또한 로그인 요청은 사용자가 자주 호출하지 않는 기능입니다.
대부분 사용자가 서비스를 시작하거나, 토큰이 만료된 후 로그인을 수행하기 때문에 호출 빈도가 비교적 낮습니다.
따라서 로그인 절차에서 발생하는 추가적인 서버 호출 비용은 최소화된 부담이라고 판단했습니다.

비용 최적화를 추구할 수도 있었지만, 보안성을 강화하는 선택이 사용자의 민감한 정보를 다루는 인증 시스템의목표와 일치한다고 결론 내렸습니다

BCrypt 값 검증 방식 

또한 다음과 같은 질문도 받게 되었는데요 
Q: 프론트,백 둘 다 BCrypt를 사용하고 프론트에서 암호화 한 후 전송한다음에 백에서 확인하면 한번으로 처리가능한거 아니에요? 

A: BCrypt를 이용해 값의 일치를 확인하려면 평문하나와 비문 하나가 필요해서 안될것 같아요 

이 것을 이해하려면 BCrypt의 동작 구조를 알아야 하는데요 BCrypt는 단방향 해쉬 알고리즘으로 한번 암호화하면 본문을 알 수 없게됩니다. 
그런데... 원문을 알 수 없는데 어떻게 입력한 비밀번호와 DB의 암호화된 비밀번호가 같다는 것을 알 수 있을까요??

정답은 간단하게도 다시 암호화를 시킨후 비교합니다.

Bcrypt는 내부적으로 Salt(임의의 값)를 생성하여 평문 비밀번호와 함께 해싱 알고리즘을 적용합니다.
생성된 Salt는 해싱 결과(비문)에 포함되며, 검증 시 동일한 Salt를 추출해 평문 비밀번호와 함께 다시 해싱합니다.
이렇게 생성된 비문이 기존 비문과 같다면, 암호화되기 전의 평문이 동일했음을 확인할 수 있습니다.

따라서.. 들어온 평문과 암호화된 비문이 같음을 알기 위해서는 무조건 평문 하나와 비문 하나가 필요하기 때문에 
백서버에서 비문 비밀번호를 응답으로 받은 후 프론트에서 들어온 평문을 이용해 검증하는 방식을 사용해야 합니다.

My-Books 로그인 절차

최종적으로 설계된 My-Books 로그인 절차는 다음과 같은 흐름으로 진행됩니다.

  1. 이메일과 비밀번호 입력
    • 사용자가 이메일과 비밀번호를 입력하여 로그인을 시도합니다. 이 정보는 Front Server를 통해 Gateway Server로 전달
  2. 이메일 인증 요청
    • Gateway Server는 Back Server로 이메일 인증 요청을 전송
    • 이메일 인증 실패 시: 로그인 절차가 중단되고, 인증 실패 응답이 반환
    • 이메일 인증 성공 시: Back Server는 암호화된 비밀번호(BCrypt로 해싱된 값)를 Gateway Server를 통해 Front Server로 응답
  3. 비밀번호 검증
    • 사용자가 입력한 평문 비밀번호와 Back Server에서 전달받은 암호화된 비밀번호를 비교하여 검증
    • 비밀번호 검증 실패 시: 인증 실패 응답이 반환
    • 비밀번호 검증 성공 시: 로그인 절차 진행 , 마지막 로그인 시간 갱신 및 포인트 적립 요청
  4. 토큰 발급
    • 토큰 발급 후 로그인처리 완료

시퀀스 다이어그램을 통해서 보면 다음과 같습니다.(Resource Server는 Back Server와 동일)

로그인 시퀀스 다이어그램

추가적으로 같이 보시면 좋은 발표 영상입니다.

들어가는 글

안녕하세요 12월 30일 AWS SAA자격증을 취득했습니다.

정보처리기사는 필요에 의해서 취득한 느낌이 강했지만 SAA의 경우는 실제로 AWS를 사용해보면서 얻은 지식을 검증하기위해 취득한 것으로 준비하는 과정이 재밌었던 것 같습니다.

특히나 사용해보지 않았던 서비스들을 간략하게 이해할 수 있었고 서버리스 아키텍처에도 흥미가 생겨 다음에 진행할 사이드 프로젝트는 API Gateway & Lambda를 써볼까 생각하고 있습니다.

공부시간/느낀점


저의 경우 프로젝트를 진행하면서 꾸준히 AWS에 대해 학습했기 때문에 공부 시간을 선정한다는 것이 조금 애매하지만
SAA취득만을 목표로 공부한 시간은 이틀정도 되는것 같습니다.

EC2, SG , NAT , VPC , Subnet , ASG , ELB , S3 , CloudFront 등에 대해서 사전 지식이 있다면 
온 프레미스 환경에서 AWS기반으로 Migration하는 부분만 보시면 되기 때문에 많은 시간이 필요해 보이진 않습니다.

그런만큼 SAA를 취득했다고 해서 "AWS에 대해 높은 이해도를 가진다!" 라고 말하기도 어려우며 사실상 Spring과 비슷한 느낌인 것 같습니다.

백엔드 누구나 Spring을 사용하지만 Spring Core , MVC , WebFlux , Cache , Security , Data .... 등 너무나 방대한 프레임워크이기 때문에 "나는 Spring을 잘 다룬다!"라고 말할 수 있는 사람이 많지 않듯이요 

이 글은 2024년에 취득과 동시에 작성하려했는데요.. 자격증 시험날 자체가 12월 30일이기도 했고 해커톤 일정과 겹쳐 2025년에 글을 작성하고 있습니다.

아무래도 날이 추워지면서 몸이 굳어 게을러지기라도 하는 모양입니다.

마지막으로 AWS관련 발표와 합격사진 올리고 마무리하겠습니다.
감사합니다.



 

'자격증' 카테고리의 다른 글

정보처리기사 합격 후기  (1) 2024.12.18

GPT 요약

My-Books 프로젝트에서는 Spring Gateway를 활용해 URL 기반 라우팅과 권한별 필터로 인가 로직을 설계했으나, 코드 중복과 비효율 문제가 발생했습니다.
SonarQube 피드백을 기반으로 중복 코드 문제를 해결하기 위해 유저와 어드민 필터를 통합하여 AuthFilter로 최적화했습니다.
사용자 상태 검토와 권한 검증을 효율적으로 처리하면서도 유지보수성과 확장성을 확보한 인가 시스템을 완성했습니다.

My-Books 프로젝트에서의 경험을 다룬 글입니다.

My-Books 프로젝트에서는 인증/인가 시스템 설계가 사용자 경험과 서비스 성능에 직결된다는 점을 알게 되었습니다.
이번 글에서는 Spring Gateway를 활용해 인가 로직을 최적화한 과정을 공유합니다.

초기 설계 - 단순 URL 기반 라우팅

처음에는 인증 서버와 백엔드 서버의 URL을 기반으로 라우팅을 구현했습니다.

  • 인증 서버: /auth/**
  • 백엔드 서버: /api/**

이 방식은 기본적인 요청 분리는 가능했지만, 모든 요청에 대해 인가 처리가 일어나는 비효율적인 구조였습니다.

이는 서비스 성능에 부정적인 영향을 끼쳤고, 이를 개선하기 위해 권한별 라우팅을 도입하기로 했습니다.

인가 처리 - 권한별 요청 구분

Spring Gateway의 RouteLocator를 활용해 요청을 권한별로 분리했습니다

  • 권한이 필요 없는 요청: /api/** , /auth/**
  • 유저 권한이 필요한 요청: /api/member/**
  • 어드민 권한이 필요한 요청: /api/admin/**

이제 권한이 필요 없는 요청은 인가 로직을 생략할 수 있어, 불필요한 리소스 낭비를 줄일 수 있었습니다.
또한 권한별 인가처리 세분화를 위해 유저 필터와 어드민 필터를 각각 구현했습니다.

  • 어드민 필터
    • 어드민 권한 확인.
    • 토큰의 유효성, 만료 여부, 조작 가능성 검토.
    • 요청 URL을 백엔드 서버의 REST API 형식에 맞게 변환.

  • 유저 필터
    • 유저 권한 확인.
    • 토큰의 유효성, 만료 여부, 조작 가능성 검토.
    • 요청 URL을 백엔드 서버의 REST API 형식에 맞게 변환.

다음과 같이 백엔드 API URL을 설정하는것도 생각해봤지만

  • /api/admin/**
  • /api/member/**

REST API형식에 어긋난다 생각하였기에 Gateway Filter에서 URL형식을 변경하는 방식을 선택했습니다.
또한 권한 계층을 두어 어드민 권한을 갖고 있을 시 모든 유저 기능을 사용 가능하게 구현하였습니다.

유저 상태 검토 - 왜 필요했을까?

권한에 따라 요청을 분리하고 인가 로직을 적용하던 중, 사용자 권한 외에도 사용자의 상태에 대해서도 고민하게 됐습니다.

이런 경험이 있지 않은가요?
오랜만에 사이트에 접속해 로그인을 하니 휴면계정으로 보호되어있다거나.. 로그인 시도가 계속시도되어 계정이 잠겼다던가..

저 또한 이런 경험이 있었기에 권한 뿐 아니라 상태에 대해서도 검증이 필요하다 생각했으며 이를 위해 유저 상태 검토 로직을 필터에 추가했습니다.

adminAuthFilter
userAuthFilter

그런데 Filter를 완성하고 나니 다음과 같은 피드백을 받게됩니다.

Q: SonarQube보니까 코드 중복도가 엄청 높던데 이거 통합하면 안되나요?

A: 역할이 다르기 때문에 분리해놓은 것이라 통합할 생각 없는데요?

그런데... 정말 그런가요??

중복되는 로직 개선 - 필터 통합

초기 설계에서는 userAuthFilteradminAuthFilter를 분리한 이유가 있었습니다.
권한별로 역할을 분리해두면 코드가 명확해지고, 확장성을 유지할 수 있다고 생각했기 때문입니다.

하지만, SonarQube를 활용해 코드 중복도를 분석한 결과 두 필터 간 중복 코드가 상당히 많았고, 이로 인해 코드 품질이 저하된다는 피드백을 받았습니다.

필터를 통합하는건 어렵진 않았습니다. 하지만 , "서로 역할이 달라보이는데 중복이 많다는 이유로 통합해야할까?" 라는 고민에 빠졌습니다.

역할별로 타입을 나누어 구현하는 가장 큰 이유는 확장성과 유지 보수성에 있다고 생각합니다.
하나의 객체가 다양한 역할을 수행하면 코드가 복잡해지고 확장성이 떨어지니까요, 그런데 이 경우는 어떤가요?

  • "인가 처리 로직이 자주 변경될 가능성이 있을까?"
  • "유저나 어드민 외에 새로운 권한이 추가될 가능성이 있을까?"
  • "활성, 잠금, 휴면 외에 추가적인 상태가 필요한 시나리오가 있을까?"

이 질문들을 깊이 고민해본 결과, 인가 처리 로직이 자주 변경될 가능성이 낮으며, 새로운 권한이나 상태가 추가될 가능성 또한 희박하다고 판단했습니다.

따라서, 유저와 어드민 필터를 하나의 필터로 통합해도 충분히 안정적이고 효율적인 구조를 유지할 수 있다는 결론에 도달했습니다.

그렇게 통합된 AuthFilter 코드입니다.

항상 느끼는 것이지만 여러 사람의 의견을 듣고 그 의견들을 깊이 고민하는 과정이 좋은 결과물을 만드는 것 같습니다.
이렇게 Gateway 인가 로직을 최적화하는 여정은 마무리됩니다.

같이 보시면 좋은 발표 영상입니다.

+ Recent posts