본문 바로가기

토공데

토스트 그리드를 통한 공공데이터 제어 프로젝트[5] - 파라미터에 의한 차트

반응형

이전 게시글에서 파라미터 없는 차트 아닌 차트를 만들었습니다.

실제 구현과정에서 이 부분이 가장 시간이 오래 걸렸다고 해도 과언이 아닐 정도로 저에겐 끝판왕 도전과제 였는데요

 

저에게 있어 중요한 내용도 많고 Toast UI 의 차트 구글 내용이 적은 만큼 잘 적어보겠습니다

 


 

 

		$.ajax({
				url : "/togongda/searchCovidChart",
				method : "POST",
				dataType : "JSON",
				data : JSON.stringify({
					"resultArray" : JSON.stringify(resultArray), 
                        "dateArray" : JSON.stringify(dateArray)  
				}),
				contentType : "application/json; charset=UTF-8",
				success : function(list) {
							chart.setData({
				  categories: dateArray,
				  series: list
				});
				
				}//chart suc
					
			}); //ajax

조회 버튼을 눌렀을 때 실행되는 ajax 함수입니다.

ajax에서 넘겨줄 data는 그리드와 동일하게 날짜범위와 지역명을 받습니다.

그 이후 컨트롤러에서 값을 리턴한 값을 series에 넣는게 핵심입니다.

 

우선 그 이후의 컨트롤러 코드를 보기 전 꼭 확인해야 할 내용이 있습니다.

그것은 API 문서 입니다.

 

우리가 차트에 데이터를 뿌려줄 메서드인 setData는 다음과 같은 형식을 받습니다.

즉 이 형식에 맞춰야 차트가 동작한다는 의미겠죠

카테고리는 String이 들어간 배열

series의 name에는 String

data는 Int가 들어간 배열이 있어야 하는구나! 를 이 문서를 보고 아셔야 합니다.

 

강조 표시한 내용을 주의깊게 보셔야 할겁니다..

 

이 내용을 숙지하셨으니 컨트롤러 코드부터 살펴보겠습니다.

 


 

 

@PostMapping(value = "/searchCovidChart")
	public  ResponseEntity<List<Map<String, Object>>>  searchCovidChart(@RequestBody Map<String, Object> params) throws IOException {
		
		String resultStr = (String) params.get("resultArray");
		String resultStr1 =resultStr.substring(0, resultStr.length()-1);		
        String resultStr2 = resultStr1.substring(1);
        
        String[] resultArray = null; 
        resultArray = resultStr2.split(",");  

		String date = (String) params.get("dateArray");
		String date1 =date.substring(0, date.length()-1);		
        String date2 = date1.substring(1);
        
        String[] dateArray = null; 
        dateArray = date2.split(",");
        
        
        List<Map<String, Object>> result = null; //마지막에 return할 List 선언
        result = new ArrayList<>();  //list 초기화

        for(int i=0; i<dateArray.length;i++) {
        	for(int j=0; j<resultArray.length;j++) {
		String xml = getCovidData((dateArray[i].substring(0, dateArray[i].length()-1)).substring(1),(resultArray[j].substring(0, resultArray[j].length()-1)).substring(1));
		Object json = XML.toJSONObject(xml); //xml -> json
        String jsonStr = json.toString(); // json -> string
        JsonParser jsonParser = new JsonParser();
        JsonObject jsonObject = (JsonObject)jsonParser.parse(jsonStr); 
        JsonObject covidInfoResponse = (JsonObject)jsonObject.get("response");
        JsonObject covidInfoBody = (JsonObject)covidInfoResponse.get("body"); // pageNo, totalCount
        JsonObject covidInfoItems = (JsonObject)covidInfoBody.get("items");
        
        JsonArray covidInfoItem = (JsonArray)covidInfoItems.get("item");   //item은 배열 형태 이기 때문에 JsonArray 형태로 변환
        int len = covidInfoItem.size(); //JsonArray의 개수를 len에 대입
        for (int k=0;k<len/2;k++){ //배열 크기만큼 반복
     	  JsonObject jso = (JsonObject) covidInfoItem.get(k); //JsonArray안에 있는 값들의 순서대로 JsonObject로 변환
     	  Map<String, Object> map = getMapFromJsonObject(jso); //변환한 JsonObject는 JSONObject를 Map<String, String> 형식으로 변환처리
        
     	  Map<String, Object> chartMap = new HashMap<String, Object>();
     	    chartMap.put("gubun",map.get("gubun"));
            chartMap.put("stdDay",map.get("stdDay"));
            chartMap.put("qurRate",map.get("qurRate")); //만명당 발생확률

     	  result.add(chartMap); //변환한 jso가 담긴 map이 list에 순서대로 담음
        }
        }
        }
        System.out.println(result); 

        

        List<Map<String, Object>> chartList =  new ArrayList<>();   //마지막에 return할 List 선언
        
        for(int i=0; i<resultArray.length;i++) {
	        Map<String, Object> chartMap1 = new HashMap<String, Object>(); 
			chartMap1.put("name", result.get(i).get("gubun").toString());

	        int suc = 0;
	        List<Integer> qurRateList = new ArrayList<Integer>(dateArray.length);  //날짜가 3일이면 3일만큼만 들어가게끔 배열 생성 구분갯수만큼 생성(초기화)하면 됌
        	for(int j=0; j<dateArray.length*resultArray.length;j++) {

        		if(result.get(j).get("gubun").equals(resultArray[i].substring(0, resultArray[i].length()-1).substring(1))) { 
        	        suc = suc+1;
        	        
        			String qurRateStr = result.get(j).get("qurRate").toString();
        			int qurRateInt = Integer.parseInt(qurRateStr);
            	    qurRateList.add(qurRateInt);		 //qurRateList 내부에는 인트값만 있음
        			
        			if(suc == dateArray.length) {        	
                	chartMap1.put("data", qurRateList);
        			}
            	    }

        	} //날짜 횟수 반복문 end

        	chartList.add(chartMap1);

        } // 구분 횟수 반복 end
        
        System.out.println(chartList);
        
		return ResponseEntity.ok().body(chartList);
	}

chartMap을 result 리스트에 담는 내용까지는 동일한 내용이기 때문에 생략하고 이후부터 설명드리겠습니다

 

1. chartList는 마지막에 담길 Map이 담긴 List

2. chartMap1은 chartList에 담길 Map

3. qurRateList는 qurRate(만명당 발생확률 값)이 담길 Integer가 담기는 List

 

위에서 설명드렸지만 ajax에선 list가 series의 값으로 대입됩니다.

즉 series의 형식에 맞는 데이터를 컨트롤러에서 제공해야 합니다.

 

이렇게 출력해야 하죠

 

가장 큰 chartList안에 chartMap1에 name과 data가 담기는데 data에는 Integer 타입의 값이 담긴 qurRateList가 담기는 것입니다.

 

 

for문 관련 로직에 대해 쉽게 설명드리자면 다음과 같습니다.

 

파라미터로 받은 지역명의 개수만큼 반복{

chartMap1에 name을 담습니다.

 

qurRate를 담을 qurRateList 배열 생성, 초기화

qurRate를 날짜수만큼 받을 수 있도록 준비(int suc=0;)

파라미터로 받은 날짜 x 지역명의 개수 만큼 반복{

만약 지역명이 동일하다면 qurRate를 형변환 후 qurRateList에 담고 suc를 증가시킨다

 

만약 suc가 날짜수만큼 증가했다면 (지역명에 맞는 데이터 값이 모두 채워졌다면)

chartMap1에 qurRateList를 담는다

}

chartMap1을 가장 큰 chartList에 담습니다.

}

 

좀 알록달록하게 설명글을 작성했지만 제가 생각한 로직은 위와 같습니다.

 

 

시행착오로는 javascript에서 map으로 받은 데이터를 HashMap으로 변경하는 코드를 들고와서 데이터를 넣어보려고 한 적도 있고 JSON.stringify를 통해 컨트롤러로부터 받은 데이터를 series에 넘겨주려고도 했었습니다.

 

하지만 위 글에서 강조했던 형식의 데이터가 아니였기 때문에 차트가 출력되지 않았었고

결과적으로 api 문서를 읽고 로직을 변경하여 차트를 완성시켰습니다.

 


결과화면은 다음과 같습니다.

 


만명당 발생확률이지만 우선 데이터 출력을 위해 따로 처리는 하지 않은 상태인데

추후적으로 마무리 때 해결하도록 하겠습니다.

 

 

++ 수정

 

qurRate (만명당 발생확률)을 10000으로 나누어 수치를 변경한 결과 수치가 낮아짐에 따라 가시성이 좋지 않아

기존 10000을 나누지 않은 상태의 기존으로 진행하는 것으로 마무리 하였습니다.

 

 

반응형