오픈스택 생태계는 하나의 서비스가 아니라 수십 개의 독립된 오픈소스 프로젝트가 조합되어 만들어진 거대한 클라우드 플랫폼이다. 여기에 속한 프로젝트는 서로 다른 언어, 프레임워크, 빌드 시스템, 번역 구조를 가지고 있다.
이번 글에서는 오픈스택 생태계에 존재하는 다양한 프로젝트 유형에 대해 정리해보고자 한다.
오픈스택의 대표적인 프로젝트인 인증 서비스 Keystone, 가상머신 서비스 Nova, 네트워킹 서비스 Neutron, 스토리지 서비스 Cinder, 대시보드 Horizon 등은 각각 독립적인 리포지토리와 빌드 시스템을 가지고 있다.
이들 프로젝트는 모두 Python으로 작성된 것처럼 보이지만 실제로는 서로 다른 유형의 프로젝트이다.
Python 프로젝트 외에도 CLI 도구, 웹 서비스, Django 기반 웹앱, ReactJS 프론트엔드, 문서 전용 프로젝트 등 다양한 유형이 존재하며, 이는 곧 번역과 배포 방식의 차이로 이어진다.
프로젝트 유형 분류
| 유형 | 대표 프로젝트 | 주요 기술 스택 | 구조적 특징 |
|---|---|---|---|
| Python Service | Keystone, Nova, Cinder, Neutron | Python, oslo, REST API | 백엔드 핵심 서비스. Babel 기반 번역 구조 |
| Django Dashboard | Horizon | Django, Python | Web UI. Django의 makemessages 시스템 사용 |
| ReactJS Frontend | skyline-console | React, Vite, i18next | 차세대 대시보드. JSON 기반 번역 구조 |
| Docs / Release Notes | openstack-manuals, release-notes-* | RST, Sphinx, YAML | Sphinx 기반 문서 번역 구조 |
| Client Library | python-openstackclient | Python CLI | 명령어 출력 중심. 번역 포맷 단순 |
| Infra / DevOps | devstack, puppet-openstack | Shell, YAML | 번역 거의 없음. 스크립트 중심 |
이처럼 프로젝트마다 기술 스택과 구조가 다르며, 동일한 .po 파일 을 다루더라도 추출 방식과 빌드 경로가 다르다.
즉, 오픈스택의 번역 자동화 파이프라인에서는 여러 프로젝트 유형을 처리할 수 있어야 한다.
Python 프로젝트 구조
가장 전통적인 유형은 Keystone, Nova, Neutron 등과 같은 Python Service 프로젝트이다.
오픈스택의 핵심 백엔드 서비스로, oslo.config, oslo.messaging 등의 공통 모듈을 사용하며, 대부분 setup.cfg와 pbr(Python Build Reasonableness) 기반으로 패키징된다.
nova/
├── nova/
│ ├── api/
│ ├── db/
│ ├── cmd/
│ └── locale/
├── setup.cfg
├── tox.ini
└── requirements.txt
아래는 실제 nova 프로젝트의 locale 폴더 구성이다.
각 언어별 번역 파일은 locale/ 디렉터리에 위치하며, Babel을 이용해 .pot → .po → .mo 순서로 처리된다.
.pot 파일은 Babel을 통해 생성되며, 프로젝트에 따라 tox -e gettext 환경이 이를 래핑해 실행한다. 이후 Zanata와의 동기화를 통해 번역이 자동화된다.
이 유형은 구조가 명확하고 규칙적이어서 자동화가 가장 쉬운 편이다.
Django 기반 Horizon (Dashboard)
Horizon은 오픈스택의 사용자 대시보드로, Django 프레임워크 위에서 동작한다. Django는 자체적인 i18n 체계를 가지고 있기 때문에 Python Babel 기반 프로젝트와는 번역 경로가 다르다.
아래는 Horizon 저장소의 실제 경로 구조이다.
horizon/
└── locale/
└── ko_KR/
└── LC_MESSAGES/
├── django.po # 서버/템플릿 번역
└── djangojs.po # 클라이언트(JS) 번역
django.po는 서버 측(Python + Template) 번역 파일.py,.html등에서{% trans %}, _(‘string’)구문으로 감싸진 문자열이 수집된다.- Django의
makemessages명령어로 자동 생성되며,
Horizon의 백엔드와 템플릿에서 사용하는 모든 문구가 이 파일에 저장된다.
djangojs.po는 클라이언트 측(JavaScript) 번역 파일- Horizon의 프론트엔드 JS 파일 내 알림창, 버튼, 대화상자 텍스트가 여기에 해당한다.
- Django는
makemessages -d djangojs옵션을 통해 JS 내 문자열을 별도로 추출한다. - 번역이 완료되면 Django의 compilemessages 과정에서
.mo로 변환되어
/static/jsi18n/경로를 통해 브라우저로 제공된다.
즉, Horizon의 번역 체계는 서버(Render 시점) 와 클라이언트(브라우저 시점) 를 분리하여 관리한다.
ReactJS 대시보드 (Skyline Console)
최근 오픈스택 커뮤니티는 차세대 대시보드로 React 기반의 Skyline Console 프로젝트를 개발하고 있다. 이 프로젝트는 Node.js 환경에서 동작하며, 역시 또 다른 i18n 구조를 가지고 있다.
src/
├── components/
├── pages/
├── locales/
│ ├── en/
│ └── ko/
├── package.json
└── vite.config.ts
이 구조에서 번역 파일은 .json 형식으로 관리된다.
예를 들어 locales/ko-kr.json 파일 안에는 다음과 같은 구조가 있다.
django.po 처럼 gettext 기반이 아니라 JSON 기반 key–value 구조의 번역 파일이다.
Release Notes 및 Documentation
오픈스택은 기술 문서와 릴리즈 노트를 전용 저장소에서 관리한다.
대표적으로 openstack-manuals와 각 서비스별 releasenotes 디렉터리가 있다.
아래는 실제 horizon 프로젝트 내부에 포함된 releasenotes 번역 디렉터리 구조이다.
releasenotes/
├── source/
│ ├── locale/
│ │ └── ko/
│ │ └── LC_MESSAGES/
│ │ └── releasenotes.po
│ ├── conf.py
│ └── index.rst
├── setup.cfg
└── tox.ini
이 구조는 Sphinx 기반 문서 프로젝트로, gettext 빌드 모드를 사용한다.
즉, .rst 문서에서 텍스트를 추출해 .pot 파일을 만들고,
그 결과로 생성된 .po 파일을 Zanata에서 번역하는 구조이다.
마치며
오픈스택의 번역 구조는 프로젝트별 기술 스택과 빌드 방식에 따라 다르게 구성된다. Python 서비스는 Babel을 기반으로, Horizon은 Django의 i18n 시스템을, Skyline은 i18next 기반 JSON 구조를, Release Notes는 Sphinx를 사용한다.
이러한 차이로 인해 .pot 생성 방식, 번역 파일 경로, 빌드 명령어가 모두 달라진다.
따라서 기존 Zanata에서 Weblate 기반으로 번역 자동화 파이프라인을 재설계할 때도 마찬가지로 각 프로젝트의 구조를 별도로 정의하고, Job을 구분해 관리해야 한다.



