개발한 Web OpenAPI를 Spring 프레임워크에서 사용할 때 ..

제목이 참 마땅히 지을만한것도 없고.. 어여 이 곳에 정리해 내 머리속에서 지워버리고자 하는 마음에 지은 제목입니다.

상황은.. jetty를 사용해 지도 OpenAPI를 만들었고, 이 OpenAPI를 Spring 프레임워크를 기본으로 하는 웹 시스템에서 사용하는데, AJAX의 POST 방식으로 OpenAPI를 호출합니다. 이때 이 OpenAPI를 Spring 프레임워크가 아닌 환경에서는 Cross Domain 문제가 발생하지 않습니다. 물론 발생하지 않도록 OpenAPI 서버에 조치를 해두었습니다. 그런데.. Spring 프레임워크에서는 Cross Domain 에러가 발생합니다. 신기한건.. AJAX의 GET 방식은 Cross Domain 에러가 발생하지 않고 POST 만 발생합니다.

먼저 Cross Domain 문제는 아래의 코드를 OpenAPI 서버(jetty를 활용하는 서버)에 적용하여 해결할 수 있었습니다. 코드가 긴데.. 불필요한 코드가 있을거라 생각되지만 일단 모두 기재합니다.

FilterHolder holder = new FilterHolder(CrossOriginFilter.class);

holder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "*");
holder.setInitParameter(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER, "*");
holder.setInitParameter(CrossOriginFilter.ALLOWED_METHODS_PARAM, "GET,POST,HEAD");
holder.setInitParameter(CrossOriginFilter.ALLOWED_HEADERS_PARAM, "X-Requested-With,Content-Type,Accept,Origin");
holder.setName("cross-origin");

FilterMapping fm = new FilterMapping();

fm.setFilterName("cross-origin");
fm.setPathSpec("*");

handler.addFilter(holder, fm);

위의 코드를 OpenAPI 서버에 적용하면 더 이상 Cross Domain 에러가 발생하지 않습니다만, 여전이 문제가 있습니다. POST 방식으로 데이터를 전달 하는데.. 이 데이터의 형식이 일반적으로 흔한 FORM 형태로 전달되어야 합니다. 그런데 Spring에서는 payload라는 형식으로 전달됩니다. 이에 대한 문제는 클라이언트 웹단에서 AJAX 호출시 headers 옵션값을 추가적으로 지정해 주면 해결됩니다. 즉, 아래처럼요.

$.ajax({
    method: 'POST',
    url: url,
    data: ketData,
    headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})

솔찍히 Spring 프레임워크에서 발생하는 문제인지는 모르겠습니다. 단지 Spring 프레임워크가 아닌 환경에서는 문제가 발생하지 않았으므로, 아마도 Spring 프레임워크 환경에서 발생하는 문제라고 추측할 뿐이지만.. 여튼 이와 유사한 문제가 발생할 경우에 대한 해결책으로써 기록을 남깁니다.

[JavaScript] SVG로 PieChart를 위한 도형 그리기

JavaScript 언어를 이용해 SVG에 PieChart를 위한 도형을 생성하기 위한 코드를 함수로 정리해 둡니다. 최종 결과는 아래처럼 4개의 항목으로 구성된 가운데 구멍이 뚫린 모양입니다.

먼저 아래처럼 svg와 PieChart를 구성하는 4개의 항목을 path로 지정해 둡니다. (실제 활용시에는 이 부분을 모두 JavaScript 코드로 동적 생성하도록 해야 합니다)


    
    
    
    

위의 4개의 path에 대해 각각 파이차트의 구성 요소로 만들어 주는 함수는 아래와 같습니다.

function toPieChartItemPath(x, y, radiusIn, radiusOut, startAngle, endAngle) {
    function _toXY(cX, cY, r, degrees) {
        var rad = (degrees) * Math.PI / 180.0;

        return {
            x: cX + (r * Math.cos(rad)),
            y: cY + (r * Math.sin(rad))
        };
    }

    var startIn = _toXY(x, y, radiusIn, endAngle);
    var endIn = _toXY(x, y, radiusIn, startAngle);

    var startOut = _toXY(x, y, radiusOut, endAngle);
    var endOut = _toXY(x, y, radiusOut, startAngle);

    var arcSweep = (endAngle - startAngle) <= 180 ? "0" : "1";

    var d = [
        "M", startIn.x, startIn.y,
        "L", startOut.x, startOut.y,
        "A", radiusOut, radiusOut, 0, arcSweep, 0, endOut.x, endOut.y,
        "L", endIn.x, endIn.y,
        "A", radiusIn, radiusIn, 0, arcSweep, 1, startIn.x, startIn.y,
        "z"
    ].join(" ");

    return d;
}

이 함수의 인자를 설명하면, x와 y는 파이 차트의 중심점이고 radiusIn과 radiusOut은 파이차트의 내부 반지름과 외부 반지름 값입니다. 그리고 startAngle와 endAngle는 시작각도(3시 방향이 0도)와 종료각도(시계방향)입니다. 이 함수를 통해 앞서 구성한 svg와 path 요소를 파이차트로 구성하는 코드는 아래와 같습니다.

document.getElementById("arc1").setAttribute("d", toPieChartItemPath(250, 250, 100, 240, 0, 45));
document.getElementById("arc2").setAttribute("d", toPieChartItemPath(250, 250, 100, 240, 45, 90));
document.getElementById("arc3").setAttribute("d", toPieChartItemPath(250, 250, 100, 240, 90, 180));
document.getElementById("arc4").setAttribute("d", toPieChartItemPath(250, 250, 100, 240, 180, 360));