728x90
반응형

Neo4j 데이터베이스를 사용한 .NET 코드 분석

이 글은 그래프 기반 코드 분석 분야에 대한 소개글이에요. 저는 Vlad이고, 아고다의 기술 책임자입니다. 지난 4년 동안 게이트웨이 API의 깔끔한 아키텍처 재설계를 포함해서 고부하 시스템의 아키텍처 변경 작업을 진행해 왔어요. 아고다 웹사이트 모듈화 관련 작업도 했었죠.

오늘은 그래프 기반 코드 분석의 기본 개념에 대해 알아보고, Strazh를 사용해서 .NET Core 프로젝트용 코드베이스 Knowledge Graph(또는 코드 Knowledge Graph, 간단히 CKG라고도 해요)를 구축하는 방법을 살펴볼게요.

  • 코드베이스 Knowledge Graph: 프로그래밍 언어에 구애받지 않는 그래프 개념이에요.
  • 스트라즈: C# 코드베이스에서 코드베이스 Knowledge Graph를 구축하는 도구입니다.

이 문서에서는 C# 코드베이스의 예를 사용할 건데요. 혹시 C#에 익숙하지 않더라도 이 문서가 도움이 될 거라고 생각해요. 코드베이스 Knowledge Graph의 개념은 보편적이거든요. 이 개념을 배우고 여러분이 선호하는 언어에 대한 그래프 빌더를 직접 만들어 볼 수도 있겠죠?

작동 방식

C# 코드 분석에 대해 이야기할 때, 항상 Roslyn 컴파일러를 빼놓을 수 없죠. Roslyn 규칙은 코드를 분석하고 코드 품질을 향상시키는 데 아주 잘 알려진 방법이기도 하고요.

다음과 같은 라이브러리들, 예를 들어 SonarAnalyzer.CSharp, Microsoft.VisualStudio.Threading.Analyzers, AsyncFixer, 그리고 아고다 사내 라이브러리인 아고다.분석기는 코드베이스에서 "코드 냄새"를 잡아내는 데 아주 유용한 도구들이에요. "이것 대신 저것을 사용하세요", "이것은 피하고 저것을 선호하세요" 와 같은 규칙들을 알려주죠.

제 경험상 대부분의 개발자들은 코드 분석에 관심이 많고, 자신의 기술 도구 상자에 이런 지식이 있으면 좋겠다고 생각하는 것 같아요.

저는 코드 분석을 한 단계 더 발전시켜서, 코드베이스를 다른 방식으로 분석할 수 있는 능력을 만들기로 결심했어요.

아이디어는 간단해요. 프로젝트 정보를 수집해서 그래프를 만들어보는 거죠!

코드베이스를 그래프로 만들면, 그래프를 탐색하고, 데이터를 `Query`하고, 코드 요소인 그래프의 `Node`와 `Relationship`을 분석할 수 있어요. Roslyn 규칙을 작성하는 대신, Cypher `Query`를 사용해서 코드 분석을 하는 거죠.

Strazh는 말 그대로 "보호자"라는 뜻이에요. 원래 매트릭스 영화에서 Sentinel, 일명 "squiddy"라고 불리는 Zion Guardians를 참고한 이름이죠. (Neo4j 자체, Cypher, APOC 같은 Neo4j 제품군 이름들도 매트릭스 세계에서 따온 거랍니다.)

예시

이건 간단한 클래스인 LoggerProviderAdapter를 그래프 구조로 변환한 모습이에요.

다음과 같은 코드 요소들의 그래프를 볼 수 있어요.

  • LoggerProviderAdapter (진한 녹색 `Node`)
  • 인터페이스 ILoggerAdapter (연한 녹색 `Node`)
  • 이 클래스가 선언된 (노란색 `Node`)
  • (파란색 `Node`)

보시다시피 Debug 메서드를 호출하는 LogDebug 메서드는 LoggerProviderAdapter 클래스의 메서드가 아니에요. 만약 그랬다면 이 클래스와도 `Relationship`이 있었겠죠.

왜 유용할까요?

그래프 기반 분석은 Roslyn 규칙을 대체하려는 게 아니라, 다음과 같은 흥미로운 가능성으로 여러분의 도구 상자를 더욱 풍성하게 만들어주는 대안적인 기술이에요.

  • 풍부한 시각화를 통해 다양한 코드베이스 통찰력에 빠르게 접근 (Neo4j Browser, Bloom 및 기타 Neo4j 도구)
  • 설계 위반 및 실수를 잡아낼 수 있는 능력
  • 다양한 적용 범위와 통계 정보를 찾을 수 있는 기능
  • 변경 사항, 기능, 리팩토링을 예측하는 데 도움을 줘요.

그래프 생성

먼저 그래프 생성이 어떻게 이루어지는지 설명하고, 그래프 자체에 대해 이야기해볼게요. 이 섹션에서는 코드베이스에서 그래프로의 변환이 기술적으로 어떻게 작동하는지 빠르게 살펴볼 거예요.

C# 코드베이스에서 그래프를 생성하기 위해, C#으로 작성된 .NET Core 콘솔 애플리케이션인 Strazh를 만들었어요. 이 애플리케이션은 Docker 컨테이너로 실행할 수도 있답니다. 이 글 마지막 부분에서 Strazh를 직접 사용해 볼 거예요.

기술적인 관점에서 Strazh는 ETL (Extract, Transform, Load) 도구라고 할 수 있어요. 코드베이스 `Knowledge Graph`를 구축하는 과정은 다음과 같아요. 먼저, 코드베이스 모델을 **추출(Extract)**해야 해요. 그런 다음 모델을 RDF 트리플로 **변환(Transform)**하고, 마지막으로 RDF 트리플을 `Graph Database`에 **로드(Load)**해서 그래프의 `Node`와 `Relationship`을 만드는 거죠.

구문 및 의미 트리
프로그램 코드는 프로그래밍 언어의 구문과 의미론의 조합으로 이루어져 있어요. 구문은 기호의 조합이 유효한 코드임을 정의하는 문법이고, 의미론은 구문 구조에 의미를 부여하는, 즉 작동 코드 모델에 대한 추상화 계층이라고 할 수 있죠.

static string GetFullName(string firstName, string lastName)
  => firstName + lastName;
구문 트리 (LINQPad)의 예

Roslyn 분석기
Roslyn은 코드 분석을 위한 API를 제공하는 강력한 .NET 컴파일러에요. 구문 및 의미 트리를 탐색해서 코드베이스를 샅샅이 뒤져 원하는 정보를 추출할 수 있죠.

RDF 트리플
RDF (Resource Description Framework), 즉 시맨틱 트리플은 사실을 표현하는 데 사용되는 특정 구조에요. RDF 트리플은 주어 - 술어 - 객체라는 표현을 기반으로 하죠. 코드베이스 의미 모델은 코드에서 추출되어 RDF 트리플로 변환돼요. 이제 RDF 트리플 컬렉션이 있으니, 여기서 그래프를 만들 수 있겠죠?

다시 LoggerProviderAdapter로 돌아가서, RDF 트리플의 예를 살펴볼까요?

  • 주어: "클래스 LoggerProviderAdapter" (`Node`: 클래스)
  • 술어: 'have' (`Relationship`: HAVE)
  • 객체: "메서드 Debug" (`Node`: 메서드)
트리플의 예: 파일에 선언된 클래스. 클래스에는 메서드가 있습니다. 메서드는 다른 메서드를 호출합니다.

그래프 빌더는 프로젝트의 소스 코드를 컴파일하고, 알려진 의미 체계 모델을 RDF 트리플로 추출해서 데이터베이스에 삽입해 그래프를 만드는 역할을 해요.

지금까지는 괜찮았죠? 이제 Codebase Knowledge Graph에 대해 자세히 알아보고 그래프 스키마를 살펴볼게요.

Codebase Knowledge Graph

그래프 기본 사항

Knowledge Graph는 자유 형식 데이터를 엔터티 네트워크, 해당 의미 유형, 속성 및 관계로 통합하는 그래프 구조 모델이에요. 여기서 자유 형식이라는 점이 정말 중요해요. 그래프를 만드는 데 사용하는 데이터가 많을수록 더 유용한 통찰력을 얻을 수 있거든요.

Codebase Knowledge Graph는 코드베이스의 엔터티, 프로그래밍 언어의 의미론적 모델, 프로젝트 구조 및 기타 상호 연결된 지식 간의 자유로운 형식 관계를 가진 그래프 구조의 데이터 세트라고 할 수 있어요.

Codebase Knowledge Graph 레이어

각 레이어는 서로 연결되어 코드베이스에 대한 강력한 분석 정보를 제공하죠. 그래프 스키마를 살펴보고 레이어를 위에서 아래로 하나씩 살펴볼까요?

Codebase Knowledge Graph 스키마

최상위 수준에는 와 가 있어요. 이 레이어는 아키텍처 개요를 확인하고 디자인 결정을 내리는 데 도움을 줘요. 이 레이어를 사용하면 프로젝트 간의 종속성을 탐색할 수 있죠. 아래는 간단한 예시예요.

UnitTests 프로젝트는 UnitTests에서 사용되는 확장된 패키지(주황색 node)가 있는 프로젝트(빨간색 node)에 따라 달라져요.

마이그레이션 단계 중 아고다 웹사이트의 모듈식 재설계에서, 어떤 시점에서는 단일 솔루션에 약 70개의 프로젝트가 있었어요.

Codebase Knowledge Graph는 심각한 종속성 위반을 포착하고 초기 단계에서 수정하는 데 도움을 줄 수 있어요.

프로젝트 종속성

물론, 동일한 다이어그램을 얻을 수 있는 기존 도구도 있지만, Neo4j는 솔루션 및 코드베이스 레이어를 탐색할 수 있는 다양한 옵션을 제공한다는 장점이 있죠. Cypher, APOC, DGS, Neo4j 브라우저, Bloom 등 다양한 기본 도구를 빠르고 쉽게 사용할 수 있다는 것도 매력적이고요.

좀 더 깊이 들어가면 구조화할 파일 시스템 계층이 있어요. 바로 와 이죠. 이 레이어는 프로젝트가 진행될 때 프로젝트 구조의 정확성을 검증하는 데 유용한 데이터예요. 모든 표준 패턴을 따르는지 확인하는 데도 도움이 되고요.

패턴 지향 소프트웨어 아키텍처 – Wikipedia

전체 파일 시스템 트리를 반환하므로 파일 및 폴더 탐색이 간단해져요.

노란색 node는 폴더이고 회색 node는 파일이에요. 빨간색 node는 프로젝트고요.


다음 레이어는 주요 코드 단위의 모음이에요. 바로 와 인터페이스죠. 클래스는 코드베이스의 필수적인 부분이며, 이 레이어를 사용하면 OOP 방식과 디자인 패턴을 분석할 수 있어요.

디자인 패턴 - 위키피디아

예를 들어 인터페이스에 선언되고 동시에 클래스에 구현되는 각 메서드를 살펴볼 수 있어요.

새로운 관계 [:IMPLEMENTED_AS]를 구축하고 이를 사용해서 코드베이스 전체를 보다 효율적으로 탐색할 수 있죠. 이는 또한 소프트웨어 설계 공간을 쿼리하고 탐색할 수 있는 더 나은 언어를 갖기 위해 더 높은 수준의 개념으로 Knowledge Graph를 풍부하게 만들어 줘요.

시각적으로 보면 이렇게 아름답답니다.


행동 양식(Method)은 유형(Type)을 인스턴스화하는 또 다른 방법이라고 할 수 있어요. 이 레이어는 애플리케이션 비즈니스 로직의 핵심이고, 그래프의 주요 부분을 구성하죠. 이 계층을 사용하면 프로그램 비즈니스 로직을 탐색하고 애플리케이션 기능 간의 관계를 찾을 수 있어요.

예를 들어, "BuildKnowledgeGraph" 메서드를 전이적으로 호출하는 다른 메서드를 찾을 수 있죠.

Strazh 프로젝트의 메소드 호출 체인은 "BuildKnowledgeGraph" 메소드에서 시작되었어요.

이제 코드베이스에서 코드베이스 Knowledge Graph를 구축해 볼까요! 여러분의 코드베이스는 여러분의 지식 정보나 다름없으니까요.

Strazh의 활동

Strazh는 콘솔 앱이고, 실행을 위해 표준 명령줄 인터페이스를 사용해요.

Usage:
   [options]
Options:
  -c, --자격 증명 (REQUIRED)
required information in format `dbname:user:password` to connect to Neo4j Database
-t, --tier
optional flag as `project` or `code` or 'all' (default `all`) selected tier to scan in a codebase
-d, --삭제
optional flag as `true` or `false` or no flag (default `true`) to delete data in graph before execution
-s, --솔루션 (REQUIRED)
optional absolute path to only one `.sln` file (can't be used together with -p / --projects)
-p, --프로젝트 (REQUIRED)
optional list of absolute path to one or many `.csproj` files (can't be used together with -s / --solution)
--버전                                   
show version information
-?, -h, --help                                
show help and usage information

단일 기반으로 코드베이스 분석을 요청할 수 있어요. 금액에 관계없이 목록을 제출하거나 제공합니다.  — 하지만 그것들을 혼합하지는 마세요. 또한 Neo4j 데이터베이스의 , 분석할 tier를 제공해야 해요. Strazh는 특정 계층에 대해서만 그래프를 분석하고 구축하거든요.

계층 “”에는 두 개의 그래프 레이어가 포함되어 있어요.

계층 “Code”에는 두 개의 그래프 레이어가 포함되어 있어요.

계층 분리는 아키텍처 및 코드 수준 결과에 대한 요구 사항을 차별화하기 위해 특별히 만들어졌어요. 프로젝트 다이어그램만 필요한 경우 '프로젝트' 계층을 실행해서 시간을 절약할 수 있죠.

도커

Strazh는 Docker Hub의 Docker 이미지로 사용할 수 있어요. 컨테이너를 끌어서 실행하기만 하면 되죠. 프로세스 속도를 높이려면 docker-compose 파일을 사용하는 게 좋을 거예요.

예 1: 솔루션
이 docker-compose 파일 예제에서는 "프로젝트" 계층만 사용하여 솔루션 파일을 분석해요. 그러면 다음과 같은 그래프가 생성되죠. 그리고 그들의 그리고 그들 사이의 종속성.

Docker에 관한 몇 가지 팁:

  • 실행 중인 Neo4j Database 인스턴스가 필요하고 Strazh에 쓰기 권한이 있는 역할을 부여해야 해요. 서비스를 차례로 실행하세요.
  • 가장 쉬운 설정은 기본 관리자 역할 "neo4j"와 함께 기본 데이터베이스 "neo4j"를 사용하는 거예요. 보시다시피 제공된 'neo4j:neo4j:strazh' 자격 증명은 Neo4j의 준비된 NEO4J_AUTH: neo4j/strazh 설정과 일치하죠.
  • 또한 Neo4j를 사용하는 것은 항상 좋아요. APOC and GDS쿼리를 강화하는 플러그인이 포함되어 있거든요.

예시 2: 프로젝트
또 다른 예시에서는 명시적으로 제공된 두 프로젝트에 대해 기본 "모든" 계층을 사용하여 코드베이스 Knowledge Graph를 구축하는 방법을 보여줄 거예요. 이 예시는 프로젝트 + 단위 테스트라는 고전적인 쌍과 완벽하게 맞아떨어지죠.

Neo4j 서비스 구성은 동일해요. 모든 것을 올바르게 설정했다면 출력에 다음과 같은 내용이 표시될 거예요.

Strazh 출력

이제 Neo4j 브라우저(https://localhost:7474)에서 첫 번째 그래프 기반 코드 분석을 시작해 보세요!

언젠가 Strazh가 여러분의 프로젝트에 도움이 되기를 바라요. 만약 그렇다면 댓글로 여러분의 사례를 공유하는 것을 잊지 마세요.

읽어주셔서 감사해요.

기여자를 찾고 있어요

저는 2020년 3월에 Strazh 프로젝트의 첫 번째 코드 줄을 작성했고, 마침내 초기 버전의 오픈 소스 프로젝트가 beta 2021년 6월에 출시되었어요.

저는 오픈 소스 세계의 초보자이고 Strazh 프로젝트의 많은 부분을 개선해야 해요.

이것이 바로 여러분의 도움이 필요한 이유예요! 여러분이 관심 있다면 Strazh와 같은 이국적인 프로젝트를 포크하고 기여해 주세요.

블라드바투시코프/스트라즈

기여자를 환영합니다!

개인적인 감사 인사

피터 자보
스시미 슈레스타
세르게이 메시체랴코프
로이 골드버그
케티삭 친부라트

 


  • csharp

에이치시스템즈LogTree는 Neo4j 기반 GraphRAG 플랫폼으로, 데이터를 자동으로 지식그래프화하고 자연어 질의로 즉시 답을 제공합니다.

👉 에이치시스템즈 홈페이지

728x90
반응형

+ Recent posts