블로그 이미지
Peter Note
Web & LLM FullStacker, Application Architecter, KnowHow Dispenser and Bike Rider

Publication

Category

Recent Post

'[LLM FullStacker]/Peter AI Framework'에 해당되는 글 1

  1. 2025.03.05 Framework에서 Developer eXperience 란?

DX는 Developer eXperience 약어이다. UX가 User 관점의 경험이라면 DX는 개발자가 개발시에 어떻게 효율적으로 생산성을 높힐지에 관심을 갖는다. 개발 조직 및 개인 관점에서 좋은 DX란 무엇일까?

 

[1] 시작을 쉽게 할 수 있어야 한다. 

  - 설정이 많다면 installer를 통해 초기 설치 및 설정을 문답식으로 진행토록 한다. 

  - 설치이후 추가 요건에 대한 생성 및 설정을 위한 명령어가 제공되어야 한다. 

[2] 복잡하지 않아야 한다.

  - 설치이후 접근 편이성이 좋아야 한다. 즉, 폴더 구조가 간편하고 설정 파일이 적어야 한다. 즉, 컨벤션에 의한 동작이 필요하다. 

[3] 로컬에서 모든 것을 실행하고, 디버깅할 수 있다. 

  - 로컬 개발서버를 실행하고 디버깅할 수 있는 환경을 제공한다. 

  - LLM 접근의 경우 prompt 디버깅이 가능해야 한다. 

[4] 애플리케이션 개발을 위한 템플릿을 제공해야 한다.

  - 제네레이터를 통해 원하는 파일을 생성할 수 있다. 

[5] 컴파일 환경을 제공한다. 

  - 빠른 번들링 속도를 제공한다.

[6] 사용자 가이드를 제공한다. 

 

 

NX 의 Monorepo 아키텍처

NXMonorepo(모노레포) 아키텍처를 위한 도구로, 하나의 리포지토리에서 여러 개의 애플리케이션과 라이브러리를 함께 관리할 수 있도록 지원하는 빌드 시스템 및 개발 도구이다. 대규모 프로젝트로 팀단위로 일할 때 생산성을 향상시켜준다. 

 

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을 제공한다. 

Figure 1

 

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

 

posted by Peter Note
prev 1 next