프론트엔드 개발자의 인프라 공부
요즈음 격무에 시달리는지라 블로그에 글을 쓰지 못하고 있었습니다😭 회사에서 일하고, 집에 와서는 그동안 부족하다 생각을 많이 했던 알고리즘이나 인프라 공부를 하고 있어요. AWS같은 클라우드 컴퓨팅 서비스를 비롯한 인프라는 최근까지도 손에 잡히는 공부는 아니었습니다. 서 비스 맨 앞단에서 일을 하고 있는 프론트엔드 개발자라서 그렇다고 생각했었는데요.
인프라를 막상 공부해보니 저 생각이 참 잘못되었다는 느낌이 많이 들었습니다. 역시 개발자 생태계에서 덮어놓고 몰라도 되는 건 없습니다. 이 글에서는 인프라 공부를 하면서 느꼈던 생각들, 특히 대용량 트래픽 처리에 대한 생각을 좀 정리해보고자 합니다.
리서치를 많이 하고 쓰는 글은 아니고, 짧은 시간 공부하고 회사에서 인프라를 살짝 만지면서 느낀 소회를 정리하는 글이 될 것 같습니다. 앞으로 공부해 나가야 할 것도 너무 많습니다만, 이제 첫 단추를 꿴 인프라 어린이의 짧은 회고 쯤으로 보시면 됩니다. 포스팅에 등장하는 인프라 관련 용어들을 따로 설명하지는 않겠습니다. 🙂
프론트도 서버다
프론트엔드도 서버입니다. 웹앱 코드를 배포해놓으면 그건 서버에서 가져다줍니다. 당연히 트래픽도 있습니다. 주소창으로 요청을 하면 볼 수 있는 웹 페이지들은 모두 서버에서 오는 것입니다. S3에 SPA를 올려놓든, 정적 웹페이지를 올려놓든, EC2에 Next같은 SSR 앱을 올려놓든, 서버리스에 올려놓든, 다양한 형태로 존재할 수 있는 서버는 프론트엔드 개발의 결과물을 서빙합니다.
프론트엔드라는 개발 분야가 생기고 발전하면서 서버, 그리고 배포는 백엔드만의 전유물이 아니게 되었습니다. 프론트엔드의 배포 프로세스는 이제 백엔드와는 독립적으로 진행될 수 있고, 관점도 다릅니다. 1월 중순부터 다니는 회사에서도 프론트엔드 배포는 백엔드 배포와는 물리적으로는 아무 상관이 없습니다. 또한,, 저는 입사하고 나서 배포 파이프라인과 스크립트를 짰고 AWS 리소스들을 어레인지하면서, 저번 직장에서 인턴으로 근무할 때 보다 인프라의 이모저모를 좀 더 접해보게 되었어요.
저는 비교적 최근인 2019년부터 개발을 시작했던지라 이러한 환경을 당연하게 받아들였습니다. 하지만 프론트엔드든 백엔드가 분리되기 전의 배포에는 프론트엔드가 백엔드 배포에 종속이 되는 경우가 많았다고 하더라고요. 서버가 유저가 요구하는 모든 리소스를 보내주던 시절의 웹개발에서는 말입니다.
이런 상황에서...🧐 프론트엔드 개발자도 인프라를 모르면 안 될 것 같다는 생각이 생겼습니다. 프론트엔드 개발자는 이제 클라이언트 코드를 서빙하는 서버와 인프라를 안정적으로 유지할 책임이 있습니다.
클라이언트 서빙하기
프론트엔드 개발자가 인프라에서 추구해야할 목표를 크게 3개로 잡아보았습니다.
안정적으로 서빙하기
안정성은 서버의 최우선 덕목입니다. 클라이언트 웹앱을 서빙하는 서버는 유저에게 클라이언트 앱을 안정적으로, 중단 없이 서빙해야 합니다. 그렇다면 질문을 좀 바꿔서, 어떠한 상황에서 서버가 불안정해질까요?
가장 쉽게 생각할 수 있는 것은 과도한 트래픽입니다. 트래픽이 너무 많아 서버가 처리할 수 없다면 서버는 뻗습니다.
물론 프론트엔드 서버의 트래픽은 백엔드 서버와 비교해봤을 때 많이 적은 수준입니다. 클라이언트 앱을 서버에 요청해 가져오는 것은 유저가 주소창이나 링크로 웹사이트에 접근했을 때와 새로고침을 누를 때 정도에만 발생하고, 그 이후에는 백엔드에 여러 데이터를 여러번 요청합니다. 대강 비율로 따지면 1:N 정도가 됩니다. 유저는 클라이언트 웹앱에 접근한 이후, 한 세션에서 백엔드에 여러번 데이터를 요청할 수 있습니다.
하지만 유저가 무지무지 많다면 프론트엔드 서버에도 가용성을 높일 수 있는 조치가 필요합니다. 프론트엔드 서버에도 트래픽은 존재하기 때문에 서버는 뻗을 수 있습니다. (물론 프론트엔드 서버의 가용성을 높여야할 정도라면 백엔드 트래픽은 정말 무시무시하게 많을 것이라 예상해볼 수 있겠습니다...😯 )
프론트엔드 배포에 자주 쓰이는 AWS S3 이야기를 해보자면, S3는 안정성이 99.99999999%이고 기본적으로 초당 3500~5500개 정도의 요청을 감당하기 때문에 대형 서비스가 아닌 경우 스토리지의 가용성을 높이거나 다수의 스토리지를 사용할 필요는 없습니다.
하지만 더 많은 트래픽을 감당할 수 있어야 하는 경우, CDN을 이용하거나(Cloud Front), Route 53으로 로드 밸런싱(Client Side Load Balancing)을 하는 방법 등으로 가용성을 높일 수 있습니다. EC2를 사용한다면 ELB 도입이나 인스턴스의 컴퓨팅 파워를 높이는 방법 등을 생각해볼 수 있겠죠.
기획/조직의 의도에 맞게 서빙하기
프론트엔드 앱과 서버를 만드는 과정에서, 기획과 조직의 의도를 파악하고 이를 반영하는 것은 중요합니다. 만약 지금 개발하고 있는 서비스가 검색 유입이 중요해서 서버사이드 렌더링을 도입해야 한다고 생각해봅시다. 기존의 서비스에 SSR을 적용해야 한다면 개발 단에서 SSR을 하는 코드를 붙여줄 수도 있지만, 여의치 않다면 인프라에서 lambda@edge를 이용하여 진행할 수도 있습니다.
SSR이 되는 앱을 새로 개발한다면 Next나 Nuxt와 같은 SSR 프레임워크의 도입을 고려할 수 있습니다. 이때 Next와 Nuxt는 클라이언트 앱 뿐 아니라 서버를 낀 채로 빌드를 할 수 있기 때문에 S3 스토리지에 올리는 것 만으로는 부족하고, EC2나 Elastic Beanstalk, 혹은 Lambda를 사용한 배포 방법이 필요합니다.
이렇게 기획과 조직의 의도를 파악하고 앱을 만들어 나가는 것에는 물론 개발 단에서 어찌할 수 있는 것들도 있지만, 배포가 가능한 인프라를 함께 고려해야 하는 경우가 생깁니다. 이외에도 조직의 효율성 재고를 위해 마이크로서비스 아키텍쳐 등을 도입해야 한다면 또 어떨까요. 이런 상황에서 프론트엔드 개발자는 서비스의 요구사항과 기획을 올바르게 반영할 수 있는 앱과, 인프라 구조를 고안해야 합니다.
쉽고 빠르게 배포하기
제가 다니는 회사의 프론트엔드 앱에 대해서 이야기해보겠습니다. 한 달 전쯤 드디어, 회사 극초기에 외주로 만들었던 레거시 서비스 코드를 들어내고, 저를 비롯한 인하우스 개발자들이 만든 웹 클라이언트 코드가 처음으로 라이브되었습니다. 레거시를 빠르게 대체하는 것을 목표로 삼았기 때문에 빠듯한 데드라인을 맞추기 위해 애를 썼었고, 처음으로 나온 결과물은 버그와 빈틈이 많았습니다. 첫 배포는 끝이 아니라 시작이었고, 그 후 3주 동안 계속해서 개선을 해온 결과 앱이 빠르게 안정되었습니다.
이 과정에서 빠른 배포는 필수적이었습니다. 기획과 디자인이 매일 수정되고 웹사이트에 문제가 있다며 채널톡으로 마구 CS가 쏟아지는 초기 스타트업의 출구없는 감성 속에서, 리뷰 직후 yarn 명령어 한번으로 수정된 코드가 바로 적용될 수 있도록 정확하게 배포할 수 있는 시스템을 만드는 것은 매우 중요했습니다. 프론트엔드 앱의 개선 속도도 빠르게 쏟아지는 버그 리포트와 기획/디자인 변경을 따라가야 했었으니까요.
저는 S3와 cloud front를 사용해 환경을 만들고, S3에 새로운 빌드 파일들을 올려놓는 동시에 CDN 캐시를 삭제(Invalidation)하여 바로 배포한 바를 확인할 수 있도록 yarn 명령어 스크립트를 만들었습니다. 물론 모든 것이 갖춰진 CI/CD 파이프라인을 구축하는 것 보다 훨씬 쉬운 일입니다만, 배포를 빠르게 할 수 있다는 사실만으로 빠르게 이루어져야 하는 앱 개선이 매우 힘을 받았습니다. 자동화의 힘을 새삼 다시 깨달을 수 있었습니다.
프론트엔드 개발자는 앱의 수정사항이 빠르게 반영되고 화면에 바로 보일 수 있도록 빠른 배포가 가능한 파이프라인을 구축할 수 있어야 하고, 이는 인프라와 자동화를 공부해야 가능할 것입니다.
또한 중요한 것 - 비동기 요청 최적화
사실... 프론트엔드 서버의 인프라를 생각해보기 이전에, 프론트엔드에서 백엔드로 보내는 불필요한 요청들을 줄일 수 있다면 백엔드의 대용량 트래픽 처리에 아주 직접적으로 도움을 줄 수 있습니다. 불필요하게 백엔드로 가는 트래픽을 아예 없앨 수 있다는 것이니까요. 빠르게 웹앱을 개발하다 보면 화면에 데이터가 잘 뿌려지고 디자인대로 잘 나오는지만 신경을 곤두세우는 경우가 많아 백엔드로 보내는 비동기 요청 최적화에 대해서는 크게 생각을 하지 못하게 되는데요. 그렇기 때문에 개발 과정에서 불필요하게 백엔드에 데이터를 요청하고 있지는 않나 한 번 의식적으로 돌아볼 필요가 있는 것 같습니다. 적당한 시점이 되기 전까지 데이터를 요청하지 않도록 캐싱을 구현한다거나 하는 방법도 좋지 않을까 생각해봅니다.
마무리
여기까지 글을 쓰고 나니, 인프라를 공부한지 얼마 안 된, 그저 인프라 미물이라서 잘못된 정보를 전달하지 않았는지, 고작 회사에서 조금 깔짝거렸을 뿐인데 이런 글을 써도 되는 건지... 자기검열을 하게 되네요.🥴 글 쓰기 잘했는지 당최 모르겠습니다.. 서비스를 개발하는 어떤 개발자도 인프라를 잘 알면 서비스에 효과적으로 기여하고, 장애에 적극적으로 대비하는 개발자가 될 수 있다는 생각을 갖고, 당분간 열심히 인프라와 자동화를 공부를 계속 해볼까 합니다.😎