내겐 너무 이쁜 Fusion Chart

들어가며..

새로운 프로젝트를 들어가면서 처음 접해본 기술은 차트를 그릴 수 있는 Fusion Chart라는 스크립트 API였습니다. 프로젝트에서의 요구사항은 계획과 실적을 비교하여 볼 수 있도록 화면에 표시할 수 있고, 추세선을 선택하여 보여줄 수 있는 그래프를 만드는 것 이였습니다. 그래서 스크립트로 화면에 차트를 그릴 수 있고 잘 정리된 API를 제공하는 “Fusion Chart”라는 유료 차트API를 사용하게 되었습니다.

Fusion Chart 특징

Fusion Chart는 Column차트, Doughnut차트, Line차트. Combination차트, Zoom차트등의 다양한 차트 타입을 제공합니다. Fusion Chart는 JavaScript(SVG)나 Flash로 차트를 표현하고, 차트를 표현하는 데이터 구조는 XML이나 JSON으로 되어있습니다. 차트는 이미지나 PDF 또는 CSV로 추출이 가능합니다. 차트를 제어하기 위한 API는 JavaScript와 jQuery를 사용하여 제어가 가능하기 때문에 웹에서 차트를 표현하기 편하고 모바일에서도 작동되는 장점이 있습니다. trial버전은 무료로 사용할 수 있습니다. 차트에 trial 표시만 추가되고 유료버전과 기능은 같습니다.

차트 외형

Fusion Chart의 기본적인 모습은 이렇습니다.

Fusion Chart는 여러 종류의 차트를 제공하고 있습니다. 데이터나 표현방식에 맞는 차트를 선택하여 사용할 수 있습니다. 예를 들어 장기간의 데이터를 추세선으로 표현하려면 ZoomLine차트를 사용하여 처음에는 전체 데이터를 띄엄띄엄 보여주다가 확대하면서 더 자세하게 보여줄 수 있습니다. 또는 시장 점유율을 표현하길 원한다면 Marimekko차트나 Doughnut차트를 이용하여 각 요소의 점유율을 표현할 수 있습니다.

차트 다루기

Fusion Chart는 기본적으로 XML 또는 Json형식의 데이터를 받아 Fusion Chart 스크립트로 차트를 만들어 HTML Element에 자식 요소로 삽입하는 형식으로 화면에 표현합니다. 차트를 그리기 위한 데이터는 특정 구조로 이루어져있기 때문에 서버에서 받은 데이터가 해당 구조와 다르다면 차트를 그리기 위한 데이터 변환을 해야 합니다.

1. 데이터 구조

차트를 그리기 위한 데이터는 차트 property는 Json객체로 되어있습니다. 차트 property는 여러 속성들로 되어있고, 속성 중 dataSource는 차트 attribute와 차트 데이터(XML 또는 XML URL 또는 Json URL 또는 Json Object) 등으로 이루어져 있습니다.

  • id : 차트를 구분하기 위한 ID
  • swfUrl : 차트swf파일의 경로를 포함한 차트 유형
  • renderAt : 차트가 삽입될 HTML Element ID
  • dataSource : 차트를 표현하기 위한 데이터
  • dataFormat : dataSource의 형태( xml / xmlurl / json / jsonurl )
  • renderer : 차트의 표현 형식 ( javascript / flash )

차트 property중 dataSource는 차트의 attribute를 가지고 있습니다. 차트의 속성은 차트의 유형에 따라 다르며 많은 속성들이 있습니다. 각 차트의 속성들은 Fusion Chart에서 제공하는 문서에 잘 정리되어있습니다.(http://docs.fusioncharts.com/charts/ FusionCharts XT >> Chart XML API )

dataSource의 간단한 예는 아래와 같습니다.

xml

<chart yAxisName="Sales Figure" caption="Top 5 Sales Person" numberPrefix="$" useRoundEdges="1" bgColor="FFFFFF,FFFFFF" showBorder="0">
        <set label="Alex" value="25000"  /> 
        <set label="Mark" value="35000" /> 
        <set label="David" value="42300" /> 
        <set label="Graham" value="35300" /> 
        <set label="John" value="31300" />
</chart>

json

{
  "chart": {
    "showborder": "0",
    "bgcolor": "FFFFFF,FFFFFF",
    "useroundedges": "1",
    "numberprefix": "$",
    "caption": "Top 5 Sales Person",
    "yaxisname": "Sales Figure"
  },
  "data": [
    {
      "value": "25000",
      "label": "Alex"
    },
    {
      "value": "35000",
      "label": "Mark"
    },
    {
      "value": "42300",
      "label": "David"
    },
    {
      "value": "35300",
      "label": "Graham"
    },
    {
      "value": "31300",
      "label": "John"
    }
  ]
}

차트의 dataSource는 XML이나 XML파일을 위한 XML URL, 또는 Json 객체나 Json URL을 사용할 수 있습니다. dataSource는 크게 chart 속성과 data로 구성되어 있고, 차트의 ttribute로 차트의 디자인 요소를 설정할 수 있으며 data로 차트에 그려질 데이터를 정의할 수 있습니다.

2. 차트 데이터 종류

차트 attribute 중 data에는 Single Series(SS) 차트와 Multi Series(MS) 차트가 있습니다.
SS차트는 하나의 카테고리(xAsix 항목)에 하나의 데이터를 나타내는 차트이고, MS차트는 하나의 카테고리에 여러 데이터를 나타내는 차트입니다. 이것은 dataSource항목의 구조로 나타나는데 SS차트는 위에 예제에서 보듯이 chart항목과 data항목으로 이루어져있습니다. MS차트는 SS차트와 다르게 chart항목과 categories항목, dataset항목으로 이루어져있습니다.

Single Series 차트

"chart": {
    // 속성들
},
"data": [
    // label과 value를 요소로 하는 객체의 배열
]

Multi Series 차트


index_html_20131227_165122

"chart": {
    // 속성들
},
"categories": [
    // 배열이지만 하나의 category만 가지고있음
    // category는 label을 배열로 가지고 있음
],
"dataset": [
    // data를 배열로 가지고 있음(Single Series의 data와 다름)
]

이렇게 데이터를 어떻게 차트로 표현하냐에 따라 차트를 그리기 위한 데이터 형식도 달라집니다.
하지만 같은 Series의 차트는 서로 같은 형식을 사용하기 때문에 차트에 맞게 chart 속성만 바꿔준다면 사용 가능합니다. 제가 있던 프로젝트에서는 MS차트만 사용하였기 때문에 서버에서 받은 데이터를 차트형식에 맞게 바꾸는 로직을 공통으로 사용하고 chart속성만 따로 추가하여 차트를 만들었습니다. 차트의 기본적인 속성들은 같은 것이 많기 때문에 Column차트를 Line차트로 바꾼다고 하여도 같은 dataSource로 표현할 수 있습니다. 그리고, chart속성 중 특정 차트에서만 쓰는 속성을 가지고 있다고 하더라도 같은 Series내의 다른 차트에서 같은 dataSource를 사용해서 그릴 때 해당 속성은 무시하고 그려지기 때문에 차트간 호환도 가능합니다. 그리고 MS차트 중에는 dataset이 dataset을 가지고 있는 차트가 있습니다

"chart": {
    // 속성들
},
"categories": [
    // category
],
"dataset": [
    // dataset배열
    // Multi Series의 dataset을 배열로 가지고 있음
]

각 항목에 두 개의 Column데이터가 표현되고 각 Column은 여러 개의 다른 데이터를 표현하고 있는 차트입니다. 위의 차트는 하나의 dataSet이 product A와 product B 항목을 가지고 있고, 다른 dataSet은 ServiceA, Service B, Service C 항목을 가지고 있으며 이 두 개의 dataSet은 하나의 dataSet에 배열로 들어있습니다.

3. 차트 그리기

Fusion Chart에서는 차트를 그리기 위한 API를 JavaScript와 jQuery로 제공합니다.
웹 페이지에 차트를 그리기 위해서는 FusionCharts.js가 필요하고, jQuery API를 사용하기 위해서는 FusionCharts.jqueryplugin.js가 필요합니다. 그리고 FusionCharts.js는 내부적으로 FusionCharts.HC.js와 FusionCharts.HC.Charts.js를 사용합니다.

- 차트 데이터 만들기(데이터를 차트에 맞게 구조화한 결과)

var makeChartData = function(){
    return {
        "chart": {
            "baseFont" : "굴림",
            "baseFontSize" : 12,
            "valueposition": "auto",
            "rotatevalues": "1",
            "showvalues": "1",
            "yaxisvaluespadding": "10",
            "labelpadding": "10",
            "divlinealpha": "30",
            "numvdivlines": "10",
            "bgcolor": "F7F7F7, E9E9E9",
            "yaxisname": "금액(억)",
            "caption": "계획 / 실적 비교"
        },
        "categories": [
            {
                "category": [
                    { "label": "2006" },
                    { "label": "2007" },
                    { "label": "2008" },
                    { "label": "2009" },
                    { "label": "2010" },
                    { "label": "2011" }
                ]
            }
        ],
        "dataset": [
            {
                "color": "A66EDD",
                "seriesname": "계획",
                "data": [
                    { "value": "35" },
                    { "value": "42" },
                    { "value": "31" },
                    { "valueposition": "above", "value": "28" },
                    { "value": "34" },
                    { "value": "30" }
                ]
            },
            {
                "color": "F6BD0F",
                "seriesname": "실적",
                "data": [
                    { "value": "22" },
                    { "value": "25" },
                    { "value": "18" },
                    { "value": "22" },
                    { "value": "17" },
                    { "value": "16" }
                ]
            }
        ]
    };
};

- 차트 property 만들기

var makeChartConf = function(eleId, chartId, chartType, chartData, dataType, renderer){
    return {
        id : chartId,
        swfUrl : CHART_SWF_PATH + chartType + ".swf",
        renderAt : eleId,
        dataSource : chartData,
        dataFormat : dataType ||"JSON",
        renderer : renderer || "flash",
        width: "400",
        height: "300"
    };
};

- 차트 property로 차트 만들기

var drawChart = function(){
    var chartId = "chartId";
    var chartType = "ZoomLine";
    var renderer = "Flash";
    var dataType = "JSON";

    FusionCharts.render(makeChartConf("chart_div", chartId, chartType, makeChartData2(), dataType, renderer));
};

4. 결과

두 차트 모두 위에 있는 스크립트를 이용하여 render방식만 다르게 그린 차트입니다. 차트의 유형은 ZoomLine차트이고 왼쪽은 JavaScript(SVG)로 그린 차트이며, 오른쪽은 Flash로 그린 차트입니다.

Fusion Chart는 Flash나 SVG로 그려지며 JavaScript 또는 jQuery로 제어합니다. 차트 모양과 애니메이션에 있어서 Flash와 SVG가 차이가 있습니다. 대부분 차트에서 Flash가 더욱 부드러운 애니메이션과 디자인을 보여줍니다. 그리고 차트 속성 중 Flash에서만 표현되는 속성들도 있어서 특별한 제약조건이 없다면 Flash로 차트를 그리는 것이 좋은 것 같습니다.

마치며…

FusionChart는 각 차트마다 다양한 속성들을 가지고 있습니다. 모든 차트가 공통적으로 가지고 있는 속성이 있기도 하고, 각 차트가 가지고 있는 고유 속성들이 있습니다. 따라서 차트를 그릴경우 기본적인 속성만 사용한다면 간단하게 그릴 수 있지만, 약간의 디자인을 변경하기 위해서는 그에 해당하는 차트 속성을 찾아서 적용해야 합니다. 이 속성이 많기 때문에 찾기 힘든 것도 있고, 차트마다 JavaScript로 그린경우와 Flash로 그린경우 속성이 적용되지 않거나 다르게 보이는 부분이 있어 차트 디자인 수정은 간단하지는 않습니다. 이런 부분이 개발자와 웹 디자이너가 분담하여 작업하기 힘들어지는 부분 같습니다.

만약 기간 데이터를 표시할 경우 xAixs에 연도와 월을 따로 표시해야 경우가 있는데 FusionChart는 xAxis에 두 가지 데이터를 표현 할 수 없어 불편한 점이 있었습니다. 월을 연속적으로 표시하고 중간에 연도를 표시하기 위해서는 Vertical Trend Line이나 Vertical Divisional Line을 사용하여 연도 구분을 해줘야 합니다.

위의 이미지는 엑셀에서 만든 차트입니다. 위의 이미지처럼 xAxis에 년도와 월을 모두 표시가 가능하지만 Fusion Chart에서는 xAxis에 하나의 데이터만 표현이 가능합니다.

그래서 위와 같이 차트에 직접 년도를 표시해야 하는 방법으로 해결하였습니다. 하지만 이런 방법도 차트에 종류에 따라, render방식에 따라 안되는 경우도 있습니다. ZoomLine차트의 경우 render형식을 JavaScript로 할 경우 VTrendLine 속성을 사용하더라도 표현이 안되는 문제가 있습니다.

제가 있었던 프로젝트에서는 차트를 그리기 위해 서버에서 데이터를 조회한 후 차트 dataSource형식에 맞는 Json으로 변환하기 보다는 서버에서 간단하게 Json형식으로 변환하고 차트에 맞는 구조로 만드는 것은 화면에서 처리하도록 하였습니다. 이유는 여러 화면에 각각 조금씩 다른 차트가 들어가는데 이것을 서버에서 차트에 맞게 일일이 구조화하는 것 보다 화면에서 디자인 처리와 같이 데이터 구조화를 하는 것이 더 효율적 이고, 디자인을 적용하기 위한 속성이 dataSource 항목 중 “chart”항목에만 들어가는 것이 아니라 data에 직접 수정해야 하는 것들도 있어서 따로 처리하는 문제도 있었습니다.

namoosori
안녕하세요. 나무소리 입니다. 나무소리는 넥스트리(주)의 교육 브랜드 입니다.넥스트리가 지난 20년 동안 쌓아온 개발 및 교육 경험들을 나무소리를 통해 많은 분들과 공유 하려고 합니다.앞으로 저희 나무소리를 통해 보다 나은 교육을 경험 하실 수 있도록 구성원 모두 최선을 다하겠습니다.