Weaviate는 기계 학습 모델을 활용하여 의미 검색을 향상시키도록 설계된 선구적인 오픈 소스 벡터 데이터베이스입니다. 키워드 일치에 의존하는 기존 검색 엔진과 달리 Weaviate는 의미 유사성 원칙을 사용합니다. 이 혁신적인 접근 방식은 다양한 형태의 데이터 (텍스트, 이미지 등) 를 데이터의 맥락과 의미의 본질을 포착하는 수치 형태인 벡터 표현으로 변환합니다. Weaviate는 이러한 벡터 간의 유사점을 분석하여 사용자의 의도를 진정으로 이해하는 검색 결과를 제공하며 키워드 기반 검색의 한계를 뛰어넘는 획기적인 도약을 제공합니다.
이 가이드의 목적은 최고의 Kubernetes 기반 객체 스토리지와 AI 기반 의미 검색 기능을 활용하여 MinIO 와 Weaviate 의 원활한 통합을 보여주는 것입니다. 컨테이너 오케스트레이션을 위해 Docker Compose를 활용하는 이 가이드는 강력하고 확장 가능하며 효율적인 데이터 관리 시스템을 구축하기 위한 전략적 접근 방식을 제공합니다. 데이터를 저장, 액세스 및 관리하는 방법을 목표로 하는 이 설정은 최신 스토리지 솔루션과 AI 기반 데이터 검색의 성능을 활용하려는 개발자, DevOps 엔지니어 및 데이터 과학자를 위한 게임 체인저입니다.
이 데모에서는 Docker를 사용하여 MinIO 버킷으로 Weaviate를 백업하는 데 중점을 둘 것입니다. 이 설정은 AI로 강화된 검색 및 분석 프로젝트에서 데이터 무결성과 접근성을 보장합니다.
이 데모는 Docker를 사용하여 MinIO와 Weaviate의 원활한 통합을 강조하고 AI로 강화된 검색 및 분석 시스템을 백업하는 안정적인 방법을 보여주는 것을 목표로 합니다.
여기에 제공된 docker-compose.yaml
파일은 Weaviate의 원활한 설정을 위해 제작되었으며, 간소화되고 효율적인 데이터 관리에 대한 Weaviate의 노력을 강조합니다. 이 구성은 MinIO가 보안 스토리지 서비스로 작동하고 Weaviate가 고급 벡터 검색 기능을 위해 이 스토리지를 활용하는 강력한 환경을 가능하게 합니다.
그만큼
version: '3.8' services: weaviate: container_name: weaviate_server image: semitechnologies/weaviate:latest ports: - "8080:8080" environment: AUTHENTICATION_ANONYMOUS_ACCESS_ENABLED: 'true' PERSISTENCE_DATA_PATH: '/var/lib/weaviate' ENABLE_MODULES: 'backup-s3' BACKUP_S3_BUCKET: 'weaviate-backups' BACKUP_S3_ENDPOINT: 'play.min.io:443' BACKUP_S3_ACCESS_KEY_ID: 'minioadmin' BACKUP_S3_SECRET_ACCESS_KEY: 'minioadmin' BACKUP_S3_USE_SSL: 'true' CLUSTER_HOSTNAME: 'node1' volumes: - ./weaviate/data:/var/lib/weaviate
Docker-Compose: backups-s3
모듈이 활성화되고 play.min.io
MinIO 서버를 사용하여 Weaviate 배포
위 docker-compose.yaml을 사용하면 Weaviate는 백업에 MinIO를 활용하여 데이터 무결성과 접근성을 보장하도록 복잡하게 구성됩니다. 이 설정에는 backup-s3
으로 설정된 ENABLE_MODULES
와 같은 필수 환경 변수와 S3 버킷, 엔드포인트, 액세스 키 및 SSL 사용에 대한 다양한 설정이 포함됩니다. 또한 데이터가 지속적으로 저장되도록 PERSISTENCE_DATA_PATH
설정되고 노드 식별을 위해 CLUSTER_NAME
설정됩니다.
ENABLE_MODULES
: '백업-s3'BACKUP_S3_BUCKET
: '백업 약화'BACKUP_S3_ENDPOINT
: 'play.min.io:443'BACKUP_S3_ACCESS_KEY_ID
: 'minioadmin'BACKUP_S3_SECRET_ACCESS_KEY
: 'minioadmin'BACKUP_S3_USE_SSL
: '참'PERSISTENCE_DATA_PATH
: '/var/lib/weaviate'CLUSTER_NAME
: '노드1'
이 docker-compose의 Weaviate 서비스는 데이터 지속성을 위해 마운트된 볼륨을 활용하도록 설정되었습니다. 이렇게 하면 세션과 작업 전반에 걸쳐 데이터가 유지됩니다.
참고: MinIO 버킷이 미리 존재해야 하며 Weaviate에서는 버킷을 생성하지 않습니다.
Docker Compose를 사용하여 MinIO 및 Weaviate를 프로젝트에 통합하려면 다음 세부 절차를 따르세요.
Docker Compose 파일 저장 또는 업데이트
docker-compose.yaml 파일이 준비되면 터미널이나 명령 프롬프트에서 다음 명령을 사용하여 배포를 시작합니다.
docker-compose up -d --build
이 명령은 분리 모드에서 Weaviate 서비스를 시작하여 시스템 백그라운드에서 실행합니다.
빌드 및 실행 프로세스 중에 Docker Compose는 docker-compose.yaml 파일에 지정된 대로 영구 디렉터리를 생성합니다. 이 디렉터리 ( Weaviate의 경우 ./weaviate/data
)는 데이터를 지속적으로 저장하는 데 사용되므로 컨테이너를 다시 시작하고 배포해도 데이터가 그대로 유지됩니다.
영구 스토리지를 사용하면 컨테이너를 다시 시작해도 데이터가 손실되지 않는 보다 안정적인 환경이 가능합니다.
docker-compose를 배포한 후에는 브라우저에서 Weaviate 서버의 URL을 방문하고 /v1/meta
방문하여 배포 구성이 올바른지 확인할 수 있습니다.
http://localhost:8080/v1/meta
에 있는 JSON 페이로드의 첫 번째 줄은 다음과 같아야 합니다.
{"hostname":"http://[::]:8080","modules":{"backup-s3":{"bucketName":"weaviate-backups","endpoint":"play.min.io:443","useSSL":true}...[truncated]...}
weaviate-backups
버킷에 대한 액세스 정책 Weaviate를 MinIO와 통합하려면 MinIO의 백업 버킷에 지정된 백업 버킷, 즉 weaviate-backups
의 공개 액세스 정책이 적절하게 필요합니다. 이 조정은 Weaviate backup-s3 모듈에 백업 작업을 위해 MinIO 버킷과 성공적으로 상호 작용하는 데 필요한 권한을 부여하는 데 필요합니다.
참고: 프로덕션 환경에서는 이를 잠가야 할 수도 있지만 이는 이 튜토리얼의 범위를 벗어납니다.
버킷을 " 공개 " 로 설정하는 경우 보안에 미치는 영향을 명확하게 이해하고 이 구성에 접근하는 것이 중요합니다. 이 설정은 개발 환경에서 백업 프로세스를 용이하게 하지만 프로덕션 시스템에서는 데이터 보안과 무결성을 유지하기 위해 대체 접근 방식을 고려해야 합니다. IAM 정책 또는 " 미리 서명된 " URL과 같은 세분화된 액세스 제어를 사용합니다.
이 데모가 끝나면 backup-s3
모듈을 활용할 때 Weaviate가 프로세스 전반에 걸쳐 생성하는 버킷 객체를 볼 수 있습니다.
Weaviate에서 S3 백업을 활성화하려면 docker-compose.yaml 파일에 필요한 환경 변수를 설정하세요. 이는 Weaviate가 백업 모듈 및 MinIO 버킷 세부 정보 설정과 관련하여 MinIO를 백업 대상으로 사용하도록 지시합니다.
기술 작업을 시작하기 전에 여기에서 사용할 수 있는 노트북에 파이프라인을 캡슐화하는 추가 이점을 위해 JupyterLab 환경에서 다음 단계를 시연하고 있음을 말씀드리고 싶습니다.
첫 번째 단계에서는 pip
사용하여 Python용 weaviate-client
라이브러리를 설치하여 환경을 설정합니다. 이 Python 패키지는 Weaviate의 RESTful API와 보다 Python적인 방식으로 인터페이스하여 스키마 생성, 데이터 인덱싱, 백업 및 복원과 같은 작업을 위해 데이터베이스와 원활하게 상호 작용하는 데 필수적입니다. 데모에서는 Weaviate Python 클라이언트 라이브러리를 사용하여 설명하겠습니다.
이 데모에서는 Weaviate V3 API를 사용하므로 Python 스크립트를 실행할 때 아래와 같은 메시지가 표시될 수 있습니다.
`DeprecationWarning: Dep016: You are using the Weaviate v3 client, which is deprecated. Consider upgrading to the new and improved v4 client instead! See here for usage: https://weaviate.io/developers/weaviate/client-libraries/python warnings.warn(`
이 메시지는 경고 배너이므로 무시해도 됩니다. 자세한 내용을 보려면 여기를 방문하세요.
!pip install weaviate-client
이 섹션에서는 'Article' 및 'Author' 클래스의 데이터 구조와 스키마를 소개하고 데이터 구성 방법에 대한 기초를 마련합니다. Weaviate 내에서 스키마를 프로그래밍 방식으로 정의하고 관리하는 방법을 보여 주며, 특정 애플리케이션 요구 사항에 맞는 다양한 데이터 모델에 적응할 수 있는 Weaviate의 유연성과 강력함을 보여줍니다.
import weaviate client = weaviate.Client("http://localhost:8080") # Schema classes to be created schema = { "classes": [ { "class": "Article", "description": "A class to store articles", "properties": [ {"name": "title", "dataType": ["string"], "description": "The title of the article"}, {"name": "content", "dataType": ["text"], "description": "The content of the article"}, {"name": "datePublished", "dataType": ["date"], "description": "The date the article was published"}, {"name": "url", "dataType": ["string"], "description": "The URL of the article"}, {"name": "customEmbeddings", "dataType": ["number[]"], "description": "Custom vector embeddings of the article"} ] }, { "class": "Author", "description": "A class to store authors", "properties": [ {"name": "name", "dataType": ["string"], "description": "The name of the author"}, {"name": "articles", "dataType": ["Article"], "description": "The articles written by the author"} ] } ] } client.schema.delete_class('Article') client.schema.delete_class('Author') client.schema.create(schema)
Python: 스키마 클래스 생성
스키마를 정의한 후 노트북은 Weaviate 클라이언트 초기화, Weaviate 인스턴스에 스키마 생성, 데이터 인덱싱 과정을 안내합니다. 이 프로세스는 데이터베이스를 초기 데이터 세트로 채워 Weaviate의 벡터 검색 기능을 탐색할 수 있게 해줍니다. 이는 데이터를 벡터화된 형식으로 저장하고 쿼리하기 위해 Weaviate를 활용하는 데 필요한 실제 단계를 보여줍니다.
# JSON data to be Ingested data = [ { "class": "Article", "properties": { "title": "LangChain: OpenAI + S3 Loader", "content": "This article discusses the integration of LangChain with OpenAI and S3 Loader...", "url": "https://blog.min.io/langchain-openai-s3-loader/", "customEmbeddings": [0.4, 0.3, 0.2, 0.1] } }, { "class": "Article", "properties": { "title": "MinIO Webhook Event Notifications", "content": "Exploring the webhook event notification system in MinIO...", "url": "https://blog.min.io/minio-webhook-event-notifications/", "customEmbeddings": [0.1, 0.2, 0.3, 0.4] } }, { "class": "Article", "properties": { "title": "MinIO Postgres Event Notifications", "content": "An in-depth look at Postgres event notifications in MinIO...", "url": "https://blog.min.io/minio-postgres-event-notifications/", "customEmbeddings": [0.3, 0.4, 0.1, 0.2] } }, { "class": "Article", "properties": { "title": "From Docker to Localhost", "content": "A guide on transitioning from Docker to localhost environments...", "url": "https://blog.min.io/from-docker-to-localhost/", "customEmbeddings": [0.4, 0.1, 0.2, 0.3] } } ] for item in data: client.data_object.create( data_object=item["properties"], class_name=item["class"] )
Python: 클래스별로 데이터 색인화
데이터가 인덱싱되면 백업을 통해 데이터베이스 상태를 보존하는 데 초점이 맞춰집니다. 노트북의 이 부분은 MinIO에 대한 백업 작업을 트리거하는 방법을 보여줍니다.
result = client.backup.create( backup_id="backup-id", backend="s3", include_classes=["Article", "Author"], # specify classes to include or omit this for all classes wait_for_completion=True, ) print(result)
Python: 백업 생성
예상하다:
{'backend': 's3', 'classes': ['Article', 'Author'], 'id': 'backup-id-2', 'path': 's3://weaviate-backups/backup-id-2', 'status': 'SUCCESS'}
성공적인 백업 응답
복원을 진행하기 전에 기존 스키마를 지워야 하는 경우가 있습니다. 이 섹션에서는 깔끔한 복원 프로세스를 위한 단계를 보여줍니다. 이렇게 하면 복원된 데이터가 데이터베이스 내의 기존 스키마 또는 데이터와 충돌하지 않습니다.
client.schema.delete_class("Article") client.schema.delete_class("Author")
이 섹션에서는 이전에 백업한 데이터를 복원하여 데이터베이스를 알려진 양호한 상태로 되돌리는 방법에 대해 설명합니다.
result = client.backup.restore( backup_id="backup-id", backend="s3", wait_for_completion=True, ) print(result)
Python: 백업 복원
예상하다:
{'backend': 's3', 'classes': ['Article', 'Author'], 'id': 'backup-id', 'path': 's3://weaviate-backups/backup-id', 'status': 'SUCCESS'}
성공적인 Backup-S3 응답
노트북의 이 부분에서는 백업 복원 프로세스 중 오류 처리를 구현하는 예를 제공합니다. 데이터 복원 작업 중 예상치 못한 문제에 대한 통찰력을 제공합니다.
from weaviate.exceptions import BackupFailedError try: result = client.backup.restore( backup_id="backup-id", backend="s3", wait_for_completion=True, ) print("Backup restored successfully:", result) except BackupFailedError as e: print("Backup restore failed with error:", e) # Here you can add logic to handle the failure, such as retrying the operation or logging the error.
예상하다:
Backup restored successfully: {'backend': 's3', 'classes': ['Author', 'Article'], 'id': 'backup-id', 'path': 's3://weaviate-backups/backup-id', 'status': 'SUCCESS'}
성공적인 백업 복원
마지막으로 백업 및 복원 프로세스가 성공적으로 완료되었는지 확인하기 위해 노트북에는 'Article' 클래스의 스키마를 검색하는 단계가 포함되어 있습니다. 이 확인을 통해 데이터와 스키마가 올바르게 복원되었는지 확인합니다.
client.schema.get("Article")
Article 클래스를 JSON 객체로 반환합니다.
예상하다:
{'class': 'Article', 'description': 'A class to store articles'... [Truncated]...}
노트북의 각 섹션은 Weaviate-client 라이브러리를 사용하여 Python 생태계 내에서 수행되는 초기 설정 및 데이터 입력부터 백업, 복원 및 확인에 이르기까지 Weaviate의 데이터 관리 수명주기에 대한 포괄적인 가이드를 제공합니다.
지금까지 우리는 Python 방식으로 이를 수행하는 방법을 보여주었습니다. 우리는 스크립트를 작성하지 않고도 동일한 작업을 수행할 수 있는 방법을 CURL
통해 내부적으로 보여주는 것이 도움이 될 것이라고 생각했습니다.
스키마 생성, 데이터 인덱싱, 백업 수행, 데이터 복원과 같은 작업을 위해 Weaviate 인스턴스와 상호 작용하려면 특정 컬 명령을 사용할 수 있습니다. 이 명령은 Weaviate의 REST API에 HTTP 요청을 보냅니다. 예를 들어 스키마를 생성하려면 스키마 세부 정보가 포함된 POST 요청이 Weaviate의 스키마 엔드포인트로 전송됩니다. 마찬가지로 데이터를 인덱싱하기 위해 데이터 페이로드가 포함된 POST 요청이 개체 엔드포인트에 수행됩니다.
백업은 백업 엔드포인트에 대한 POST 요청을 통해 트리거되고, 복원은 복원 엔드포인트에 대한 POST 요청을 통해 수행됩니다. 이러한 각 작업에는 일반적으로 @
기호를 사용하여 컬 명령에서 파일 참조로 제공되는 적절한 JSON 페이로드가 필요합니다.
Weaviate를 구현하려면 물론 작업할 샘플 데이터가 필요합니다.
나는 다음을 포함했습니다:
schema.json
인덱싱하려는 데이터의 구조를 간략하게 설명합니다.
data.json
실제 데이터가 작용하는 곳이며, 그 구조는 Schema.json 파일의 클래스와 일치합니다.
Schema.json 및 data.json 파일은 다음 위치에 있는 MinIO 블로그 자산 저장소에서 사용할 수 있습니다.
{ "classes": [ { "class": "Article", "description": "A class to store articles", "properties": [ {"name": "title", "dataType": ["string"], "description": "The title of the article"}, {"name": "content", "dataType": ["text"], "description": "The content of the article"}, {"name": "datePublished", "dataType": ["date"], "description": "The date the article was published"}, {"name": "url", "dataType": ["string"], "description": "The URL of the article"}, {"name": "customEmbeddings", "dataType": ["number[]"], "description": "Custom vector embeddings of the article"} ] }, { "class": "Author", "description": "A class to store authors", "properties": [ {"name": "name", "dataType": ["string"], "description": "The name of the author"}, {"name": "articles", "dataType": ["Article"], "description": "The articles written by the author"} ] } ] }
Article 및 Author에 대한 예제 스키마 클래스
그만큼
반면,
[ { "class": "Article", "properties": { "title": "LangChain: OpenAI + S3 Loader", "content": "This article discusses the integration of LangChain with OpenAI and S3 Loader...", "url": "https://blog.min.io/langchain-openai-s3-loader/", "customEmbeddings": [0.4, 0.3, 0.2, 0.1] } }, { "class": "Article", "properties": { "title": "MinIO Webhook Event Notifications", "content": "Exploring the webhook event notification system in MinIO...", "url": "https://blog.min.io/minio-webhook-event-notifications/", "customEmbeddings": [0.1, 0.2, 0.3, 0.4] } }, { "class": "Article", "properties": { "title": "MinIO Postgres Event Notifications", "content": "An in-depth look at Postgres event notifications in MinIO...", "url": "https://blog.min.io/minio-postgres-event-notifications/", "customEmbeddings": [0.3, 0.4, 0.1, 0.2] } }, { "class": "Article", "properties": { "title": "From Docker to Localhost", "content": "A guide on transitioning from Docker to localhost environments...", "url": "https://blog.min.io/from-docker-to-localhost/", "customEmbeddings": [0.4, 0.1, 0.2, 0.3] } } ]
기사가 포함된 샘플 데이터
스키마는 데이터 관리 시스템의 구조적 백본 역할을 하며 데이터 구성, 색인화 및 쿼리 방법을 정의합니다.
간단한 컬 명령을 통해 현재 작업 디렉터리에 로컬로 복제된 샘플 파일을 사용합니다. 우리는 Schema.json을 Weaviate에 직접 게시하여 데이터가 준수할 규칙과 관계를 설정할 수 있습니다.
curl -X POST -H "Content-Type: application/json" \ --data @schema.json http://localhost:8080/v1/schema
컬: 생성
스키마가 준비되면 다음 단계에서는 스키마를 실제 데이터로 채우는 작업이 포함됩니다. 다른 컬 명령을 사용하여 data.json을 스키마에 인덱싱합니다.
curl -X POST -H "Content-Type: application/json" \ --data @data.json http://localhost:8080/v1/objects
컬: 인덱스
고유 식별자, 즉 "backup-id"를 할당해야 합니다. 이 식별자는 백업 세트의 정확한 추적 및 검색을 용이하게 할 뿐만 아니라 각 데이터 세트의 버전이 제어되도록 보장합니다.
curl -X POST 'http://localhost:8080/v1/backups/s3' -H 'Content-Type:application/json' -d '{ "id": "backup-id", "include": [ "Article", "Author" ] }'
컬: 백업-s3
예상하다:
{'backend': 's3', 'classes': ['Article', 'Author'], 'id': 'backup-id', 'path': 's3://weaviate-backups/backup-id', 'status': 'SUCCESS'}
성공적인 Backup-S3 응답
이 출력은 JSON 개체로 형식화됩니다. 여기에는 사용된 백엔드(이 경우 's3'
), 백업에 포함된 클래스 목록( 'Article'
, 'Author'
), 백업에 제공된 고유 식별자 ID( 'backup-id'
)가 포함됩니다. , S3 버킷 내에서 백업이 저장되는 위치를 나타내는 경로( s3://weaviate-backups/backup-id
) 및 작업 상태( 'SUCCESS'
).
이 구조화된 응답은 백업 프로세스의 성공적인 완료를 확인할 뿐만 아니라 향후 참조, 감사 또는 복원 프로세스에 사용할 수 있는 필수 정보도 제공합니다.
Weaviate 생태계 내 데이터 복원은 backup-id로 식별되는 /v1/backups/s3/backup-id/restore 엔드포인트를 대상으로 하는 POST 요청을 통해 구조화된 API 호출을 통해 촉진됩니다. 이 컬 호출은 손실되거나 보관된 데이터를 복원할 뿐만 아니라 연속성을 유지할 수 있게 해줍니다.
curl -X POST 'http://localhost:8080/v1/backups/s3/backup-id/restore' \ -H 'Content-Type:application/json' \ -d '{ "id": "backup-id", "exclude": ["Author"] }'
컬: 복원
예상하다:
{ "backend": "s3", "classes": ["Article"], "id": "backup-id", "path": "s3://weaviate-backups/backup-id", "status": "SUCCESS" }
성공적인 복원 대응
이러한 각 명령은 특정 설정 및 요구 사항에 따라 조정되어야 합니다. 필요에 따라 엔드포인트 URL, 데이터 파일 경로 및 기타 매개변수를 수정해야 할 수도 있습니다. 또한 필요한 파일(schema.json, data.json) 및 구성을 환경에서 사용할 수 있는지 확인하십시오.
Git의 모든 것을 코드화함으로써 팀은 변경 사항을 쉽게 추적하고, 이전 상태로 롤백하고, 환경 전반에서 일관성을 보장할 수 있습니다. GitOps 워크플로는 CI/CD(지속적 통합/지속적 배포) 도구 및 Kubernetes와 통합되어 컨테이너화된 애플리케이션 및 인프라 관리의 조정을 더욱 단순화할 수 있습니다. GitOps를 사용하여 자동화하는 방법에 대해서는 향후 게시물에서 자세히 설명하겠습니다.
Weaviate를 사용하면 특정 클래스를 백업하거나 복원할 수 있으므로 부분 데이터 마이그레이션이나 개발 테스트와 같은 경우에 유용합니다.
다중 노드 백업: 특히 Kubernetes 환경에서 다중 노드 설정의 경우 구성이 백업 모듈(예: MinIO의 경우 backup-s3) 및 관련 환경 변수를 올바르게 지정하는지 확인하십시오.
백업 또는 복원 중에 문제가 발생하면 특히 MinIO와 같은 S3 호환 스토리지에 대한 SSL 설정과 관련된 환경 변수 구성을 확인하세요. SSL을 비활성화하면( BACKUP_S3_USE_SSL: false
) 특정 연결 문제가 해결될 수 있습니다.
Docker Compose를 사용하여 Weaviate를 MinIO와 통합하는 탐색을 마무리하면서 이 조합이 단순한 기술 솔루션이 아니라 데이터 관리에 대한 전략적 향상이라는 것이 분명해졌습니다. 이 통합은 이제 Weaviate의 AI 기반 기능으로 증폭되는 확장 가능하고 안전하며 고성능 데이터 스토리지 솔루션을 제공하려는 MinIO의 약속과 완벽하게 일치합니다. Docker Compose를 사용하면 이러한 통합이 더욱 간소화되어 복잡한 기술에 액세스하고 관리할 수 있도록 하는 데 중점을 둡니다.
언제나 그렇듯이 MinIO 팀은 데이터 관리 분야의 혁신을 주도하기 위해 최선을 다하고 있습니다. 데이터가 저장, 액세스 및 분석되는 방식을 향상하고 간소화하려는 우리의 헌신은 우리 사명의 핵심입니다.
Weaviate의 고급 벡터 데이터베이스 기능과 MinIO가 제공하는 강력한 스토리지 솔루션을 결합함으로써 사용자는 데이터의 잠재력을 최대한 활용할 수 있습니다. 여기에는 데이터의 접근성뿐만 아니라 기초 수준의 보안도 보장하는 의미론적 검색 기능을 활용하는 것이 포함됩니다.
우리는 여러분과 같은 헌신적이고 열정적인 개발자들의 마음에서 솟아나는 놀라운 혁신에 진심으로 영감을 받았습니다. 우리는 귀하의 데이터 기반 프로젝트에서 고급 솔루션을 탐색하고 새로운 차원에 도달하기 위한 귀하의 여정에 지원을 제공하고 참여할 수 있게 되어 기쁘게 생각합니다. 주저하지 마시고 저희에게 연락주세요.