DX는 Developer eXperience 약어이다. UX가 User 관점의 경험이라면 DX는 개발자가 개발시에 어떻게 효율적으로 생산성을 높힐지에 관심을 갖는다. 개발 조직 및 개인 관점에서 좋은 DX란 무엇일까?
[1] 시작을 쉽게 할 수 있어야 한다.
- 설정이 많다면 installer를 통해 초기 설치 및 설정을 문답식으로 진행토록 한다.
- 설치이후 추가 요건에 대한 생성 및 설정을 위한 명령어가 제공되어야 한다.
[2] 복잡하지 않아야 한다.
- 설치이후 접근 편이성이 좋아야 한다. 즉, 폴더 구조가 간편하고 설정 파일이 적어야 한다. 즉, 컨벤션에 의한 동작이 필요하다.
[3] 로컬에서 모든 것을 실행하고, 디버깅할 수 있다.
- 로컬 개발서버를 실행하고 디버깅할 수 있는 환경을 제공한다.
- LLM 접근의 경우 prompt 디버깅이 가능해야 한다.
[4] 애플리케이션 개발을 위한 템플릿을 제공해야 한다.
- 제네레이터를 통해 원하는 파일을 생성할 수 있다.
[5] 컴파일 환경을 제공한다.
- 빠른 번들링 속도를 제공한다.
[6] 사용자 가이드를 제공한다.
NX 의 Monorepo 아키텍처
NX는 Monorepo(모노레포) 아키텍처를 위한 도구로, 하나의 리포지토리에서 여러 개의 애플리케이션과 라이브러리를 함께 관리할 수 있도록 지원하는 빌드 시스템 및 개발 도구이다. 대규모 프로젝트로 팀단위로 일할 때 생산성을 향상시켜준다.
how to improve developer experience with NX? 의 구글 답변:
Monorepo(모노레포)는 하나의 Git 리포지토리에서 여러 개의 프로젝트(앱, 라이브러리)를 관리하는 방식을 의미합니다. 일반적인 Polyrepo(각 프로젝트를 별도의 리포지토리에서 관리하는 방식)와 달리, 모든 코드베이스를 하나의 저장소에서 관리할 수 있습니다.
GPT 통해 NX 모노레포 아키텍쳐에 대해 문의한 답변:
NX 기반 Python 개발환경 만들기
Node.js 최신 LTS 버전을 설치한다. 나중을 위하여 NVM(Node Version Manager)를 통해 설치하기를 권장한다.
[1] create-nx-workspace 실행하고, 질문에 선택을 한다.
- workspace 명칭: aip
> npx create-nx-workspace
✔ Where would you like to create your workspace? · aip
✔ Which stack do you want to use? · none
✔ Would you like to use Prettier for code formatting? · Yes
✔ Which CI provider would you like to use? · azure
NX Creating your v20.5.0 workspace.
✔ Installing dependencies with npm
[2] NX 전용 파이썬 플러그인을 설치한다. @nxlv/python 은 build, publish 등 uv 패키지 메니져 사용시, poetry 의 장점을 보완한다.
- aip 폴더로 이동한다.
npx nx add @nxlv/python
설치후 uv 패키지 메니져를 설정한다.
- nx.json 파일을 열고 추가한 플러그인 환경을 설정한다.
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"production": ["default"],
"sharedGlobals": ["{workspaceRoot}/azure-pipelines.yml"]
},
"nxCloudId": "67d10bd6d85eaf278ac96674",
"plugins": [
// add -- start
{
"plugin": "@nxlv/python",
"options": {
"packageManager": "uv"
}
},
// add -- end
{
"plugin": "@nx/js/typescript",
"options": {
"typecheck": {
"targetName": "typecheck"
},
"build": {
"targetName": "build",
"configName": "tsconfig.lib.json",
"buildDepsName": "build-deps",
"watchDepsName": "watch-deps"
}
}
}
]
}
Applications 와 Packages 관계
NX의 모노레포 아키텍쳐에서는 Shell Library Pattern 방식을 지향한다. 이는 다양한 애플리케이션(서비스)안에서 사용하는 패키지(라이브러리)를 분리 관리하는 방식으로 확장성과 유지보수성을 높혀준다.
프로젝트에서 애플리케이션의 모든 페이지와 컴포넌트를 패키지에 담고, 애플리케이션은 이들의 조합하고 설정하는 역할만 수행한다. 이때 패키지는 Nexus Registry에 배포하여 버전관리를 하게되면 유지보수성이 좋아진다.
실 프로젝트에서 Frontend 파트를 보면 Micro Applications들은 각가의 Micro Frontend 로 구성하고, Portal 이 라는 곳에서 Module Federation을 통해 각 micro frontend를 통합하여 표현한다. Micro Frontend에는 비즈니스 로직이 없고, 애플리케이션 구성 환경설정만 존재한다. libs 폴더안에 있는 것이 패키지로 각 패키지는 NPM Registry에 배포되어 버전 관리를 하고, 애플리케이션은 libs에 있는 패키지를 통해 화면 및 비지니스 로직을 구현한다.
Peter real project folder structure
NX의 Shell Library Pattern도 유사하게 Feature Shell 이라는 Integrated Application을 제공한다.
A domain-wise application is the composition of every application that has the same routes, behavior, and functionalities. In the example in Figure 1, the Booking Application is the union of the Booking Web Application, the Booking Desktop Application, and the Booking Mobile Application.
apps & libs 폴더 구조
NX Python Application & Package 생성하기
UV 가상환경부터 미리 만들자. 3.11 버전을 사용토록 고정 설정한다.
uv python pin 3.11
UV 기반의 python 애플리케이션 또는 패키지를 생성(Generate)하기 위한 명령어.
npx nx g @nxlv/python:uv-project src --projectType=library --directory=packages/embedding --packageName=aip-embedding --publishable
- src 폴더 밑으로 템플릿 기반 소스 생성
- pyproject.toml 파일 생성
- project.json NX 환경파일 생성
- 그외 Unit test 용 tests 폴더 생성
▶ npx nx g @nxlv/python:uv-project src --projectType=library --directory=packages/embedding --packageName=aip-embedding --publishable
NX Generating @nxlv/python:uv-project
CREATE packages/embedding/project.json
CREATE packages/embedding/README.md
CREATE packages/embedding/.python-version
CREATE packages/embedding/src/__init__.py
CREATE packages/embedding/src/hello.py
CREATE packages/embedding/pyproject.toml
CREATE packages/embedding/tests/__init__.py
CREATE packages/embedding/tests/conftest.py
CREATE packages/embedding/tests/test_hello.py
=========
▶ npx nx g @nxlv/python:uv-project --help
NX generate @nxlv/python:uv-project [name] [options,...]
From: @nxlv/python (v20.7.0)
Name: uv-project
Options:
--name [string]
--projectType Project type [string] [choices: "application",
"library"] [default: "application"]
--buildBundleLocalDependencies Bundle local dependencies [boolean] [default: true]
--buildLockedVersions Use locked versions for build dependencies [boolean] [default: true]
--codeCoverage Generate code coverage report [boolean] [default: true]
--codeCoverageHtmlReport Generate html report for code coverage [boolean] [default: true]
--codeCoverageThreshold Code coverage threshold [number]
--codeCoverageXmlReport Generate Xml report for code coverage [boolean] [default: true]
--description Project short description [string]
--devDependenciesProject This approach installs all the missing dev [string]
dependencies in a separate project
(optional)
--directory A directory where the project is placed [string]
--linter Project linter [string] [choices: "flake8", "ruff",
"none"] [default: "ruff"]
--moduleName Python module name [string]
--packageName Python package name [string]
--projectNameAndRootFormat Whether to generate the project name and [string] [choices: "as-provided",
root directory as provided (`as-provided`) "derived"] [default: "as-provided"]
or generate them composing their values and
taking the configured layout into account
(`derived`).
--publishable Project is publishable [boolean]
--pyenvPythonVersion Pyenv .python-version content (default to [string]
current python version)
--pyprojectPythonDependency Pyproject python dependency version range [string] [default: ">=3.9,<4"]
--rootPyprojectDependencyGroup If a shared pyproject.toml is used, which [string] [default: "main"]
dependency group does this new project
should belong to
--tags, -t Add tags to the project (used for linting) [string]
--templateDir Custom template directory, this will [string]
override the default template, if not
provided the default template will be used
--unitTestHtmlReport Generate html report for unit tests [boolean] [default: true]
--unitTestJUnitReport Generate junit report for unit tests [boolean] [default: true]
--unitTestRunner Project unit test runner [string] [choices: "pytest", "none"]
[default: "pytest"]
packages/embedding 폴더로 이동하여 build 수행
$> cd packages/embedding
$> npx nx build
dist 폴더 하위로 배포파일이 자동 생성된다.
│ ├── aip_embedding-1.0.0-py3-none-any.whl
│ └── aip_embedding-1.0.0.tar.gz
생성된 tar.gz 파일 배포는 registry가 public 인지 private 따라 설정을 진행하여 최초 로그인된 후 실행 가능하다.
packages/embedding 에서 빌드파일 private registry 배포(publish)
해당 폴더의 pyproject.toml 파일에 registry를 설정한다.
[[tool.uv.index]]
name = "podo"
url = "your private pypi registry address"
publish-url = "your private pypi registry address"
project.json 을 보면 nx-release-publish 설정이 되어 있다. nx-release-publish 는 npx nx build 재수행 후 publish를 수행한다.
$> npx nx nx-release-publish --index podo --username user01 --password user01_pwd
Building project src ...
Copying project files to a temporary folder
Resolving dependencies...
Generating sdist and wheel artifacts
Running command: uv build at /var/folders/bp/d8c3kvg54pvg8gjh2zj5bmdc0000gn/T/nx-python/build/0dec4085-ce4c-4842-ab1f-22269b421daf folder
Building source distribution...
Building wheel from source distribution...
Successfully built dist/aip_embedding-1.0.0.tar.gz
Successfully built dist/aip_embedding-1.0.0-py3-none-any.whl
Artifacts generated at packages/embedding/dist folder
Publishing project src ...
Running command: uv publish --index podo --username user01 --password user01_pwd at /var/folders/bp/d8c3kvg54pvg8gjh2zj5bmdc0000gn/T/nx-python/build/0dec4085-ce4c-4842-ab1f-22269b421daf folder
Publishing 2 files https://<your private pypi registry>/repository/pypi-sites/
Uploading aip_embedding-1.0.0-py3-none-any.whl (1.3KiB)
Uploading aip_embedding-1.0.0.tar.gz (21.3KiB)
NX Successfully ran target nx-release-publish for project src (3s)
또는 uv 명령으로 직접 배포하기. 직접할 때는 uv build 또는 npx nx build를 사전에 수행해야 한다.
$> uv publish --index <name> --username <username> --password <password>
ex) uv publish --index podo --username user01 --password user01_pwd
<참조>
https://angular.love/shell-library-patterns-with-nx-and-monorepo-architectures
Shell Library patterns with Nx and Monorepo Architectures
Angular.love - a place for all Angular enthusiasts created to inspire and educate.
angular.love
https://docs.astral.sh/uv/guides/package/#building-your-package
Building and publishing a package | uv
Introduction Guides uv supports building Python packages into source and binary distributions via uv build and uploading them to a registry with uv publish. Before attempting to publish your project, you'll want to make sure it's ready to be packaged for d
docs.astral.sh