강좌와 팁

C# : 테이블을 XML로 저장하기 날짜:2021-7-4 9:47:19 조회수:64
작성자 : 소엔
포인트 : 1580
가입일 : 2020-02-02 00:09:14
방문횟수 : 109
글 203개, 댓글 64개
소개 : SoEn 운영자입니다.
작성글 보기
쪽지 보내기
SQL 닷넷 데이터베이스의 기본만 알아도 테이블을 만들고 그리드에 표시하는 것은 어려운 일이 아니다. 다음 코드는 tblPeople 테이블을 생성하고 그리드 뷰에 출력한다. 폼에 그리드 하나만 배치해 두면 테이블 내용을 즉시 확인할 있다.

private void Form1_Load(object sender, EventArgs e)
{
    DataTable tblPeople = MakePeopleTable();
    dataGridView1.DataSource = tblPeople;
}

private DataTable MakePeopleTable()
{
      // 내용 생략
}

MakePeopleTable 메서드는 DataTable, DataColumn, DataRow 차례대로 생성하여 3개의 필드를 가지는 4행짜리 초간단 테이블을 만든다. 메서드 내용은 단순한 초기화 명령의 나열이며 본문에도 이미 공개되어 있으므로 참고하자.
실무에서는 이런 식으로 코드에서 테이블을 생성하기보다 쿼리를 통해 DBMS 테이블을 읽는 것이 보편적이고 손쉽다. 그러나 예제에서 그렇게 하자면 DBMS 연결해야 하고 샘플 테이블도 준비해야 하는 여러모로 번거로워 테스트의 편의상 코드에서 테이블을 생성했다.
직접 생성하든 쿼리에서 읽어오건 DataTable 객체를 구했으면 어떤 식으로든 활용할 있다. 원하는 값을 검색할 수도 있고 집계를 산출하거나 차트를 그릴 수도 있다. 단순히 테이블의 내용을 확인해 보려면 그리드에 대입하면 된다.



쿼리 날려서 테이블 얻고 테이블을 사용하는 것은 아주 일상적인 코드이다. 그런데 가끔 다음과 같은 경우가 있다.

- 테이블 크기는 작지만 추출해 내는데 엄청난 시간이 걸린다.
- 왠만해서는 테이블 구조가 바뀌지 않는다.
- 이후의 작업 과정에 중요한 참조 테이블로 사용한다.

실무에서 이런 예가 있었는데 500만개 레코드를 계층별로 분류하여 트리로 출력하는 일이었다. 결과 트리 자체는 작지만 전체 테이블을 스캔하여 노드를 뽑아 내는 작업은 대략 10 가량 소모되었다. 게다가 계층은 바뀌지도 않고 똑같아 굳이 실시간으로 매번 조사할 필요도 없다.
이런 테이블을 프로그램 시작할 때마다 조사하면 시작이 10초간 지연되는 심각한 부작용이 나타난다. 이럴 때는 매번 복잡한 쿼리를 실행하지 말고 테이블 내용을 어딘가에 따로 저장해 놓고 저장된 내용을 읽어 오면 된다. 임시 테이블도 방편이고 요약 테이블을 따로 만드는 방법도 있다.
여기서는 테이블 내용을 XML 뽑아 내어 문자열을 저장해 놓고 XML로부터 다시 테이블을 생성하는 기법을 소개한다. XML 임의의 모든 테이블을 표현할 있고 길이도 짧아 읽는 것도 순간적이다. 변하지 않는 복잡한 테이블을 저장해 놓을 아주 유용하다.
코드는 다음과 같다. 메모리 스트림을 생성하고 WriteXml, ReadXml 입출력하는 코드이며 주의 사항에 대해 주석을 상세히 달아 놓았으므로 자세한 설명은 생략한다. 유사한 동작을 구현하려면 코드대로 그대로 따라하면 된다.

private void Form1_Load(object sender, EventArgs e)
{
    DataTable tblPeople = MakePeopleTable();

    // 레코드에 대한 엘리먼트명으로 사용할 테이블명 지정. 생략시 에러이며 반드시 이름이 있어야 한다.
    tblPeople.TableName = "test";
    MemoryStream ms = new MemoryStream();
    // 스키마를 생성하도록 옵션 지정. IgnoreSchema 이면 스키마가 생략되어 테이블 구조를 유추할 없다.
    tblPeople.WriteXml(ms, XmlWriteMode.WriteSchema);
    // 스트림에 UTF8 저장되는데 C#에서 쓰기 편하게 String 객체로 변환한다
    String xml = Encoding.UTF8.GetString(ms.ToArray());

    // 이렇게 만든 xml 문자열을 다른 테이블의 컬럼, 레지스트리, 텍스트 파일 등에 저장해 둔다.
    // 단순한 문자열이므로 저장 복구가 편리하다.

    // 문자열을 UTF8 변환한다.
    byte[] raw = Encoding.UTF8.GetBytes(xml);
    // 문자열을 가지는 스트림을 생성한다.
    MemoryStream ms2 = new MemoryStream(raw);
    // 테이블을 생성하고 스트림으로부터 테이블을 읽어 들인다.
    DataTable tblPeople2 = new DataTable();
    tblPeople2.ReadXml(ms2);

    // XML로부터 만든 테이블을 그리드에 출력한다.
    dataGridView1.DataSource = tblPeople2;
}

tblPeople XML 문자열로 변환하고 XML 문자열로부터 tblPeople2 다시 생성한다. 중간에 생성되는 XML 문자열을 MessageBox 찍어 보면 다음과 같은 모양이며 스키마와 데이터가 완벽하게 저장되어 있다.



XML 어딘가에 저장해 놓기만 하면 똑같은 테이블을 언제든지 신속하게 생성할 있다. tblPeople2 생성하여 그리드에 출력해 보았다. 중간 과정을 한번 거쳤을 실행 결과는 완전히 같다.
이런 테이블 저장 기법은 아주 실용적이다. 테이블을 구하는 시간이 아무리 길어도 XML 한번만 구해 두면 순간적으로 테이블을 생성하므로 반응성이 향상된다. 또한 실행할 때마다 복잡한 테이블을 매번 생성하지 않아 서버를 괴롭히는 긍정적인 효과도 있다. 서버가 10초간 뭔가에 몰두하는 것은 전체적인 성능에도 바람직하지 않다.
실무에 방식을 적용한 시작이 빨라져 아주 쾌적해졌다. 다만 저장해 놓은 데이터이지 라이브 데이터가 아니어서 혹시라도 원본 데이터가 바뀐다면 주기적으로 갱신해 주어야 한다는 단점이 있다. 주기적으로 바뀌는 테이블에 기법을 때는 업데이트에 대해서도 고려해야 한다.
테이블을 저장해 놓는 용도로는 XML 외에 JSON 포맷도 쓸만하다. XML 보다 형식이 단순해서 결과 문자열이 짧다는 이점이 있다. 다만, XML 닷넷이 기본 지원하여 간편하고 결과가 항상 일정하지만 JSON 별도의 참조를 추가해야 한다는 점에서 번거롭고 라이브러리에 따라 사용 방법이 약간씩 달라지기도 한다.

 



개발자의 천국 SoEn

목록보기 삭제 수정 신고 스크랩


로그인하셔야 댓글을 달 수 있습니다.