C# Reed-Solomon error correction 테스트

C#을 사용하여 프로그램을 하나 만들려고 하는데 데이터에 에러가 발생될 경우 이를 복구할 수 있는 방법이 있으면 좋을것 같아 검색해 보니 Reed-Solomon 알고리즘을 알게 되었고 C#용 NuGet 패키지도 지원되어 쉽고 간편하게 사용해 볼 수 있을것 같아 테스트 해 보았습니다.

Reed-Solomon을 처음 알게되어 궁금하여 검색해 보니 어지러운 수식이 난무하여, 챗GPT에 Reed-Solomon에 대해 간략히 알려달라는 질문에 아래와 같은 답변을 주었습니다.

답변을 확인해 보니 사용되지 않는곳이 없을 정도로 다양한 분야에서 사용되고 있음을 알게 되었습니다.

Reed-Solomon 알고리즘은 주로 오류 검출 및 수정을 위해 사용되는 에러 정정 코드(Error Correcting Code, ECC)의 일종입니다. 
다음과 같은 다양한 분야에서 널리 사용됩니다:

1. 디지털 통신
   - 위성 통신: 신호 전송 과정에서 발생하는 데이터 손실이나 잡음을 보정하는 데 사용됩니다.
   - 광통신: 데이터 전송 중 발생하는 오류를 수정하기 위해 사용됩니다.
   - 모뎀: 데이터 전송 중의 잡음으로 인한 오류를 수정하기 위해 사용됩니다.

2. 데이터 스토리지
   - CD, DVD, Blu-ray 디스크: Reed-Solomon 코드는 물리적 손상이나 스크래치로 인해 발생하는 오류를 복구하여 데이터를 정확하게 읽을 수 있게 합니다.
   - QR 코드: 코드 내 일부 데이터 손실이 발생하더라도 Reed-Solomon 코드를 통해 이를 복원할 수 있습니다.
   - 하드 드라이브 및 SSD: 데이터 읽기 중 발생할 수 있는 오류를 수정합니다.

3. 네트워크 전송
   - 무선 통신: 잡음이 많거나 간섭이 발생할 수 있는 무선 네트워크에서 데이터 오류를 수정하는 데 사용됩니다.
   - 위성방송: 송신과 수신 과정에서 발생하는 신호 손실 및 오류를 보정합니다.

4. 공간 탐사
   - 우주선 및 탐사선 통신: 매우 먼 거리에서 전송되는 신호가 약해질 수 있는 우주 탐사에서 중요한 역할을 합니다. NASA의 우주선에서 사용되는 이미지 전송에서도 Reed-Solomon 알고리즘이 사용되었습니다.

5. 데이터 백업 및 복구
   - RAID 시스템: RAID 6와 같은 백업 시스템에서 데이터 손실을 방지하기 위해 사용됩니다. 

Reed-Solomon 알고리즘은 데이터 전송 및 저장 과정에서 발생할 수 있는 오류를 탐지하고 복구함으로써 데이터의 신뢰성과 무결성을 보장하는 핵심적인 기술입니다.

이렇게 다양한 분야에서 사용되는 Reed-Solomon 테스트를 위해 C# Console 애플리케이션(.NET 8.0 사용)을 작성하여 테스트해 보았습니다.

 

패키지 설치

프로젝트를 생성 후 NuGet 패키지 관리자를 통해 STH1123.ReedSolomon 패키지를 설치합니다.

STH1123.ReedSolomon
STH1123.ReedSolomon (https://github.com/Sonic-The-Hedgehog-LNK1123/ReedSolomon)

 

Main 메소드 생성

패키지가 설치가 완료되었으면 아래와 같이 Program.cs파일을 아래와 같이 작성합니다.

using STH1123.ReedSolomon;

class Program {
    static void Main(string[] args) {
    }
}

 

초기화

ReedSolomonEncoder에서 사용될 갈루아 필드(Galois field)를 생성후 인코딩전에 테스트할 data를 출력해 보았습니다.

ecBytes는 데이터에 추가되어 디코딩시 보정용으로 사용되는 여분의 데이터 필드의 갯수로 보정할 에러 갯수의 2배 값을 사용합니다.

여기서는 9이므로 최대 4개의 에러값을 보정할 수 있습니다.

int ecBytes = 9;

GenericGF field = new GenericGF(285, 256, 0);

int[] data = new int[] { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

Console.WriteLine("original - [{0}]", string.Join(", ", data));

 

인코딩

ReedSolomonEncoder를 생성후 Encode 메소드의 파라미터에 data와 ecBytes를 넣어줍니다.

ReedSolomonEncoder rse = new ReedSolomonEncoder(field);

rse.Encode(data, ecBytes);

Console.WriteLine("encode - [{0}]", string.Join(", ", data));

 

강제적인 데이터 에러 삽입

데이터의 1, 3번째 값에 강제적으로 0을 대입하여 에러를 강제적으로 발생하게 하였습니다.

data[1] = 0;
data[3] = 0;

Console.WriteLine("broken - [{0}]", string.Join(", ", data));

 

디코딩 및 에러복구

ReedSolomonDecoder를 생성후 수신받은 데이터와 ecBytes값을 파라미터로 Decode 메소드에 넣어 줍니다.

ecBytes내에서 자동으로 복구를 시도하여 성공/실패를 알려줍니다.

ReedSolomonDecoder rsd = new ReedSolomonDecoder(field);

if (rsd.Decode(data, ecBytes)) {
    Console.WriteLine("Data corrected.");
    Console.WriteLine("decode - [{0}]", string.Join(", ", data));
}
else {
    Console.WriteLine("Too many errors/erasures to correct.");
    Console.WriteLine("error - [{0}]", string.Join(", ", data));
}

 

전체 테스트 소스

using STH1123.ReedSolomon;

class Program {
    static void Main(string[] args) {
        int ecBytes = 9;

        GenericGF field = new GenericGF(285, 256, 0);

        ReedSolomonEncoder rse = new ReedSolomonEncoder(field);

        int[] data = new int[] { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

        Console.WriteLine("original - [{0}]", string.Join(", ", data));

        rse.Encode(data, ecBytes);

        Console.WriteLine("encode - [{0}]", string.Join(", ", data));

        data[1] = 0;
        data[3] = 0;

        Console.WriteLine("broken - [{0}]", string.Join(", ", data));

        ReedSolomonDecoder rsd = new ReedSolomonDecoder(field);

        if (rsd.Decode(data, ecBytes)) {
            Console.WriteLine("Data corrected.");
            Console.WriteLine("decode - [{0}]", string.Join(", ", data));
        }
        else {
            Console.WriteLine("Too many errors/erasures to correct.");
            Console.WriteLine("error - [{0}]", string.Join(", ", data));
        }
    }
}

 

실행결과

ecBytes = 9인 경우 ‘Data corrected’ 메시지가 나오며 에러가 발생된 2개의 데이터를 정상적으로 복구하였습니다.

Reed-Solomon Test - OK

ecBytes = 3인 경우 최대 1개의 데이터만 복구할 수 있기 때문에 2개의 데이터 에러에 대해서는 복구가 불가능하여 ‘Too many errors/erasures to correct.’ 메시지가 나오며 데이터가 정상적으로 복구되지 않았습니다.

Reed-Solomon Test - Fail

Reed-Solomon의 이론적인 배경을 잘 몰라도 이런식으로 쉽고 편리하게 Reed-Solomon 알고리즘을 C# 애플리케이션에서 사용할 수 있습니다.

물론 이론적인 배경을 알면 좋겠지만 방대한 수식 및 기호를 보니 쉽게 접근하기가 어렵네요.

Leave a Comment