LightningChart .NET으로 1조 개 데이터 포인트 데이터 애플리케이션 만들기
소개
이번 LightningChart .NET 새 아티클에 오신 것을 환영합니다. 이 프로젝트에서는 각 채널이 독립적인 객체(또는 다중 스레드)로 실행되는 멀티 채널 차트를 생성하고, 최대 1조 개의 포인트 규모를 처리하는 프로세스를 추가합니다. 또한 실시간으로 프로세스를 제어할 수 있도록 여러 UI 컨트롤을 사용할 예정입니다.
LightningChart .NET은 .NET 환경을 위한 고도로 최적화된 차트 라이브러리로, 특히 대용량 데이터나 실시간 업데이트를 다룰 때 매우 유용합니다. 보다 범용적인 차트 솔루션과 달리, LightningChart .NET은 수백만 개의 데이터 포인트도 부드럽게 처리할 수 있습니다.
스레드와 동시성
프로그래밍에서 스레드(thread)는 프로세스 내에서 실행되는 기본 단위입니다. 하나의 프로그램은 여러 개의 스레드를 병렬로 실행할 수 있으며, 각 스레드는 특정 작업을 독립적으로 수행하도록 할당될 수 있습니다.
왜 스레드를 사용하나요?
예를 들어, 애플리케이션이 매우 방대한 양의 정보(예: 실시간으로 최대 1조 개의 데이터 포인트)를 처리해야 하면서 동시에 사용자 입력(클릭, 스크롤, 창 크기 조절 등)에 부드럽게 반응해야 한다고 가정해 봅시다. 이 모든 부하가 단일 스레드에 집중되면 인터페이스는 느려지거나 응답하지 않게 되며, 심한 경우 완전히 중단될 수도 있습니다. 이를 방지하기 위해 보조 스레드 또는 “백그라운드” 스레드를 사용하여, 사용자 경험을 저해하지 않으면서 연산 집약적인 작업을 처리합니다.
동시성이란 무엇인가요?
동시성(concurrency)은 여러 작업을 동시에 실행하거나, 작업 간을 효율적으로 전환하며 실행할 수 있도록 해줍니다. 작업 부하가 큰 애플리케이션의 경우, 그래픽 인터페이스를 담당하는 메인 스레드와 함께, 복잡한 계산, 데이터 분석, 대규모 정보 생성과 같은 작업을 처리하는 별도의 스레드를 사용하는 것이 일반적입니다.
이 프로젝트에서는 실시간 데이터 생성 및 처리를 전담하는 독립적인 스레드를 사용했으며, 이 스레드는 최대 1조 개의 데이터 포인트를 처리할 수 있습니다. 이를 통해 막대한 정보 부하 상황에서도 그래픽 인터페이스는 민첩하고 부드러우며, 완전히 인터랙티브한 상태를 유지할 수 있습니다.
샘플링 레이트
샘플링 레이트(sampling rate)는 연속 신호를 디지털 데이터로 변환하기 위해 초당 몇 개의 샘플을 취하는지를 나타냅니다. 예를 들어, 온도 센서의 값을 초당 100회 기록하고자 한다면, 샘플링 레이트는 100 Hz(초당 100 샘플)입니다.
왜 중요한가요?
적절한 샘플링 레이트는 신호를 정확하게 표현하는 데 필수적입니다. 너무 느리게 샘플링하면 중요한 변화를 놓치거나 부정확한 데이터가 생성될 수 있습니다. 반대로, 지나치게 빠른 샘플링은 시스템 자원에 부담을 줄 수 있을 정도로 과도한 데이터 양을 초래할 수 있습니다.
대규모 데이터 환경(예: 최대 1조(1,000,000,000,000) 개의 데이터 포인트를 처리하는 경우)에서는 올바른 샘플링 레이트를 선택하는 것이 더욱 중요해집니다. 효율적인 샘플링은 메모리나 연산 자원을 과도하게 소모하지 않으면서도 의미 있는 정보를 포착할 수 있도록 보장합니다.
이 프로젝트에서는 샘플링 레이트를 사용하여 경과 시간에 따라 생성되어야 할 샘플 수를 시뮬레이션함으로써, 차트 업데이트 리듬을 부드럽고 일관되게 유지합니다. 이 방식은 매우 높은 데이터 볼륨을 처리하는 상황에서도 효율성과 반응성을 유지하도록 설계되었습니다.
자, 이 간단한 소개를 마쳤으니 이제 프로젝트를 본격적으로 진행할 준비가 되었습니다. 시작해 봅시다!
프로젝트 개요
이 프로젝트를 따라 진행하려면, 필요한 모든 리소스가 포함된 ZIP 파일을 다운로드하세요.

로컬 설정
이 프로젝트를 컴파일하기 전에 다음 요구 사항을 충족해야 합니다.
OS: 32비트 또는 64비트 Windows Vista 이상, Windows Server 2008 R2 이상.
DirectX: 9.0c(Shader Model 3 이상) 또는 11.0과 호환되는 그래픽 어댑터.
Visual Studio: 개발용으로는 2022 버전 필요, 배포 시에는 필수 아님.
Platform .NET Framework: 8.0 이상 버전 설치 필요.
이제 다음 URL로 이동하여 LightningChart .NET을 다운로드하세요. 이후 로그인 페이지로 리디렉션되며, LightningChart 계정에 접근하기 위해 간단한 회원가입 절차를 완료해야 합니다.

계정에 로그인한 후, 이 튜토리얼에 필요한 주요 기능을 사용할 수 있는 SDK “free trial” 버전을 다운로드할 수 있습니다. SDK를 다운로드하면 다음과 같은 .exe 파일을 받게 됩니다:

설치는 일반적인 Windows 설치 과정이므로, 완료될 때까지 그대로 진행해 주세요. 설치가 끝나면 다음과 같은 프로그램들을 확인할 수 있습니다:

라이선스 매니저
이 애플리케이션에서는 구매 옵션을 확인할 수 있습니다. 이 트라이얼 SDK로 생성한 모든 프로젝트는 향후 개발 시에도 모든 기능이 활성화된 상태로 그대로 사용할 수 있습니다.

프로젝트 만들기
“interactive examples” 애플리케이션에서 예제를 실행하면 다음과 같은 옵션을 확인할 수 있습니다.

LightningChart는 현재 선택된 차트를 기반으로 Windows Presentation Foundation(WPF), WinForms, 그리고 해당 .NET 6 버전을 사용한 프로젝트를 생성할 수 있습니다.

추출 옵션을 선택하면 프로젝트용 새 폴더를 만들어야 합니다

프로젝트가 저장되면 Visual Studio가 스스로 열리고, 이런 프로젝트가 나올 것입니다

CreateChart() 메서드
이 CreateChart() 코드는 LightningChart를 사용하여 고성능 실시간 차트를 생성하고 구성하며, 최대 1조 개 이상의 데이터 포인트와 같은 대규모 데이터셋을 표시하도록 최적화되어 있습니다. 이 코드는 다음과 같은 요소들을 설정합니다.
빠른 업데이트를 위한 부드러운 렌더링과 레이아웃 구성
실시간 데이터 모니터링을 위한 스크롤 방식의 X축
오래된 데이터와 새로운 데이터를 시각적으로 구분하기 위한 그라디언트 효과
메모리 정리 및 고정 마진 설정과 같은 성능 최적화 요소
그 다음 차트를 UI에 추가하고 데이터 시각화를 시작합니다.
차트 초기화 및 구성
새로운 LightningChart 객체가 생성되며, 성능 최적화를 위해 BeginUpdate 블록 내에서 설정이 적용됩니다.
_chart = new LightningChart();
_chart.BeginUpdate();
_chart.ChartName = "1 Trillion Points";
_chart.ChartRenderOptions.DeviceType = RendererDeviceType.AutoPreferD11;
_chart.ChartRenderOptions.LineAAType2D = LineAntiAliasingType.QLAA;
차트 제목을 설정하고, 안티앨리어싱과 같은 렌더링 옵션 및 DirectX 렌더링 관련 설정을 구성하여 1조 개 데이터 포인트와 같은 대규모 데이터셋에서도 최적의 성능을 낼 수 있도록 합니다.
_chart.Title.Font.Size = 25;
_chart.Title.Text = "Digital Line Series 1 TRILLION (and more) data points showcase";//"Set options and press Start.\nPC with 16GB RAM + fast graphics card is strongly recommended";
//_chart.Title.Color = Color.FromArgb(255, 255, 204, 0);
_chart.Title.Align = ChartTitleAlignment.TopCenter;
ViewXY view = _chart.ViewXY;
실시간 데이터 스크롤을 위한 X축 설정
X축은 스크롤 방식으로 설정되어, 새로운 데이터가 유입될 때 자동으로 이동합니다. 가독성을 높이기 위해 레이블 형식, 축 제목, 표시 범위를 조정합니다. 또한 레이블 자동 포맷팅을 비활성화하고 고정 범위를 설정함으로써, 연속적인 데이터 처리에 필요한 고성능 동작을 가능하게 합니다.
//Set real-time monitoring scroll mode
view.XAxes[0].ScrollMode = XAxisScrollMode.Scrolling;
view.XAxes[0].SweepingGap = 0;
view.XAxes[0].ValueType = AxisValueType.Number;
view.XAxes[0].AutoFormatLabels = false;
view.XAxes[0].LabelsNumberFormat = "N0";
view.XAxes[0].Title.Text = "Point number";
view.XAxes[0].SetRange(0, 100000);
view.XAxes[0].MajorGrid.Pattern = LinePattern.Solid;
view.XAxes[0].Units.Text = "Points";
뷰 레이아웃과 성능 최적화
메모리 절약을 위해 오래된 데이터(DropOldSeriesData = true)를 실시간으로 정리할 수 있게 합니다.
//Set real-time monitoring automatic old data destruction
view.DropOldSeriesData = true;
Y축 배열은 여러 시리즈를 읽기 쉽게 하기 위해 맞춤 간격과 위치 조정으로 중첩되어 있습니다.
//Set Axis layout to Segmented
view.AxisLayout.YAxesLayout = YAxesLayout.Stacked;
view.AxisLayout.SegmentsGap = 2;
view.AxisLayout.YAxisAutoPlacement = YAxisAutoPlacement.LeftThenRight;
view.AxisLayout.YAxisTitleAutoPlacement = true;
마진은 대규모 데이터셋에서 비용이 많이 드는 레이아웃 재계산을 방지하기 위해 고정되어 있습니다.
// fix margins to prevent Graph resize, which may take long time for Billion points
view.AxisLayout.AutoAdjustMargins = false;
view.Margins = new Thickness(70, 35, 70, 40);
데이터 이동을 위한 시각적 스윕 효과 추가
두 개의 그라데이언트 밴드(어두운 띠와 밝은 띠)가 생성되어 X축에 묶여 있습니다. 이 밴드는 데이터의 스윕 또는 이동을 시각적으로 보여줍니다. 하나는 '기존' 데이터가 점점 사라지는 (어두움)을 나타내고, 다른 하나는 '새로운' 들어오는 데이터(밝음)를 강조합니다.
//Create a dark sweeping gradient band for old page
Band sweepBandDark = new Band(view, view.XAxes[0], view.YAxes[0])
{
BorderWidth = 0
};
sweepBandDark.Fill.Color = Color.FromArgb(255, 0, 0, 0);
sweepBandDark.Fill.GradientColor = Color.FromArgb(0, 0, 0, 0);
sweepBandDark.Fill.GradientFill = GradientFill.Linear;
sweepBandDark.Fill.GradientDirection = 0;
sweepBandDark.Binding = AxisBinding.XAxis;
sweepBandDark.AllowUserInteraction = false;
view.Bands.Add(sweepBandDark);
//Create a bright sweeping gradient band, for new page
Band sweepBandBright = new Band(view, view.XAxes[0], view.YAxes[0])
{
BorderWidth = 0
};
sweepBandBright.Fill.Color = Color.FromArgb(0, 0, 0, 0);
sweepBandBright.Fill.GradientColor = Color.FromArgb(150, 255, 255, 255);
sweepBandBright.Fill.GradientFill = GradientFill.Linear;
sweepBandBright.Fill.GradientDirection = 0;
sweepBandBright.Binding = AxisBinding.XAxis;
sweepBandBright.AllowUserInteraction = false;
view.Bands.Add(sweepBandBright);
UI 및 최종 손질
전설 상자는 UI를 정리하기 위해 숨겨져 있습니다. 차트 업데이트는 EndUpdate()로 끝나서 모든 것을 한 번에 렌더링해 효율성을 높입니다
//Don't show legend box
view.LegendBoxes[0].Visible = false;
_chart.EndUpdate();
UI에 차트 추가 및 렌더링 시작
차트는 UI 그리드 레이아웃의 지정된 행과 열에 추가됩니다. 마지막으로 Start()라고 불리며, 실시간 데이터 피드 또는 시뮬레이션을 시작하는 방법입니다.
gridMain.Children.Add(_chart);
Grid.SetRow(_chart, 0);
Grid.SetColumn(_chart, 1);
Start();
시작()Start() 메서드는 사용자 입력을 기반으로 새로운 디지털 라인 시리즈를 사용해 차트를 초기화합니다. 깨끗한 초기 상태를 보장하고, 필요한 모든 데이터를 생성하며, 축과 시리즈를 구성하고, 필요에 따라 데이터를 미리 로드합니다. 이 메서드는 여러 채널에 걸쳐 이진 형태의 신호를 고속 실시간으로 플로팅하도록 설계되었습니다.
상태 초기화 및 연결 렌더링 이벤트
라운드 수, 포인트 수, 렌더링 프레임 수에 대한 카운터를 초기화합니다. 성능 측정을 위해 사용되던 스톱워치를 중지합니다. CompositionTarget.Rendering 이벤트를 분리했다가 다시 연결하여 렌더링이 깨끗한 상태에서 시작되도록 합니다. 또한 Start/Stop 버튼의 텍스트를 “Restart”로 업데이트합니다.
//Start
_iRound = 0;
_pointsAppended = 0;
_framesRenderedCount = 0;
stopWatch.Stop(); //this is started in the CompositionTargetRendering in first round
CompositionTarget.Rendering -= CompositionTarget_Rendering;
CompositionTarget.Rendering += CompositionTarget_Rendering;
buttonStartStop.Content = "Restart";
사용자 입력을 읽고 검증합니다
표시할 데이터 시리즈 수, 업데이트 라운드당 추가할 포인트 수, X축 길이(시간 범위 또는 포인트 수)에 대한 값을 입력 필드에서 가져옵니다. 입력 값 중 하나라도 유효하지 않으면 메시지 박스를 표시하고, 메서드는 즉시 종료됩니다.
//Read series count
try
{
_seriesCount = int.Parse(textBoxSeriesCount.Text);
}
catch
{
MessageBox.Show("Invalid series count text input");
return;
}
//Read append count / round
try
{
_appendCountPerRound = int.Parse(textBoxAppendCountPerRound.Text);
}
catch
{
MessageBox.Show("Invalid append count");
return;
}
차트 작성 전 입력 데이터 생성
CreateInputData()를 호출하여 사용할 모든 데이터를 미리 생성합니다. 이를 통해 실시간 차트 렌더링 중에 데이터를 즉석에서 생성하는 과정을 피할 수 있어, 차트 표시를 부드럽고 빠르게 유지할 수 있습니다.
기존 차트 콘텐츠 삭제
새로운 차트를 그리기 전에 기존 시리즈와 Y축을 해제(dispose)하기 위해 헬퍼 메서드를 호출합니다. 이를 통해 이전 실행에서 남아 있을 수 있는 메모리 누수나 시각적 중첩 문제를 방지합니다.
//Clear Data series
DisposeAllAndClear(v.DigitalLineSeries);
//Clear Y axes
DisposeAllAndClear(v.YAxes);
새로운 Y축 및 데이터 시리즈 생성
사용자 입력에 따라 각 시리즈마다 새로운 Y축을 생성하고, 사용자 지정 색상, 제목, 레이아웃을 설정합니다. 이어서 이진 형태의 High/Low 신호 라인을 표현하는 새로운 디지털 라인 시리즈를 추가합니다. 데이터 간 간격의 일관성을 유지하기 위해 샘플링 레이트와 초기 타임스탬프를 설정합니다. 마지막 Y축에는 미니 스케일(작은 오버뷰 창)을 포함시켜, 축을 숨기거나 확대·축소할 때도 전체적인 맥락을 쉽게 파악할 수 있도록 합니다.
//Series count of Y axes and SampleDataBlockSeries
for (int seriesIndex = 0; seriesIndex < _seriesCount; seriesIndex++)
{
Color lineBaseColor = DefaultColors.SeriesForBlackBackgroundWpf[seriesIndex % DefaultColors.SeriesForBlackBackgroundWpf.Length];
AxisY axisY = new AxisY(v);
axisY.SetRange(YMin, YMax);
axisY.Title.Text = string.Format("Ch {0}", seriesIndex + 1);
axisY.Title.Angle = 0;
axisY.Title.Color = ChartTools.CalcGradient(lineBaseColor, System.Windows.Media.Colors.White, 50);
axisY.Units.Visible = false;
axisY.AllowScaling = false;
axisY.MajorGrid.Visible = false;
axisY.MinorGrid.Visible = false;
axisY.MajorGrid.Pattern = LinePattern.Solid;
axisY.AutoDivSeparationPercent = 0;
axisY.Units.Text = "mV";
axisY.Visible = true;
axisY.MajorDivTickStyle.Alignment = seriesIndex % 2 == 0 ? Alignment.Near : Alignment.Far;
axisY.Title.HorizontalAlign = seriesIndex % 2 == 0 ? YAxisTitleAlignmentHorizontal.Left : YAxisTitleAlignmentHorizontal.Right;
설정 완료 및 선택적으로 데이터 사전 채우기
X축 범위를 사용자 정의 길이에 맞게 설정합니다. “Prefill” 체크박스가 선택된 경우, 차트에 데이터를 미리 로드하며 이 과정은 몇 초가 소요될 수 있지만 즉시 시각적인 결과를 확인할 수 있습니다. 마지막으로 _chart.EndUpdate()를 호출하여 업데이트 블록을 종료하고, 모든 요소를 한 번에 렌더링합니다.
//Prefill with data, this may take several seconds
if (checkBoxPrefill.IsChecked == true)
{
PrefillChartWithData();
}
_chart.EndUpdate();
CreateInputData()CreateInputData() 메서드는 각 시리즈에 대해 모든 데이터 포인트를 사전에 생성합니다. 이 메서드는 무작위의 디지털 형태 패턴으로 구성된 2차원 배열을 생성하여, 실시간 시각화 중에도 데이터를 빠르고 부드럽게 차트에 추가할 수 있도록 합니다.
uint[][] data = new uint[seriesCount][];
// System.Threading.Tasks.Parallel.For(0, seriesCount, (seriesIndex) =>
for(int seriesIndex = 0; seriesIndex < seriesCount; seriesIndex++)
{
int dataPointCount = PreGenerateDataForRoundCount * appendCountPerRound;
uint[] seriesData = new uint[dataPointCount];
for (int i = 0; i < dataPointCount; i++)
{
switch((int)(rdm.NextDouble() * 5))
{
case 0:
seriesData[i] = 0x00000000;
break;
case 1:
seriesData[i] = 0xFF000000;
break;
case 2:
seriesData[i] = 0x000000FF;
break;
case 3:
seriesData[i] = 0x0000FF00;
break;
case 4:
seriesData[i] = 0x000FF000;
break;
case 5:
seriesData[i] = 0xFFFFFFFF;
break;
}
}
data[seriesIndex] = seriesData;
}//);
PrefillChartWithData()PrefillChartWithData() 메서드는 실시간 업데이트가 시작되기 전에 사전에 생성된 디지털 데이터를 차트에 채웁니다. 이 메서드는 속도 향상을 위해 병렬 처리를 사용하고, 이진 형태의 데이터를 효율적으로 추가하며, X축을 올바른 스크롤 위치로 설정하여 차트가 시작부터 활성화되고 반응성 있게 보이도록 합니다.
//How many rounds to prefill in the series
int roundsToPrefill = (int)(0.9 * xLen) / appendCountPerRound / 32;
//How many points to prefill in the series
int pointCount = roundsToPrefill * _appendCountPerRound / 32;
System.Threading.Tasks.Parallel.For(0, _seriesCount, (seriesIndex) =>
{
uint[] thisSeriesData = _data[seriesIndex];
for (int round = 0; round < roundsToPrefill; round++)
{
uint[] dataArray = new uint[_appendCountPerRound];
Array.Copy(thisSeriesData, (round % PreGenerateDataForRoundCount) * appendCountPerRound, dataArray, 0, appendCountPerRound);
_chart.ViewXY.DigitalLineSeries[seriesIndex].AddBits(dataArray, false);
}
});
_pointsAppended += pointCount 32 32;
_iRound += roundsToPrefill;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
_chart.ViewXY.XAxes[0].ScrollPosition = lastX;
FeedData()FeedData()는 다음 데이터 청크를 차트에 전달하고, 뷰를 앞으로 이동시키며, 스크롤 동작에 맞춰 시각 효과를 조정하여 차트가 살아 움직이는 것처럼 보이게 합니다.
각 시리즈에 대한 신규 데이터 추가
각 시리즈마다 사전에 생성된 데이터의 일부를 복사한 뒤 AddBits()를 사용해 추가합니다. 이 과정은 속도 향상을 위해 병렬로 수행되며, 새로운 디지털 신호 데이터 “프레임”이 유입되는 상황을 시뮬레이션합니다.
System.Threading.Tasks.Parallel.For(0, _seriesCount, (seriesIndex) =>
{
uint[] thisSeriesData = _data[seriesIndex];
uint[] dataToAppendNow = new uint[_appendCountPerRound];
Array.Copy(thisSeriesData, (_iRound % PreGenerateDataForRoundCount) * appendCountPerRound, dataToAppendNow, 0, appendCountPerRound);
_chart.ViewXY.DigitalLineSeries[seriesIndex].AddBits(dataToAppendNow, false);
});
X축 스크롤을 통한 신규 데이터 표시
지금까지 추가된 포인트 수를 기준으로 X축의 스크롤 위치를 업데이트합니다. 이를 통해 차트가 실시간으로 계속 앞으로 이동하도록 유지합니다.
pointsAppended += appendCountPerRound * 32;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
chart.ViewXY.XAxes[0].ScrollPosition = lastX;pointsAppended += _appendCountPerRound * 32;
//Set X axis real-time scrolling position
double lastX = _pointsAppended * XInterval;
_chart.ViewXY.XAxes[0].ScrollPosition = lastX;
스크롤 모드에 기반한 스윕 밴드 업데이트
X축이 스위핑(sweeping) 모드로 설정된 경우, 두 개의 그라디언트 밴드를 표시합니다. 하나는 오래된 데이터가 서서히 사라지는 영역을 나타내는 어두운 밴드이고, 다른 하나는 새로 유입되는 데이터를 강조하는 밝은 밴드입니다.
if (_chart.ViewXY.XAxes[0].ScrollMode == XAxisScrollMode.Sweeping)
{
//Dark band of old page fading away
double pageLen = chart.ViewXY.XAxes[0].Maximum - chart.ViewXY.XAxes[0].Minimum;
double sweepGapWidth = pageLen / 20.0;
_chart.ViewXY.Bands[0].SetValues(lastX - pageLen, lastX - pageLen + sweepGapWidth);
if (_chart.ViewXY.Bands[0].Visible == false)
{
_chart.ViewXY.Bands[0].Visible = true;
}
//Bright new page band
_chart.ViewXY.Bands[1].SetValues(lastX - sweepGapWidth / 6, lastX);
if (_chart.ViewXY.Bands[1].Visible == false)
{
_chart.ViewXY.Bands[1].Visible = true;
}
}
스위핑 모드가 아닌 경우에는, 현재 표시 모드에 맞게 해당 밴드들을 숨깁니다.
else
{
//Hide sweeping bands if not in sweeping mode
if (_chart.ViewXY.Bands[0].Visible == true)
{
_chart.ViewXY.Bands[0].Visible = false;
}
if (_chart.ViewXY.Bands[1].Visible == true)
{
_chart.ViewXY.Bands[1].Visible = false;
}
}
결론
특히 여러 실시간 채널에 걸쳐 수백만, 나아가 수조 개의 포인트를 다루는 대규모 데이터 볼륨을 처리하는 작업은 매우 어렵기로 잘 알려져 있습니다. 하지만 LightningChart .NET은 이러한 복잡한 도전을 놀라울 만큼 단순하고 고성능의 경험으로 전환해 줍니다.
차트와 축 설정과 같은 초기 단계부터 실시간 데이터 피드와 시각 효과에 이르기까지, 이 프레임워크는 속도, 확장성, 그리고 개발자 편의성을 중심으로 설계되었습니다. 단 몇 줄의 코드만으로도 각각 고유한 Y축, 스타일, 레이아웃을 가진 수십 개, 심지어 수백 개의 디지털 라인 시리즈를 동적으로 생성할 수 있습니다.
이 라이브러리는 축 스태킹, 레이블 배치, 그리고 대규모 데이터셋을 플로팅할 때 UI 리사이징 지연을 방지하기 위한 사전 메모리 할당과 같은 최적화까지 자동으로 처리합니다. LightningChart가 특히 뛰어난 부분은 내부 성능 튜닝입니다.
비트 패킹된 디지털 데이터(AddBits()), 병렬 데이터 추가, GPU 가속, 실시간 메모리 관리(예: 오래된 데이터 포인트 자동 제거)와 같은 기능을 통해 수십 개의 시리즈를 동시에, 끊김 없이 업데이트할 수 있습니다.
또 다른 강점은 시각적 연속성과 반응성에 대한 지원입니다. 스위핑 그라디언트 밴드와 같은 도구는 오래된 데이터와 새로운 데이터를 시각적으로 구분할 수 있게 해주며, 실시간 스크롤링과 사용자 정의 가능한 프리필(prefill) 옵션은 차트가 처음 표시되는 순간부터 실제 데이터처럼 자연스럽게 보이도록 합니다. LightningChart는 단순히 데이터를 표시하는 데 그치지 않고, 명확성, 유연성, 그리고 맥락을 갖추어 데이터를 표현합니다.
LightningChart .NET은 성능을 최우선으로 하면서도 개발자의 시간과 워크플로를 존중합니다. 과학적 모니터링, 산업 시스템, 금융 지표, 다채널 진단 등 어떤 분야의 개발이든, 이 API는 불필요한 복잡성을 추가하지 않으면서도 다양한 요구 사항에 유연하게 대응할 수 있도록 설계되었습니다.