12 Factor Apps 란 무엇인가?
클라우드 환경에서 특히 적합한 방법론으로,
확장성 및 유지보수가 용이한 웹 애플리케이션을 구축하기 위한 12가지 원칙세트이다.
주요 원칙은 아래와 같다.
1. 코드 기반
2. 종속성
3. 구성
4. 지원 서비스
5. 빌드, 릴리즈, 실행
6. 프로세스
7. 포트바인딩
8. 동시성
9. 일회용
10. 개발/운영 환경 동일하게 유지
11. 로그
12. 관리 프로세스
1. 코드 기반
애플리케이션의 소스코드 뿐 아니라 모든 관련된 자산, 프로비저닝 스크립트, 구성 설정 등의 애플리케이션의 모든 것이 개발자나 테스터, 시스템 관리 직원이 액세스 가능한 소스코드 저장소에 저장되어야 한다는 것을 의미한다.
2. 종속성
이 원칙의 핵심은 "애플리케이션에서 필요한 외부 기능이나 라이브러리(=종속성)는 명확히 선언하고 따로 관리하라"는 것이다.
-
명시적 선언: 애플리케이션이 사용하는 모든 외부 라이브러리나 패키지를 코드에 직접 넣지 말고, 종속성 관리 파일에 명시해야 한다.
예) Node.js는 package.json에 필요한 패키지를 명시하고, Java는 pom.xml이나 build.gradle 파일에 라이브러리를 선언한다.
-
격리된 관리: 외부 라이브러리 파일 자체를 소스 코드 저장소에 직접 포함하지 말라
대신, 애플리케이션을 실행할 때 종속성 관리 파일에서 필요한 외부 라이브러리를 자동으로 다운로드하고 설정하는 방법을 사용한다. 이를 통해 코드가 더 깔끔하고 관리가 쉬워지며, 필요할 때마다 최신 버전으로 쉽게 업데이트할 수 있다.
➡️ 애플리케이션의 코드와 외부 라이브러리나 기능들이 서로 명확하게 분리되어 코드 충돌이나 버전 호환성 문제를 줄일 수 있고 배포 시에도 일관된 환경을 유지할 수 있다.
3. 구성
환경에 따라 설정을 분리하는 것을 의미한다. 즉 애플리케이션 코드에 직접 환경설정 정보를 넣지말고, 환경별로 분리하여 관리하라는 것이다. 이렇게하면 코드와 환경 설정이 분리되어 코드의 재 사용성이 높아지고 배포 환경에 맞춰 쉽게 설정을 변경할 수 있다.
사용예시
Java의 properties 파일, k8s의 매니페스트, docker-compose.yml 파일
- 환경 변수나 별도의 구성 파일 사용
예) 포트번호, 데이터베이스 URL, 디버그 모드 같은 설정정보를 코드에 직접 넣지 않고 환경 변수 또는 독립 구성 파일에 따로 저장한다.
- 환경 마다 다른 설정
개발, 테스트, 운영 등 환경 별로 필요한 설정이 다를 수 있으므로 각 환경에 맞게 별도의 설정 파일을 적용할 수 있다.
예) 운영환경에서는 DEBUG=false, 테스트 환경에서는 true로 설정하는 방식
4. 지원 서비스
데이터베이스, 이메일 서버, 메세지 브로커 같은 외부 서비스들은 코드에 직접 연결하지 않고 독립된 리소스 처럼 취급하라는 것이다.
사용예시
데이터베이스를 환경변수나 구성파일에서 URL로 가져와 연결하기
Redis나 RabbitMQ 같은 메세지 브로커를 외부서비스처럼 다루어 연결
- 서비스를 별도의 리소스로 취급
외부 서비스들은 애플리케이션과 느슨하게 결합되어야 한다. 서비스가 필요할 때 외부에서 가져와 사용할 수 있도록 연결만 해두고 특정 서비스에 종속되지 않도록 해야한다는 뜻이다.
- 유연한 변경 가능
예) 현재 MySQL을 쓰고 있다가도 상황에 따라 Postgres로 변경할 수 있는 유연성이 생긴다.
5. 빌드, 릴리즈, 실행
어플리캐이션의 배포과정을 3단계로 나누어 관리하라는 것이다. 각 단계는 명확히 분리되며 언제든 문제가 생겨도 다시 처음부터 재구성할 수 있도록 설계해야한다

이미지 출처 : Redhat
- 빌드 단계 : 코드를 컴파일해서 애플리케이션의 실행파일(artifact)를 만드는 과정이다. 소스코드 관리 시스템에서 코드를 검색해서 아티팩트로 빌드하고 컴파일하는 단계이다.
예) Docker이미지를 빌드하거나 Maven 저장소에 라이브러리를 빌드하는 단계
- 릴리즈 단계 : 빌드된 artifact에 환경별 설정정보를 적용하는 단계. 배포 환경에 맞는 구성을 추가해서 최종 배포준비를 마친다.
- 실행 단계 : 설정된 환경에서 어플리케이션이 실행되는 단계. 이 단계에서는 서버나 데이터베이스 같은 리소스가 연결되고, 사용자에게 서비스를 제공한다.
예) Ansible 같은 도구를 사용해서 스크립트를 통해 런타임환경에 프로비저닝 된다.
6. 프로세스
애플리케이션을 한 개 이상의 상태 비저장(stateless) 프로세스로 운영하여야 한다. 프로세스 자체에 데이터를 저장하지 말고 필요한 경우 데이터베이스나 외부 저장소를 활용해야한다는 원칙이다.
- 상태 비저장 : 각 프로세스는 자신만의 상태를 가지지 않고 독립적으로 동작한다.
예) 세션 데이터나 워크플로우 상태는 프로세스에 저장되지 않고 외부에서 관리된다.
- 확장성 : staeteless 상태로 운영하면 프로세스를 쉽게 추가하거나 제거할 수 있어 확장성에 용이하다.
7. 포트 바인딩
서비스를 포트 번호를 통해 외부에 공개하라는 원칙이다.
➡️ 포트를 통해 애플리케이션을 쉽게 식별할 수 있고 환경 간 네트워크 설정이 표준화된다는 장점이 있다.

이미지 출처 : Redhat
- 포트 바인딩 사용 : 애플리케이션은 특정 포트를 사용해서 네트워크에 노출된다.
- 일관성 있는 포트 사용 : 일반적으로 사용되는 포트 규칙에 따라 서비스를 구성하면 충돌을 줄이고 관리가 쉬워진다.
예) MySQL:3306, ssh:22, MongoDB:27017 등
8. 동시성
프로세스를 목적에 따라 구성한 다음 필요에 따라 확장하거나 축소할 수 있도록 프로세스를 분리하라는 뜻이다.
➡️ 특정 기능만 확장할 수 있어 효율적인 리소스 관리가 가능하게 된다.
- 역할 기반 프로세스 분리 : 애플리케이션의 기능을 웹 서버, 비즈니스 로직, 데이터 처리 등 역할에 따라 나누어 각 기증에 맞게 확장한다.
- 부하에 따른 확장 : 웹 서버에 트래픽이 몰리면 웹 서버만 추가하고, 데이터 처리량이 많아지면 데이터 처리 프로세스만 확장할 수 있다.
9. 일회용
애플리케이션이 빠르게 시작하고 종료될 수 있도록 설계하는 원칙이다.
➡️ 빠르게 시작/종료할 수 있어 유연한 배포와 안정적인 운영이 가능하다.
- 빠른 시작 : 애플리케이션이 최대한 빠르게 준비되어야 한다. 필요한 연결(데이터베이스 등)을 즉시 설정하여 서비스를 제공할 수 있게 한다.
- 우아한 종료 : 종료 시 리소스를 안전하게 해제한다.
예) 연결 끊기, 로그 남기기
10. 개발/운영 환경 동일하게 유지
개발 환경과 운영환경을 최대한 유사하게 유지해야 한다.
- 유사한 환경 유지 : 개발, 테스트, 운영 환경에서 코드가 같은 방식으로 배포되고 작동하도록 설정한다. 이를 통해 개발 중 발생하지 않은 오류가 운영에서 발생하는 일을 줄일 수 있다.
- 일관된 배포 프로세스 : 모든 환경에서 동일하게 빌드, 릴리즈, 실행과정을 따른다.
11. 로그
로그는 이벤트스트림으로 다루어야 한다는 원칙이다.
➡️ 로그가 애플리케이션과 분리되어 여러 용도로 사용가능하고, 문제가 발생해도 데이터를 안전하게 유지할 수 있다.

이미지 출처 : Redhat
- 이벤트 스트림으로 전달 : 로그는 시간 순서대로 기록되는 이벤트의 흐름으로, 애플리케이션과 분리하여 다양한 분석 시스템에서 활용할 수 있도록 한다.
- 다양한 소비자를 지원 : 로그데이터를 필요에 따라 여러 곳에서 분석할 수 있다. 예를 들어 에러만 따로 추출하거나 모든 로그를 저장하는 등 용도에 맞게 활용 가능하다.
12. 관리 프로세스
관리 프로세스(데이터 초기화, 시스템설정, 유지보수 등)를 일회성 프로세스로 독립 실행하여야 한다.
- 일회성 프로세스 : 관리 작업은 평소 애플리케이션과 함께 실행되는 것이 아니라 필요할 때 한번씩 수행된다.
예) 데이터 베이스에 데이터를 미리 넣는 작업을 초기 설정 시 실행한다.
- 주요 프로세스로 취급 : 관리 프로세스 역시 주요 소프트웨어 기능의 일부로 취급하고, 배포와 실행을 신중히 다루어야 한다.
참고
https://www.redhat.com/en/blog/12-factor-app