login register Sysop! about ME  
qrcode
    최초 작성일 :    2009년 06월 10일
  최종 수정일 :    2009년 06월 10일
  작성자 :    프렐루드
  편집자 :    프렐루드 (김 영환)
  읽음수 :    22,015

강좌 목록으로 돌아가기

필자의 잡담~

프렐루드님의 9번째 강좌입니다.

어느새 아홉 번째 글입니다. 다음 글에서는 윈도우즈 응용 프로그램에서의 차트 컨트롤을 다룰 예정이기 때문에 ASP.NET에서 사용하는 차트 컨트롤에 대한 글은 이번 글이 마지막 글이 되겠네요.

이번 글에서는 공백 값. 즉, 빈 값에 대해서 알아보려고 합니다. 앞의 글에서 몇 번 언급하긴 했지만 차트 컨트롤에서 공백 값의 처리는 의외로 중요합니다. 일반적인 경우에 차트에 바인딩 되는 값들은 표현하고자 하는 영역에 대해서 완전한 값을 사용하기 때문에 공백 값에 대한 고려는 거의 하지 않아도 좋은 경우가 많습니다. 하지만 그렇기 때문에 공백 값에 대한 처리를 해주어야 할 때 정확한 처리를 하지 않음으로써 제대로 된 그래프를 그리지 못하게 되는 경우가 왕왕 생기게 됩니다. 이번 글에서는 공백 값을 처리하는 방법에 대해서 알아보고 ASP.NET에서의 차트에 대한 글을 마무리 해 보겠습니다.

우선 Series에서 하나의 위치를 말해주는 Point는 기본으로 Double형을 갖는다는 점을 알아두어야 합니다. 지금까지 대부분의 예제에서 정수형 값을 사용했기 때문에 오해하기 쉽지만 차트에서 하나의 점을 표시하는 기본형은 Double형입니다. 차트에서 정수만을 표시하라는 법은 없으니까 이는 당연한 부분이기도 합니다. 때문에 차트에서 공백 값을 세팅할 때는 다음처럼 코딩해 주면 됩니다.

Chart1.Series[0].Points.AddY(Double.Nan);

혹시 다음과 같은 코드는 어떨까요?

Chart1.Series[0].Points.AddY(null);

Double.Nan은 상수이기 때문에 메서드가 이상 없이 실행 되지만 null을 적어준 경우에는 런타임 에러가 발생하면서 정상적인 처리가 되지 않음을 확인할 수 있습니다. 그럼 간단한 코드를 살펴보고 공백 값이 설정되었을 때 차트가 어떤 모습을 가지게 되는지 살펴보겠습니다.

다음처럼 HTML 코드를 작성합니다.

<asp:Chart ID="Chart1" Width="600" Height="300" runat="server" ImageType="Png">
  
<series>
    
<asp:Series ChartType="Line" MarkerStyle="Square" BorderWidth="2" 
      Color
="DodgerBlue" ShadowColor="20, 20, 20" ShadowOffset="1" Name="Series1" />
  </
series>
  
<chartareas>
    
<asp:ChartArea Name="ChartArea1" BackGradientStyle="LeftRight" 
      BackSecondaryColor
="240, 240, 240" BackColor="255, 255, 255">                
      
<axisy LineColor="64, 64, 64">
        
<MajorGrid LineColor="180, 180, 180" Interval="100" />
        <
LabelStyle ForeColor="Gray" Font="맑은 고딕, style=Bold" />
      </
axisy>
      
<axisx LineColor="64, 64, 64" Interval="2">
        
<MajorGrid LineColor="180, 180, 180" />
        <
LabelStyle ForeColor="DimGray" Font="굴림, style=Bold" Interval="1" />
      </
axisx>
    
</asp:ChartArea>
  
</chartareas>
</asp:Chart>

그리고 다음처럼 .cs 코드를 작성합니다.

protected void Page_Load(object sender, EventArgs e)

{

    double[] yValues1 = new double[20];

 

    Random rand = new Random();

 

    for (int i = 0; i < 20; i++)

    {

        if (i == 14)

            yValues1[i] = double.NaN;

        else

            yValues1[i] = rand.Next(1000);

    }

 

    Chart1.Series[0].Points.DataBindY(yValues1);

    Chart1.Series[0].Points[14].IsEmpty = true;

}

그리고 이 코드에 의한 결과는 다음과 같습니다.

일반적인 선형 그래프이지만 열 다섯 번째 점이(Chart1.Series[0].Points[14]) 표현되지 않고 빈 공간으로 되어 있음을 확인할 수 있습니다. .cs코드에서는 글의 서두에서 말한 것 처럼 열 다섯 번째의 값을 Double.Nan으로 설정함을 확인할 수 있습니다. 그리고 다음처럼 해당 값이 공백 값이라고 알려줌으로서 차트에서 공백으로 표현되도록 해 줍니다.

Chart1.Series[0].Points[14].IsEmpty = true;

만약 IsEmpty 값을 false로 설정하면 어떻게 될까요? 코드를 다음처럼 고쳐 봅니다.

Chart1.Series[0].Points[14].IsEmpty = false;

이에 의한 결과는 다음과 같습니다.

이번에는 공백으로 표시하지 않고 해당 점에 0을 넣은 것과 동일한 형식이 됩니다.

이번에는 조금 다른 방식으로 공백에 대한 부분을 살펴보고자 합니다. AddXY()메서드를 이용하면 X축과 Y값으로 점을 바인딩할 수 있습니다. 여기에서 X의 값을 1, 2, 3,... 13. 15. 16,... 같은 형태로 하면 어떻게 될까요? 다음의 코드를 통해서 결과를 확인해 보도록 하겠습니다.

.cs 코드를 다음처럼 변경합니다.

protected void Page_Load(object sender, EventArgs e)

{

    double[] yValues1 = new double[20];

 

    Random rand = new Random();

 

    for (int i = 0; i < 20; i++)

    {

        if (i != 14)

            Chart1.Series[0].Points.AddXY(i + 1, rand.Next(1000));

    }

}

이에 의한 결과는 다음과 같습니다.

얼핏 보기에는 아무런 문제가 없어 보이는 그래프입니다. 사실 아무런 문제가 없기는 합니다. 하지만 그래프에 있는 마커를 잘 살펴보면 15의 위치에는 찍혀있지 않음을 확인할 수 있습니다. 이 그래프의 경우에는 그래프에 마커를 찍어 줌으로서 해당 위치에 값이 있는지 명시하고 있지만 마커가 없다면 이 그래프를 보는 사용자는 마치 15의 위치에 500정도되는 값이 있다고 착각하게 됩니다. 이처럼 공백 값이 마치 공백 값이 아닌 것처럼 보이는 것을 막기 위해서는 첫 번째 예제에서 살펴본 것과 같이 명백하게 이 점이 공백임을 알려주어야 합니다. 이 그래프가 어떤 학생이 받은 시험 점수라고 한다면(별로 그래보이지는 않는 그래프지만요. 무슨 찍기 대회를 하는 것도 아니고 저렇게 시험점수가 촐랑대면서 변할리는 없으니까요) 15번째 시험에서는 0점인데도(시험을 안봤다고 한다면) 500점 정도로 생각되고 위의 그래프에 의한 평균 값이라도 출력하게 되면 이 통계를 보는 사람은 뭔가 이상하다라는 생각을 하게 되겠죠.

아무튼 공백값을 적절하게 처리하지 않았을 경우에 생기는 문제도 살펴보았으므로 이번에는 공백값을 보여주는 방법에 대해서 알아보겠습니다.

다음처럼 HTML 코드를 작성합니다.

<asp:Chart ID="Chart1" Width="600" Height="300" runat="server" ImageType="Png">
  
<series>
    
<asp:Series ChartType="Line" MarkerStyle="Square" BorderWidth="2" 
      Color
="DodgerBlue" ShadowColor="20, 20, 20" ShadowOffset="1" Name="Series1" />
  </
series>
  
<chartareas>
    
<asp:ChartArea Name="ChartArea1" BackGradientStyle="LeftRight" 
       BackSecondaryColor
="240, 240, 240" BackColor="255, 255, 255">                
      
<axisy LineColor="64, 64, 64">
      
<MajorGrid LineColor="180, 180, 180" Interval="100" />
        <
LabelStyle ForeColor="Gray" Font="맑은 고딕, style=Bold" />
      </
axisy>
      
<axisx LineColor="64, 64, 64" Interval="2">
        
<MajorGrid LineColor="180, 180, 180" />
        <
LabelStyle ForeColor="DimGray" Font="굴림, style=Bold" />
      </
axisx>
    
</asp:ChartArea>
  
</chartareas>
</asp:Chart>

그리고 다음처럼 .cs코드를 작성합니다.

protected void Page_Load(object sender, EventArgs e)

{

    double[] yValues1 = new double[20];

 

    Random rand = new Random();

 

    for (int i = 0; i < 20; i++)

    {

        if (i == 14)

            yValues1[i] = double.NaN;

        else

            yValues1[i] = rand.Next(1000);

    }       

 

    Chart1.Series[0].Points.DataBindY(yValues1);

    Chart1.Series[0].Points[14].IsEmpty = true;

 

    Chart1.Series[0].EmptyPointStyle.Color = Color.Gray;

    Chart1.Series[0].EmptyPointStyle.BorderWidth = 2;

    Chart1.Series[0].EmptyPointStyle.BorderDashStyle = ChartDashStyle.Dash;

    Chart1.Series[0].EmptyPointStyle.MarkerSize = 7;

    Chart1.Series[0].EmptyPointStyle.MarkerStyle = MarkerStyle.Cross;

    Chart1.Series[0].EmptyPointStyle.MarkerBorderColor = Color.Black;

    Chart1.Series[0].EmptyPointStyle.MarkerColor = Color.LightGray;

}

코드에 의한 결과는 다음과 같습니다.

이 번에는 공백 부분을 회색의 마커로 지정해 이 값이 회색임을 명백히 알리고 공백 부분의 선 그래프 부분을 회색 파선으로 그려 이 영역의 그래프는 특정한 값을 가지지 않음을 알려주고 있습니다. 시리즈에서 공백으로 표시된 부분을 꾸미기 위해서는 EmptyPointStyle을 사용합니다. EmptyPointStyle에 설정한 여러가지 값은 속성의 이름과 속성의 값이 그 설명 그대로이므로 부가적인 설명은 하지 않겠습니다.

하지만 공백 부분을 회색의 파선과 회색의 십자 마커로 바꿔준 것 만으로도 이전까지의 꽤나 불명확했던 그래프의 형태를 바로잡을 수 있었습니다. 공백값이 있을 것으로 예상되는 그래프에는 이처럼 공백에 대한 처리를 해준다면 불명확한 그래프 표현으로 인한 오해를 방지하는 방법이 될 수 있습니다. 예를 들자면 매년 인구조사를 실시하던 한 나라에서 중간에 한번 인구조사를 못했다고 해서 그 해의 인구를 0으로 표시하는 건 있을 수 없는 일이니까요. 그렇다고 그 해의 값을 비우고 표시한다면 그 나름대로 잘못된 해석의 여지가 생길 수 있습니다. 이것으로 공백 값에 대한 글을 마무리 하겠습니다.

마지막이니 조금 아쉬운 마음에 뽀~너~스로 실시간 그래프에 대해서 간단하게 살펴보고 지나가 보겠습니다. 차트 컨트롤에서 실시간 그래프는 AJAX를 이용해 구현됩니다. 사실 실시간 그래프라는 말이 올바르지 않을 수도 있습니다. ASP.NET에서 제공하는 UpdatePanel과 Timer를 이용해서 Timer_Tick 이벤트가 발생될 때 마다 새로 그려주는 것 뿐이니까요. 하지만 ActiveX나 자바 애플릿등 부가적인 프로그램의 도움을 받아야 구현할 수 있는 것을 HTML표준 요소로만 구현할 수 있다는 것은 꽤 매력적인 부분입니다. 대부분의 최신 브라우저에서 아무런 추가 설치없이 실행되는 그래프라면 약간 어색함이 있더라도 꽤 유용한 기법이 되리라 생각합니다. 그럼 코드를 볼까요?

다음처럼 HTML 코드를 코딩합니다

<form id="form1" runat="server">
  
<div>
    
<asp:ScriptManager ID="ScriptManager1" runat="server" />
    실시간 갱신 그래프<
br />
    <
asp:UpdatePanel ID="up" runat="server">
      
<ContentTemplate>
        
<asp:Chart ID="Chart1" Width="600" Height="300" runat="server" 
            ImageType
="Png" EnableViewState="true">
          
<series>
            
<asp:Series ChartType="Spline" MarkerStyle="Square" BorderWidth="2" 
               Color
="DodgerBlue" ShadowColor="20, 20, 20" ShadowOffset="1" 
               Name
="Series1" />
          </
series>
          
<chartareas>
            
<asp:ChartArea Name="ChartArea1" BackGradientStyle="LeftRight" 
               BackSecondaryColor
="240, 240, 240" BackColor="255, 255, 255">                
              
<axisy LineColor="64, 64, 64">
                
<MajorGrid LineColor="180, 180, 180" />
                <
LabelStyle ForeColor="Gray" Font="맑은 고딕, style=Bold" />
              </
axisy>
              
<axisx LineColor="64, 64, 64" Interval="1">
                
<MajorGrid LineColor="180, 180, 180" />
                <
LabelStyle ForeColor="DimGray" Font="굴림, style=Bold" />
              </
axisx>
            
</asp:ChartArea>
          
</chartareas>
        
</asp:Chart>
        
<asp:Timer ID="tmTimer" runat="server" Interval="1000" OnTick="tmTimer_Tick" />
      
</ContentTemplate>
    
</asp:UpdatePanel>              
  
</div>
</form>

그리고 다음처럼 .cs 코드를 코딩합니다.

protected void Page_Load(object sender, EventArgs e)

{

    if (!Page.IsPostBack)

    {

        Random rand = new Random();

 

        Chart1.Series[0].Points.AddXY(1, rand.Next(100));

 

        double axisMinimum = this.Chart1.Series[0].Points[0].XValue;

 

        this.Chart1.ChartAreas[0].AxisX.Minimum = axisMinimum;

        this.Chart1.ChartAreas[0].AxisX.Maximum = axisMinimum + 19;

 

        this.Chart1.ChartAreas[0].AxisY.Minimum = 0;

        this.Chart1.ChartAreas[0].AxisY.Maximum = 100;

    }

}

 

protected void tmTimer_Tick(object sender, EventArgs e)

{

    Random rand = new Random();

 

    Series series = Chart1.Series[0];

 

    series.Points.AddXY(series.Points[series.Points.Count-1].XValue + 1,

                            rand.Next(100));

 

    while (this.Chart1.Series[0].Points.Count > 20)

    {

        series.Points.RemoveAt(0);           

    }

 

    double axisMinimum = this.Chart1.Series[0].Points[0].XValue;

 

    this.Chart1.ChartAreas[0].AxisX.Minimum = axisMinimum;

    this.Chart1.ChartAreas[0].AxisX.Maximum = axisMinimum + 19;

 

    this.Chart1.ChartAreas[0].AxisY.Minimum = 0;

    this.Chart1.ChartAreas[0].AxisY.Maximum = 100;

}

그리고 이에 의한 결과는 다음과 같습니다.

마지막 뽀~나~스 인 만큼 Ani-Gif로 만들어봤습니다. 그래프는 GIF의 모습처럼 1초에 한번씩 새로운 값을 받아서 그래프를 갱신하는 형태로 되어 있습니다. 이에 대한 여러가지 코드가 있지만 중요한 부분을 살펴보자면.

1. 실시간 그래프로 처리하고자 하는 영역을 UpdatePanel로 감싼다.
2. 갱신하고자 하는 시간 간격 만큼 Timer를 통해서 UpdatePanel을 갱신한다.
   (이 예제에서는 1초에 한번씩 갱신하고 있습니다.)
3. 갱신시마다 Timer_Tick() 메서드에서 그래프를 다시 그려준다.

이것으로 끝입니다. 여기에서는 빈 값에서 시작해서 값을 채우고 값이 정해진 수만큼 채워지면 스라이딩 방식으로 움직이도록 구현되었기 때문에 다소 복잡한 코드가 되었지만 실제 애플리케이션을 작성할때 _Tick() 메서드에서 해당 시점의 그래프를 새로 그려주는 부분만 주의한다면 크게 어렵지 않게 실시간 그래프를 그리실 수 있습니다.

그럼 길다면 길고 짧다면 짧았을 차트 컨트롤에 대한 글을 마무리 하겠습니다. 외전(?)식으로 윈도우즈 프로그래밍에 대한 글을 하나 더 준비하고 있지만 ASP.NET에 대한 글은 이것으로 마무리 되기 때문에 왠지 이것으로 끝이다라는 느낌이 더 크네요. 부족한 필력의 글을 따라오시느라 수고 많으셨습니다.


authored by


 
 
.NET과 Java 동영상 기반의 교육사이트

로딩 중입니다...

서버 프레임워크 지원 : NeoDEEX
based on ASP.NET 3.5
Creative Commons License
{5}
{2} 읽음   :{3} ({4})