CSV 포맷 및 CsvHelper 라이브러리

공재원
∙∙조회 21

CSV 포맷 및 CsvHelper 라이브러리

1. CSV 포맷

Q1. CSV란 무엇인가?

CSV(Comma-Separated Values)는 쉼표(,)로 값을 구분하는 텍스트 파일 포맷이다.

  • Excel, Google Sheets와 호환되어 스프레드시트 프로그램에서 편집할 수 있다.
  • 기획자가 아이템, 몬스터, 스테이지 등의 데이터를 관리하기 좋다.
  • 별도의 데이터베이스 없이 텍스트 파일로 데이터를 저장하고 관리할 수 있다.
  • 파일 구조가 단순하고 대부분의 프로그램에서 지원한다.

Q2. CSV는 어떤 구조로 구성되는가?

CSV는 일반적으로 첫 번째 줄에 헤더를 작성하고, 이후 줄에 데이터를 작성한다.

  • 첫 번째 줄: 헤더(Header)로 각 열의 이름을 나타낸다.
  • 이후 줄: 데이터(Data)로 각 행이 하나의 레코드(Record)를 나타낸다.
  • 구분자(Delimiter): 쉼표(,)로 각 필드를 구분한다.
  • 필드(Field): 하나의 열에 해당하는 개별 값이다.
  • 레코드(Record): 하나의 행에 해당하는 데이터 묶음이다.

예를 들어 아이템 데이터는 다음과 같은 구조로 작성한다.

IdTypeNameValueCost
Item1Weapon검10500
Item2Equip방패20200
Item3Consumable물약5050

Q3. 프로젝트에서 사용하는 실제 CSV 구조는 무엇인가?

프로젝트의 CSV 파일 위치는 다음과 같다.

  • 경로: Assets/Resources/DataTables/ItemTable.csv
  • 헤더: Id,Type,Name,Desc,Value,Cost,Icon

실제 프로젝트에서는 Name과 Desc에 한글을 직접 작성하지 않고 ITEM_1_NAME과 같은 스트링 테이블 키를 사용한다.

이러한 방식을 사용하면 다음과 같은 장점이 있다.

  • 언어별 문자열을 별도로 관리할 수 있다.
  • CSV 데이터와 실제 표시 문자열을 분리할 수 있다.
  • 다국어 지원 및 로컬라이제이션(Localization)을 쉽게 관리할 수 있다.

즉, CSV에는 문자열 자체가 아니라 문자열을 찾기 위한 키를 저장하고, 실제 표시할 문자열은 스트링 테이블에서 가져오는 구조이다.

Q4. CSV 데이터를 작성할 때 지켜야 하는 규칙은 무엇인가?

규칙설명예시
쉼표 구분쉼표로 각 필드를 구분한다.Item1,Weapon,10
줄바꿈 구분줄바꿈으로 레코드를 구분한다.한 행이 하나의 레코드가 된다.
따옴표 감싸기값에 쉼표나 줄바꿈이 포함되면 큰따옴표로 감싼다."값에, 쉼표 포함"
따옴표 이스케이프값에 큰따옴표가 포함되면 큰따옴표를 두 번 작성한다."그가 ""안녕""이라 했다"

주의할 점은 따옴표로 감싼 필드에 줄바꿈이 포함될 수 있다는 것이다. 따라서 CSV에서 물리적인 한 줄이 반드시 하나의 레코드라고 볼 수는 없다. 정확한 레코드 구분은 CSV 파서가 처리한다.

Q5. CSV의 장점과 단점은 무엇인가?

장점단점
구조가 단순하고 파일 크기가 작다.중첩 구조를 표현하기 어렵다.
Excel, Google Sheets에서 바로 편집할 수 있다.데이터 타입 정보가 별도로 저장되지 않는다.
거의 모든 프로그램에서 지원한다.표준이 느슨하여 구현마다 처리 방식에 차이가 있을 수 있다.
텍스트 파일이므로 내용을 직접 확인하고 수정할 수 있다.복잡한 데이터 구조를 관리하기 어렵다.

CSV의 모든 값은 기본적으로 텍스트로 저장된다. 숫자, 날짜, 열거형 등의 데이터 타입은 CSV 자체에 기록되지 않으며, 데이터를 읽는 프로그램에서 적절한 타입으로 변환해야 한다.


2. CsvHelper 라이브러리

Q1. CsvHelper란 무엇인가?

CsvHelper는 C#에서 CSV 파일을 읽고 쓰기 위한 라이브러리이다.

주요 기능은 다음과 같다.

  • CSV 파일 읽기
  • CSV 파일 쓰기
  • CSV 데이터를 C# 객체로 자동 매핑
  • 문자열을 숫자, 날짜, 열거형 등의 타입으로 변환
  • 헤더 이름과 열 인덱스를 이용한 데이터 접근
  • CSV 읽기 및 쓰기 규칙 설정

프로젝트에서는 NuGetForUnity를 통해 CsvHelper 33.x 버전을 사용한다.

Q2. CsvReader란 무엇인가?

CsvReader는 CSV 데이터를 읽기 위한 클래스이다.

CSV 파일을 읽고 각 행의 데이터를 가져오거나, CSV 데이터를 C# 객체로 변환할 때 사용한다.

기본적인 처리 과정은 다음과 같다.

  1. CSV 데이터를 저장할 클래스를 정의한다.
  2. Reader를 생성하여 CSV 데이터를 읽을 준비를 한다.
  3. CsvReader를 생성한다.
  4. CSV 데이터를 읽는다.
  5. 필요하면 C# 객체로 변환한다.

Q3. CSV 데이터를 C# 객체로 자동 매핑하려면 어떻게 해야 하는가?

먼저 CSV의 헤더와 대응하는 프로퍼티를 가진 클래스를 정의한다.

예를 들어 CSV 헤더가 Id,String이라면 C# 클래스에도 Id, String이라는 프로퍼티를 정의한다.

CsvReader의 GetRecords<T>()를 사용하면 CSV의 각 행을 지정한 제네릭 타입 T의 객체로 자동 변환할 수 있다.

CSV 데이터가 다음과 같다면,

IdString
HELLO안녕
BYE잘가

각 행이 CsvData 객체로 변환되며, 다음과 같은 데이터를 얻는다.

  • HELLO : 안녕
  • BYE : 잘가

이때 클래스의 프로퍼티 이름과 CSV 헤더 이름이 매핑 기준이 된다.

Q4. CsvReader 생성자는 어떤 인자를 받는가?

CsvReader 생성자는 기본적으로 다음 두 가지 요소를 사용한다.

  • TextReader
  • CultureInfo

TextReader는 텍스트를 읽기 위한 추상 클래스이다.

대표적인 하위 클래스는 다음과 같다.

클래스설명입력
StreamReader파일이나 스트림에서 텍스트를 읽는다.파일 경로 또는 스트림
StringReader메모리에 저장된 문자열을 읽는다.string

CultureInfo는 숫자, 날짜 등의 데이터를 문화권에 맞게 해석하기 위한 설정이다.

Q5. CultureInfo.InvariantCulture란 무엇인가?

CultureInfo.InvariantCulture는 특정 국가나 문화권에 종속되지 않는 고정된 형식으로 데이터를 처리하기 위한 설정이다.

국가나 문화권에 따라 숫자와 날짜를 표현하는 방식은 달라질 수 있다.

문화권숫자 표기 예시날짜 표기 예시
한국(ko-KR)1,234.562025-01-15
독일(de-DE)1.234,5615.01.2025
InvariantCulture1234.5601/15/2025

InvariantCulture를 사용하면 실행 환경의 문화권 설정에 영향을 받지 않고 일정한 형식으로 숫자와 날짜를 파싱할 수 있다.

특히 게임 데이터처럼 개발 환경과 실행 환경이 달라질 수 있는 경우 유용하다.

주의할 점은 InvariantCulture가 모든 숫자와 날짜를 자동으로 동일하게 저장한다는 의미는 아니라는 것이다. 데이터를 읽거나 쓸 때 적용되는 문화권별 형식을 고정하는 역할을 한다.

Q6. GetRecords()란 무엇인가?

GetRecords<T>()는 CSV의 각 행을 제네릭 타입 T의 객체로 자동 변환하는 메서드이다.

주요 특징은 다음과 같다.

  • CSV 헤더와 C# 프로퍼티 이름을 기준으로 자동 매핑한다.
  • CSV 문자열을 프로퍼티의 자료형에 맞게 변환한다.
  • 여러 행을 IEnumerable 형태로 반환한다.
  • 별도로 각 필드를 하나씩 읽지 않아도 된다.

Q7. GetRecords()의 자동 매핑 규칙은 무엇인가?

기본적인 자동 매핑은 CSV 헤더와 클래스의 프로퍼티 이름을 기준으로 이루어진다.

CSV 헤더C# 프로퍼티
IdId
StringString

자동 매핑의 주요 규칙은 다음과 같다.

  1. CSV 헤더 이름과 C# 프로퍼티 이름을 기준으로 매핑한다.
  2. 기본적으로 읽기와 쓰기가 가능한 프로퍼티를 매핑 대상으로 사용한다.
  3. 일반 필드는 기본적으로 프로퍼티와 동일한 방식으로 매핑되지 않는다.
  4. CSV의 문자열을 C# 프로퍼티 타입에 맞게 자동 변환할 수 있다.
  5. enum 타입도 이름을 기준으로 변환할 수 있다.

자동 타입 변환 예시는 다음과 같다.

CSV 값C# 타입변환 결과
"10"int10
"3.14"float3.14
"Weapon"ItemTypesItemTypes.Weapon

단, 변환 가능한 형식이어야 하며 CSV 값이 대상 타입에 맞지 않으면 변환 오류가 발생할 수 있다.

대소문자 매칭에 관한 주의사항

원본 학습 자료에는 기본적으로 대소문자를 구분하여 id, ID가 Id에 매핑되지 않는다고 정리되어 있다.

하지만 CsvHelper 33.x의 기본 헤더 처리 설정은 헤더를 소문자로 정규화하는 방식을 사용하므로, 기본 설정에서는 대소문자를 구분하지 않는 매칭이 이루어진다.

따라서 다음 내용을 구분해서 이해해야 한다.

  • 기본 설정에서는 대소문자를 무시하는 헤더 매칭이 가능하다.
  • PrepareHeaderForMatch를 직접 설정하면 헤더 매칭 방식을 변경할 수 있다.
  • HeaderValidationException은 일반적으로 필요한 헤더가 존재하지 않거나 헤더 검증에 실패했을 때 발생한다.
  • 대소문자 차이만으로 항상 HeaderValidationException이 발생한다고 이해하면 안 된다.

Q8. GetRecords()의 지연 실행(Lazy Evaluation)이란 무엇인가?

지연 실행은 데이터를 요청하는 시점에 실제 작업을 수행하는 방식이다.

GetRecords<T>()는 호출하는 즉시 CSV의 모든 데이터를 읽어서 메모리에 저장하는 것이 아니다.

반환된 IEnumerable를 실제로 순회할 때 CSV 데이터를 읽고 객체로 변환한다.

따라서 Reader가 닫힌 이후 데이터를 순회하면 예외가 발생할 수 있다.

문제가 발생하는 이유

  1. using 블록 내부에서 CsvReader를 생성한다.
  2. GetRecords()를 호출한다.
  3. IEnumerable만 반환받고 실제 데이터 읽기는 수행하지 않는다.
  4. using 블록이 종료되면서 Reader가 닫힌다.
  5. using 블록 밖에서 foreach로 데이터를 순회한다.
  6. 이미 닫힌 Reader에 접근하므로 예외가 발생한다.

해결 방법: ToList()

ToList()는 IEnumerable의 데이터를 즉시 순회하여 List에 저장하는 메서드이다.

따라서 Reader가 열려 있는 using 블록 내부에서 ToList()를 호출하면 데이터를 즉시 읽어 메모리에 저장할 수 있다.

방식결과
GetRecords()만 호출하고 using 블록 밖에서 순회Reader가 닫혀 예외가 발생할 수 있다.
using 블록 내부에서 GetRecords().ToList() 호출데이터를 즉시 읽어 List에 저장하므로 이후에도 사용할 수 있다.

핵심은 GetRecords()가 지연 실행된다는 점과 ToList()가 즉시 실행을 유도한다는 점이다.

Q9. IEnumerable와 List의 차이는 무엇인가?

구분IEnumerableList
의미데이터를 순회할 수 있는 인터페이스데이터를 메모리에 저장하는 컬렉션
데이터 처리지연 실행이 가능한 형태로 데이터를 제공할 수 있다.실제 데이터를 저장한다.
인덱스 접근기본적으로 인덱스 접근을 제공하지 않는다.인덱스로 접근할 수 있다.
CSV 사용GetRecords()의 반환 형태로 사용한다.ToList()를 통해 데이터를 저장할 때 사용한다.

IEnumerable 자체가 항상 지연 실행되는 것은 아니다. 다만 CsvHelper의 GetRecords()는 지연 실행 방식으로 데이터를 제공한다.

Q10. 수동 읽기란 무엇인가?

수동 읽기는 GetRecords()를 이용한 자동 매핑 대신 CSV의 각 행과 필드를 직접 지정하여 읽는 방식이다.

자동 매핑을 사용하지 않고 필요한 데이터만 선택적으로 가져오거나, CSV 구조에 맞춰 직접 처리할 때 사용한다.

수동 읽기의 처리 순서는 다음과 같다.

  1. csv.Read()를 호출하여 첫 번째 행을 읽는다.
  2. csv.ReadHeader()를 호출하여 헤더를 등록한다.
  3. while (csv.Read())를 사용하여 데이터 행을 한 줄씩 읽는다.
  4. GetField<T>()를 사용하여 필요한 필드를 가져온다.

필드에 접근하는 방법은 다음과 같다.

메서드설명
GetField("Id")헤더 이름을 기준으로 Id 필드를 가져온다.
GetField("Value")Value 필드를 int 타입으로 변환하여 가져온다.
GetField(1)0부터 시작하는 열 인덱스를 기준으로 필드를 가져온다.

헤더 이름을 사용하면 열의 순서가 변경되어도 해당 이름으로 필드를 찾을 수 있다.

인덱스를 사용하면 열의 순서에 의존하여 데이터를 가져온다.

Q11. CsvConfiguration이란 무엇인가?

CsvConfiguration은 CsvReader와 CsvWriter의 동작을 세부적으로 설정하기 위한 클래스이다.

기본적인 CSV 처리 방식 외에도 헤더 매칭, 구분자, 따옴표 처리 등 다양한 설정을 지정할 수 있다.

생성 시 CultureInfo를 전달하여 문화권 설정을 지정한다.

PrepareHeaderForMatch

PrepareHeaderForMatch는 CSV 헤더와 클래스의 프로퍼티 이름을 비교하기 전에 헤더를 가공하는 설정이다.

예를 들어 헤더와 프로퍼티 이름을 모두 소문자로 변환하면 다음과 같은 이름을 동일하게 비교할 수 있다.

  • CSV 헤더: id
  • CSV 헤더: ID
  • CSV 헤더: Id
  • C# 프로퍼티: Id

모두 소문자로 변환하면 id가 되므로 같은 이름으로 비교할 수 있다.

이 설정을 사용하면 CSV 작성 시 대소문자가 달라지더라도 매핑할 수 있다.

CsvReader 생성 방식의 차이

방식설명
CsvReader(reader, CultureInfo.InvariantCulture)문화권 설정을 직접 전달한다.
CsvReader(reader, config)CsvConfiguration 객체를 전달하여 세부 설정을 적용한다.

CsvConfiguration을 사용하면 문화권 설정과 헤더 처리 방식을 하나의 설정 객체에서 관리할 수 있다.

Q12. Attribute 매핑 설정이란 무엇인가?

Attribute(어트리뷰트)는 클래스나 프로퍼티에 추가적인 정보를 지정하는 기능이다.

CsvHelper에서는 어트리뷰트를 사용하여 CSV 헤더와 프로퍼티의 매핑 규칙을 지정할 수 있다.

사용하려면 다음 네임스페이스를 가져와야 한다.

CsvHelper.Configuration.Attributes

주요 어트리뷰트는 다음과 같다.

어트리뷰트설명
[Name("헤더명")]CSV 헤더 이름과 C# 프로퍼티를 연결한다.
[Index(n)]CSV의 n번째 열과 프로퍼티를 연결한다. 인덱스는 0부터 시작한다.
[Ignore]해당 프로퍼티를 CSV 매핑 대상에서 제외한다.

Name

CSV 헤더 이름과 C# 프로퍼티 이름이 서로 다를 때 사용한다.

예를 들어 CSV 헤더가 item_id이고 C# 프로퍼티가 Id라면 두 항목을 연결할 때 사용한다.

Index

CSV 헤더 이름 대신 열의 위치를 기준으로 매핑할 때 사용한다.

인덱스는 0부터 시작한다.

  • 첫 번째 열: 0
  • 두 번째 열: 1
  • 세 번째 열: 2

Ignore

특정 프로퍼티를 CSV 매핑에서 제외할 때 사용한다.

CSV에 존재하지 않거나 CSV에서 읽고 쓰지 않을 임시 데이터 등을 관리할 때 활용한다.


3. CSV 쓰기 - CsvWriter

Q1. CsvWriter란 무엇인가?

CsvWriter는 C# 객체의 데이터를 CSV 파일로 기록하기 위한 클래스이다.

CsvReader가 CSV를 읽는 역할을 한다면 CsvWriter는 C# 데이터를 CSV로 저장하는 역할을 한다.

Q2. CsvWriter는 어떻게 사용하는가?

기본적인 처리 과정은 다음과 같다.

  1. CSV로 저장할 객체들을 준비한다.
  2. StreamWriter를 생성하여 파일에 기록할 준비를 한다.
  3. CsvWriter를 생성한다.
  4. WriteRecords()를 호출하여 데이터를 기록한다.
  5. Writer가 종료되면서 파일 기록을 마무리한다.

Q3. WriteRecords(records)는 어떤 역할을 하는가?

WriteRecords(records)는 컬렉션에 저장된 여러 객체를 CSV 파일에 기록하는 메서드이다.

주요 특징은 다음과 같다.

  • 여러 객체를 한 번에 기록한다.
  • 프로퍼티 이름을 CSV 헤더로 사용한다.
  • 첫 번째 줄에 헤더를 기록한다.
  • 이후 줄에 각 객체의 데이터를 기록한다.

예를 들어 다음과 같은 Foo 객체가 있다면,

IdName
1one
2two

생성되는 CSV 파일은 다음 구조가 된다.

  • 첫 번째 줄: Id,Name
  • 두 번째 줄: 1,one
  • 세 번째 줄: 2,two

즉, WriteRecords()는 헤더와 모든 레코드를 자동으로 기록한다.


4. 문자열에서 CSV 읽기 - StringReader

Q1. StringReader란 무엇인가?

StringReader는 메모리에 저장된 문자열을 읽기 위한 클래스이다.

CsvHelper는 TextReader를 입력으로 받기 때문에 파일이 아닌 문자열을 파싱할 때도 동일한 CsvReader를 사용할 수 있다.

이때 StreamReader 대신 StringReader를 사용한다.

Q2. StreamReader와 StringReader의 차이는 무엇인가?

두 클래스 모두 TextReader를 상속하므로 CsvReader의 입력으로 사용할 수 있다.

구분StreamReaderStringReader
목적파일이나 스트림에서 텍스트를 읽는다.메모리에 저장된 문자열을 읽는다.
입력파일 경로 또는 스트림string
사용 상황파일에 저장된 CSV를 읽을 때이미 메모리에 로드된 CSV 문자열을 읽을 때

핵심은 CSV 데이터가 어디에 저장되어 있는지에 따라 Reader를 선택한다는 점이다.

Q3. Unity에서 StringReader를 사용하는 이유는 무엇인가?

Unity에서 Resources.Load<TextAsset>()을 사용하면 CSV 파일을 TextAsset으로 불러올 수 있다.

TextAsset의 text 프로퍼티에는 CSV 파일의 내용이 문자열 형태로 저장되어 있다.

따라서 파일 경로를 다시 열기 위한 StreamReader가 아니라 이미 메모리에 있는 문자열을 읽는 StringReader를 사용한다.

Unity 프로젝트의 DataTable.LoadCSV<T>()가 이러한 방식을 사용한다.

처리 과정은 다음과 같다.

  1. Resources.Load()으로 CSV 파일을 불러온다.
  2. TextAsset.text를 통해 CSV 문자열을 가져온다.
  3. StringReader로 문자열을 읽을 준비를 한다.
  4. CsvReader에 StringReader를 전달한다.
  5. GetRecords()로 CSV 데이터를 C# 객체로 변환한다.
  6. ToList()로 데이터를 즉시 평가하여 리스트에 저장한다.

5. 핵심 개념 비교 및 주의사항

Q1. CSV, CsvReader, CsvWriter의 역할은 무엇인가?

구분역할
CSV데이터를 텍스트 형태로 저장하는 파일 포맷이다.
CsvReaderCSV 데이터를 읽는 클래스이다.
CsvWriterC# 데이터를 CSV 파일로 기록하는 클래스이다.
CsvHelperCSV 읽기와 쓰기를 지원하는 C# 라이브러리이다.

Q2. CSV를 읽는 방식에는 어떤 차이가 있는가?

구분자동 매핑수동 읽기
사용 방법GetRecords()Read(), ReadHeader(), GetField()
데이터 처리객체로 자동 변환한다.필요한 필드를 직접 가져온다.
장점코드가 간결하고 여러 데이터를 처리하기 편리하다.원하는 필드만 선택적으로 처리할 수 있다.
단점클래스와 CSV 헤더의 매핑 규칙에 영향을 받는다.직접 읽고 변환하는 작업이 필요하다.

Q3. CSV를 읽을 때 어떤 Reader를 사용해야 하는가?

상황Reader설명
파일에서 읽기StreamReader파일에 저장된 CSV를 읽는다.
메모리 문자열에서 읽기StringReader이미 문자열로 저장된 CSV를 읽는다.

Q4. CsvHelper를 사용할 때 주의해야 할 부분은 무엇인가?

  1. CSV 헤더와 C# 프로퍼티의 매핑 관계를 확인한다.
  2. 기본 매핑 대상은 프로퍼티이며 일반 필드는 별도 설정이 필요하다.
  3. CSV 문자열을 숫자나 enum으로 변환할 때 값의 형식이 올바른지 확인한다.
  4. 실행 환경에 따른 숫자 및 날짜 형식 차이를 방지하려면 InvariantCulture를 사용한다.
  5. GetRecords()는 지연 실행이므로 Reader가 닫히기 전에 ToList()로 즉시 평가한다.
  6. 헤더 이름이 서로 다르면 Name 어트리뷰트나 CsvConfiguration을 활용한다.
  7. 열의 순서로 매핑하려면 Index 어트리뷰트 또는 인덱스 접근을 사용한다.
  8. 매핑에서 제외할 프로퍼티에는 Ignore 어트리뷰트를 사용한다.
  9. 파일을 읽을 때는 StreamReader를 사용하고, 메모리에 있는 문자열을 읽을 때는 StringReader를 사용한다.
  10. CSV 값에 쉼표, 줄바꿈, 큰따옴표가 포함될 때는 CSV 규칙에 맞게 처리해야 한다.

6. Unity 프로젝트 적용 내용

Q1. Unity에서 CSV를 사용하는 이유는 무엇인가?

게임에서 사용하는 아이템, 몬스터, 스킬 등의 데이터를 코드와 분리하여 관리하기 위해 사용한다.

CSV를 사용하면 다음과 같은 장점이 있다.

  • 게임 데이터를 코드 수정 없이 변경할 수 있다.
  • Excel이나 Google Sheets에서 데이터를 편집할 수 있다.
  • 기획자와 프로그래머가 데이터를 분리하여 관리할 수 있다.
  • 여러 게임 오브젝트의 설정값을 일관된 구조로 관리할 수 있다.
  • 스트링 테이블 키를 사용하여 다국어 데이터를 관리할 수 있다.

Q2. Unity에서 CSV를 불러오는 전체 과정은 무엇인가?

  1. CSV 파일을 Resources 폴더에 저장한다.
  2. Resources.Load()으로 CSV 파일을 불러온다.
  3. TextAsset.text에서 CSV 문자열을 가져온다.
  4. StringReader로 문자열을 읽는다.
  5. CsvReader로 CSV 데이터를 파싱한다.
  6. GetRecords()로 C# 객체에 자동 매핑한다.
  7. ToList()로 데이터를 즉시 평가하여 메모리에 저장한다.
  8. 변환된 데이터를 게임 시스템에서 사용한다.

Q3. 프로젝트의 DataTable.LoadCSV()는 어떤 역할을 하는가?

DataTable.LoadCSV()는 Unity에서 CSV 데이터를 불러와 C# 객체로 변환하는 역할을 한다.

Resources.Load()으로 CSV를 불러오고, TextAsset.text를 StringReader에 전달하여 데이터를 읽는 구조를 사용한다.

CsvHelper의 GetRecords()를 이용하면 CSV의 각 행을 지정한 데이터 클래스의 객체로 변환할 수 있다.

이러한 구조를 사용하면 게임 시스템에서 CSV 파일을 직접 해석하지 않고 이미 객체로 변환된 데이터를 사용할 수 있다.


7. 복습할 내용

CSV 포맷

  • CSV의 의미와 기본 구조
  • 헤더, 레코드, 필드의 차이
  • 쉼표와 줄바꿈을 이용한 데이터 구분
  • 큰따옴표를 사용하는 이유
  • 큰따옴표 이스케이프 규칙
  • CSV의 장점과 단점
  • 스트링 테이블 키와 로컬라이제이션의 관계

CsvHelper

  • CsvHelper의 역할
  • CsvReader와 CsvWriter의 차이
  • TextReader의 역할
  • StreamReader와 StringReader의 차이
  • CultureInfo.InvariantCulture의 역할
  • GetRecords()의 자동 매핑
  • 프로퍼티와 필드의 매핑 차이
  • CSV 문자열의 자동 타입 변환
  • enum 타입 변환
  • Lazy Evaluation의 의미
  • ToList()를 사용하는 이유
  • IEnumerable와 List의 차이
  • 수동 읽기의 처리 순서
  • GetField()의 헤더 및 인덱스 접근
  • CsvConfiguration의 역할
  • PrepareHeaderForMatch의 역할
  • Name, Index, Ignore 어트리뷰트의 차이
  • WriteRecords()의 역할

Unity 적용

  • Resources.Load()의 역할
  • TextAsset.text의 의미
  • Unity에서 StringReader를 사용하는 이유
  • DataTable.LoadCSV()의 처리 과정
  • CSV를 이용한 게임 데이터 관리 방식

8. 다음 학습 순서

  1. CSV의 구조와 작성 규칙을 이해한다.
  2. CsvReader를 이용한 CSV 읽기 과정을 이해한다.
  3. GetRecords()의 자동 매핑과 타입 변환을 복습한다.
  4. Lazy Evaluation과 ToList()의 관계를 이해한다.
  5. 수동 읽기와 자동 매핑의 차이를 이해한다.
  6. CsvConfiguration과 Attribute 매핑을 복습한다.
  7. CsvWriter를 이용한 CSV 쓰기 과정을 이해한다.
  8. StreamReader와 StringReader의 차이를 이해한다.
  9. Unity의 Resources.Load()과 DataTable.LoadCSV()의 연결 과정을 이해한다.
  10. 실제 CSV 데이터를 직접 읽고 게임 시스템에 적용한다.

9. 면접 전 핵심 정리

Q. CSV란 무엇인가?

CSV는 쉼표로 필드를 구분하고 줄바꿈으로 레코드를 구분하는 텍스트 파일 포맷이다. 첫 번째 줄에는 일반적으로 헤더가 들어간다.

Q. CSV에서 쉼표나 큰따옴표가 포함된 값은 어떻게 처리하는가?

쉼표나 줄바꿈이 포함된 값은 큰따옴표로 감싸고, 값 내부의 큰따옴표는 두 번 작성하여 이스케이프한다.

Q. CsvHelper란 무엇인가?

C#에서 CSV 데이터를 읽고 쓰며, CSV 데이터를 C# 객체로 자동 매핑할 수 있도록 지원하는 라이브러리이다.

Q. CsvReader와 CsvWriter의 차이는 무엇인가?

CsvReader는 CSV 데이터를 읽는 역할을 하고, CsvWriter는 C# 객체의 데이터를 CSV 파일로 기록하는 역할을 한다.

Q. CultureInfo.InvariantCulture를 사용하는 이유는 무엇인가?

운영체제나 실행 환경의 문화권 설정에 따라 숫자와 날짜의 표현 방식이 달라지는 문제를 방지하고, 일정한 형식으로 데이터를 파싱하기 위해 사용한다.

Q. GetRecords()는 어떤 역할을 하는가?

CSV의 각 행을 제네릭 타입 T의 객체로 자동 변환한다. CSV 헤더와 C# 프로퍼티 이름을 기준으로 매핑한다.

Q. GetRecords()에서 ToList()를 사용하는 이유는 무엇인가?

GetRecords()는 지연 실행되기 때문에 Reader가 닫히기 전에 데이터를 실제로 읽어 메모리에 저장하기 위해 ToList()를 사용한다.

Q. IEnumerable와 List의 차이는 무엇인가?

IEnumerable는 데이터를 순회할 수 있는 인터페이스이고, List는 데이터를 메모리에 저장하는 컬렉션이다.

Q. 수동 읽기와 자동 매핑의 차이는 무엇인가?

자동 매핑은 GetRecords()로 CSV 행을 객체로 변환하고, 수동 읽기는 Read()와 GetField()를 사용하여 필요한 필드를 직접 가져온다.

Q. CsvConfiguration은 어떤 역할을 하는가?

CsvReader와 CsvWriter의 동작을 세부적으로 설정한다. 헤더 처리, 문화권 설정 등의 규칙을 지정할 수 있다.

Q. Name, Index, Ignore 어트리뷰트의 차이는 무엇인가?

Name은 CSV 헤더 이름으로 매핑하고, Index는 열의 위치로 매핑하며, Ignore는 해당 프로퍼티를 매핑에서 제외한다.

Q. StreamReader와 StringReader의 차이는 무엇인가?

StreamReader는 파일이나 스트림에서 텍스트를 읽고, StringReader는 메모리에 저장된 문자열을 읽는다.

Q. Unity에서 StringReader를 사용하는 이유는 무엇인가?

Resources.Load()으로 불러온 CSV는 TextAsset.text에 문자열로 저장되어 있으므로 StringReader를 사용하여 파싱한다.

Q. Unity에서 CSV를 사용하는 이유는 무엇인가?

게임 데이터를 코드와 분리하여 관리하고, Excel 등의 도구를 통해 데이터를 편리하게 수정하기 위해 사용한다.