12 Factor App Methodology

Updated:


12 Factor APP

image

  • methodology for building software-as-a-service apps 이라고도 불리고 어플리케이션을 만들기 위한 하나의 방법론 입니다.

  • 소프트웨어 개발 / 유지 보수 비용을 최소화 하면서 개발 환경의 기능과 인력을 극대화 할 수 있는 개발 방법론 중 하나로써 개발자로써 꼭 알아 둬야 하는 사항 입니다.

1.Codebase

  • 코드베이스의 유지와 관리에 대한 방법론으로 개발하는데 있어서 아주 중요한 문서작업 작업을 한 하나의 흔적입니다. 코드 베이스를 어떻게 작성을 했느냐, 어떤식으로 이것을 관리하느냐 등 코드를 덧붙히고 빼고 수정하는 여러가지 작업을 거치면서 계속 새로운 버전의 코드베이스를 만들어 갑니다.

  • 이러한 모든 스냅샷, 코드의 변화되가는 여러가지 버전을 항상 관리할 수 있는 Git 을 사용해서 상태 관리를 코드베이스를 관리하게 됩니다.

  • Application 과 Code 는 1:1 관계에 있는데 Application 은 repository 가 얼마많큼 dependency 를 가지고 있는냐와 상관 없이 반드시, 총괄적으로 봤을때 어플리케이션은 하나의 코드베이스 집합체로 이루어져야 한다는 것입니다. 즉, Application 하나를 완성시키기 위해서 다른 repository 들이 각각 따로 배포가 되어서 Application 쪽에서 하나로 뭉쳐져서 Application 이 완성된다는 것입니다.

  • 1:1 관계를 유지 시키기 위해서는 공유되는 코드를 라이브러리화 시켜야 합니다. 하나의 package 로 형성을 시켜서 dependency 로 관리를 해야 합니다. Application codebase 는 결국 하나의 집합체여야 하지만 배포 (deployment) 는 여러개가 될수 있는것입니다. 그래서 배포마다 항상 새로운 버전으로 활성화 시켜줘야 합니다. 근데 코드베이스 자체는 같은 코드베이스를 배포를 하게 되는것입니다. 새로운 기능을 추가한 버전을 생성하는것이지, 결국은 같은 코드베이스를 배포하는 것입니다.

2.Dependencies

  • 대부분 쓰고 있는 프로그래밍은 남들이 이미 개발하고 배포된 라이브러리를 다시 불러들여서 그것을 활용하여서 또다른 하나의 코드베이스를 만드는 이러한 형태가 개발을 진행하게 됩니다. 이러한 라이브러리는 여러가지 사용하고 있는 페키징 시스템을 통하여서 코드베이스에 지정된 폴더에 설치를 해서 사용합니다. (예, npm, yarn) 그래서 시스템 내의 하나의 특정한 페키지가 암묵적으로 존재하면 안되며 모든 종속성을 완전하고 완벽하게 엄격하게 선언을 해야 합니다.

  • 즉 이러한 종속성이 어떤 구조적 트리를 가지고 있는지 정확하게 알고 있어야 합니다.

3.Config

  • 환경에 저장된 설정으로써 배포되는 기능마다 달라질 수 있는데 새로운 배포때마다, 새로운 기능들을 계속 배포를 하기 때문에 configuration 값이 바뀌게 됩니다. 그래서 코드의 버전을 관리하는 것처럼 설정값의 버전을 관리할 필요성이 있습니다.

  • 이 모든 설정들은 흔히 Environment Variable (환경변수) 라고 불리는데 크게 3가지 방법으로 관리를 하게 되는데.

    1.코드에 같이 저장해서 배포를 통해 설정갑을 바꾼다 -> 12 factor app 에 위반되는 것

    2.데이터 베이스 서비스를 이용해 설정값을 관리한다

    3.리소스 서버 (예, AWS 의 S3) 를 사용한다

이러한 config 값은 코드와 설정은 철저하고 업격하게 분리하는것은 12 factor app 에서 반드시 필요한 요소입니다

4.Backing Services

  • 사용자가 네트워크를 통해 사용하는 서비스의 형태를 말하는것입니다. 예를들어 사용자의 프로파일을 저장할때 데이터베이스를 사용하게 되는데 이러한 서시스들은 주로 외부 리소스로 취급을 해야 합니다. 백엔드에 관련하여서 필요한 여러가지 설정값을 코드의 배포를 통하여서 혹은 코드의 직접적인 작업을 통해서 설정을 바꾸지 않아도 설정값을 바꿀수 있게 해야 하는것이 바로 백엔드 서비스 입니다.

  • 개발을 하기 위해서 필요한 여러가지 테스트용 데이터베이스, 프로덕션에서 사용되는 실제적인 데이터베이스는 철저하게 구분되어서 관리해야 합니다.

  • 개발에 필요한 시나리오를 설정하기 위해서 필요한 설정값들과 데이터베이스, 테스트 케이스를 커버하기 위해서 즉, Edge case 를 커버할 수 있는 여러가지 다른 시나리오를 커버 할수 있는 데이터베이스와 설정값을 테스트에 맞게 설정을 할 수 있게 되는것입니다.

  • 그래서 backend service 도 하나의 Application 이 될 수 있기 때문에 철저하게 리소스화 하거나 서브스화 시켜서 따로 12 factor app rule 을 따라가야됩니다.

5.Build, Release, Run

release 와 deploy 의 단어 차이점

  • release 는 코딩을 하고, 개발을 해서 소비자들이 사용할 수 있는 완성된 코드, 혹은 어플리케이션의 스냅샷 즉, development 한 싸이클이 끝나고 배포할 준비가 되어 있는 배포룰 할 수 있게 완성되어 있는 코드베이스의 완성체를 말합니다. (버전화 된 코드 스냅샷을 지칭할 때 를 말함) release version xx.xx.xx

  • deploy 는 빌드한 코드를 서버에 안착시키는 그 모든 과정을 개발과 Q.A과 끝난 그 시기에서 부터 서버에 안착시키기짜기에 필요한 모든 작업들을 deployment 라고 부를 수 있습니다.

release 라는 단어를 deployment 라는 단어 대신 쓸수는 있지만 deployment 를 release 단어 대신 사용할 수 없습니다. 왜냐면 release 는 코드 집합체를 뜻 할 수 있기 때문입니다.

  • build 라는 것은 작선한 코드를 컴퓨터, 브라우저가 읽을 수 있게 그러한 형태의 코드로 축출해서 배포하는것인데 이 코드를 그대로 배포하는 것이 아니라 이것을 컴파일을 통해 컴퓨터, 웹브라우저가 일기 적합한 형태로 변환을 해주는 과정이라고 보면 됩니다. 인터넷 상에서 코드가 서버와 클라이언트 사이에서 사이즈를 최소한으로 하기 위한 하나의 작업이 build 입니다. (예를 들어, Typescript 는 브라우저가 읽을 수 없는 언어 이기 때문에 JS 로 변환해주는 작업 또한 빌드의 한 과정이라고 할 수 있습니다.)

  • release 는 deployment 에 가까운 행위를 말합니다. release 는 배포를 할때마다 유니크한 버전 넘버를 가지고 있어야 합니다. 배포한 코드를 서버에서 작동시켜서 유저들이 웹에 접속을 할때 running 할 수 있는 상태를 만드는 것입니다

6.Processes

  • 개발하는 어플은 stateless 이어야 합니다. => 어떠한 정보가 미리 주어지지 않은 상태에서도 어플리케이션이 실행 될 수 있어야 된다는 뜻입니다. 이미 전에 실행을 하면서 어플리케이션을 들이는데 필요한 여러가지 설정값들 (state) 유저들이 사용했던 상태를 결정짓는데 중요한 것들이 존재한다는 가정하에서 어플리케이션이 돌아가게 해서는 안된 다는 것입니다. 물론 localStorage 나 사용자 측면에서 이 정보를 저장하고 사용하는 방법도 있지만, 이러한 정보들은 단기간 짧은 lifecycle 을 가져야만 합니다.

  • application 이 다시 재부팅 된 상태에서 purge 즉, 없어진 상태에서 application 을 돌릴수 있게 그런상태로 만들어야 하는것이 바로 Process 라고 합니다.

7.Port binding

  • 웹 어플리케이션은 web server container 안에서도 실행이 되기도 합니다. (예를들면 php 경우에 Apache 서버내에서 돌릴수 있는거와 같은거와 같은것)

  • 12 Factor App rule 에서는 완전하게 독립적으로 웹서버가 서비스를 만들기 위해 처리하는 실행환경에 대한 runtime injection 에 의존하지 않습니다.

  • 그 대신에 port 를 binding 해서 포트 바인딩을 통한 http 서비스로 공개되며, 포트로 들어오는 request 를 기다리게 되는 것입니다. local 환경에서 개발할 때에는 로컬호스트의 port 를 바인딩해서 사용합니다. (예, 8080, 3000, 8000 등) 이러한 포트 바인딩을 통하여서 개발자가 개발하는 어플리케이션 서비스에 접근할 수 있게 됩니다.

  • 일반적으로 종속성 declare 를 선언할 때, 웹서버 라이브러리를 추가하면서 이런 기능을 구현할 수 있게 됩니다. 그래서 http 도 하나의 포트 바인딩 입니다. 포트 바인딩에 의해서 공개되는 서비스는 http 에 국한되지 않습니다. 거의 모든 종류의 대부분의 서버를 통한 서비스는 바인딩을 먼저 하고 요펑이 들어오길 기다리는 현태의 프로세스를 통하여서 실행될 수 있습니다.

  • 포트바인딩을 사용한다는 것은 하나의 어플리케이션이 다른 어플리케이션의 백엔드 서비스로 적용될 수 있다는 것을 의미 합니다. 백앤드 어플리케이션의 url 을 endpoint 로 사용하게 되는 또 다른 어플리케이션의 설정에 추가되는 방식으로 다른 어플라케이션이 다르게 또 서비스를 사용할 수 있게 됩니다.

8.Concurrency

  • 동시성을 말하며, 웹 어플리케이션은 하나, 혹은 여러가지의 서비스를 필요로 할때가 있습니다. 예를 들면, API, Worker, Web service 등 이런 여러가지 서비스가 필요로 하는 어플리케이션이 있다고 가정을 할때 이러한 여러가지 서비스를 동시다발적으로 한꺼번에 돌릴수가 있습니다. 이것은 서버가 load balancer를 사용해 필요에 따라 scale 을 조정할수 있게 될 때, 서비스를 async 로 처리하는것보다 한꺼번에 동시다발적으로 처리하는것이 훨씬 더 유용합니다.

  • 다만, 서버가 그만큼의 필요한 scalability 가 주어지지 않을 때는 거기 레벨에 맞는 concurrency 를 유지하는것이 좋습니다.

9.Disposability

  • 폐기 기능을 말하며 크게 3가지가 해당되는데

    • Fast Launch

    • Responsive

    • Graceful shutdown

Fast launch

12 factor 에서는 중요하게 생각하는 것이, 서비스를 런칭할때, 서비스를 러닝할때 launching time 이 항살 빨라야 합니다. 이것은 앞에 dependency, stateless processes 와 연관성이 있는데 이런것들이 갖춰주어야지만 fast launching 이 가능하게 됩니다. 그래서 application 이 가벼워야 되고 정확하게 dependency 가 declare 되어 있으면서 stateful application 을 돌리면 안됩니다.

Responsive

만약 호스트가 terminate 가 되었을 경우, 언제든지 새로운 호스트로 어플리케이션을 다시 돌릴수 있게 되는 그러한 responsive 또는 scale up / down 이 가능한 load balancer 를 적절하게 사용하면서 만들어지는 app responsive 해야 합니다.

Graceful shutdown

서비스가 갑자기 terminate 되버렸을때, application 을 정지 시켜버리는것이 아니고 이 app 은 graceful shutdown 을 핸들할 수 있어야 하는것이 12 factor app 에 해당됩니다.

10.Dev/Prod parity

  • 개발, 스테이징, 프로던션 환경을 최대한 비슷하게 유지하는것을 말하는 것으로, 통상적인 개발환경은 local environment, local 환경이 아닌 어딘가에 배포가 되어서 개발자들 사이에서 협업이 일어나는 그러한 환경을 이야기 할때 development environment 라고 이야기 합니다. 그 다음에 staging 이 있고 preprod 가 있는 경우도 있고 testing environment, production environment 등 여러가지 개발 환경이 있습니다.

  • 지금 개발하고 있는 코드 상태, 기능들이 production 갔을때까지 아무런 문제 없이, 혹은 코드가 배포되었을때 그때 일어날 수 잇는 문제를 미리, 지금 내가 개발하고 있는 환경에서 최대한으로 빨리 발견해서 어떻게, 무엇이 필요한가를 하려면, 개발 환경과 프로덕션간에 통일된 셋팅 이 필요합니다.

  • 크게 3가지 단계로

    1.개발이 시작된 그 순간부터 프로덕션에 배포 되기까지의 그 시간의 간격을 최대한 줄여야 됩니다.

    2.개발하는 당사자가 마지막에 배포하는 단계까지 최대한으로 근접하게 관여해서 배포가 일어나야 합니다.

    3.개발하는 환경, 그리고 프러덕션이 가지고 있는 환경을 구축하는 툴들이 통일되어 있어야 합니다.

조금이라도 시간이 오래 걸린다던지, 개발하는 사람과 배포하는 사람이 전혀 다른 사람이라던지 사용하는 툴이 다르게 되면 works on my machine 즉, 내 local 환경에서는 분명 작동을 하는데 production, staging 에서 작동을 하지 않는 경우가 일어날수가 있다는 것입니다.

11.Logs

  • 로그는 어플리케이션에서 일어나는 모든 이벤트들을 스트림 형식으로 작성하는것을 말합니다. 항상 실시간으로 모든 이벤트를 캡쳐해서 standard output 으로 저장하게 되는데 stdout 이라고 함

  • 어플리케이션은 로그를 출력할때 그 어떠한 관여도 해서는 안됩니다.

12. Admin Processes

  • 어플리케이션을 개발하거나 어플리케이션을 운영하게 될때 유지보수를 해야될 필요가 간혹 있습니다. 서비스를 업그레이드를 하거나 database migration 을 한다던지 여러가지 administrative 한 일들 즉, 어플리케이션을 유지하기 위한 작업을 일반적으로 다른 코드 작업하는것과 마찬가지로 같은 프로세스로 작업하게 됩니다. 서비스 업그레이드 이런것들도 결국, process 를 dependencies, stateless process 를 철저하게 지키면서 작업을 해야 되고, 이러한 과정을 똑같이 거치는 것을 admin process 를 하게 됩니다.

🔶 🔷 📌 🔑

Reference

개발자가 반드시 알아야할 12가지 - https://youtu.be/XCa2bA3ZDLs

imgur - https://imgur.com/gallery/V9nAWbd

Leave a comment