WebSocket과 Web에서의 Javascript를 통한 바이너리 데이터 통신

크아! 제목 한번 요상합니다. JavaScript가 클라이언트 뿐만 아니라 Java나 서버단(Node.js 등)에서도 활용되다 보니… 여튼, WebSoket과 웹에서의 Javascript를 통한 통신의 예로 Binary 데이터 타입을 주고 받는 코드를 정리합니다. 이 글은 텍스트 타입의 데이터를 주고 받는 [jetty를 이용한 WebSocket 서버 구현하기]라는 글을 기반으로 작성된 글입니다.

WebSocket을 위한 서버는 jetty를 활용하였습니다. 먼저 클라이언트가 서버 단에 바이너리 데이터가를 전달하는 코드는 다음과 같습니다.

var buffer = new ArrayBuffer(8);
var dataview = new DataView(buffer);

dataview.setInt32(0, 9438);
dataview.setFloat32(4, 3224.3224);
            
webSocket.send(buffer);

8 Bytes 크기의 데이터 덩어리를 만들고, 이 덩어리 안에 Int와 Float 타입에 대한 값으로 각각 9438과 3224.3224를 넣어서 웹소켓으로 전송하는 코드입니다. 이렇게 전송하면 서버가 받아야 하는데, 아래의 코드는 서버 측의 코드입니다.

@Override
public void onWebSocketBinary(byte[] payload, int offset, int len)
{
    if ((outbound != null) && (outbound.isOpen()))
    {
        InputStream is = new ByteArrayInputStream(payload);
        DataInputStream dis = new DataInputStream(is);
    		
        try {
            int v1 = dis.readInt();
            float v2 = dis.readFloat();
            double result = (double)v1 * (double)v2;
    			
            ByteBuffer bb = ByteBuffer.allocate(8);
            bb.putDouble(0, result);
            outbound.getRemote().sendBytes(bb);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

10번과 11번에서 클라이언트가 보낸 int와 float 값을 읽고, 엄청나게 복잡한 연산인 곱의 결과 값을 16번 코드에서 클라이언트로 전달하고 있는 코드입니다. 이제 아래는 다시 클라이언트가 서버가 계산한 소중한 결과를 받는 코드입니다.

webSocket.onmessage = function (message) {
    var blob = message.data;
    var fileReader = new FileReader();

    fileReader.onload = function (event) {
        var arrayBuffer = event.target.result;
        var dataview = new DataView(arrayBuffer);
        var answer = dataview.getFloat64(0);

        alert("Server> : " + answer);
    };

    fileReader.readAsArrayBuffer(blob);
};

서버로부터 받는 바이너리 데이터는 blob 형식으로 받습니다. 이 데이터는 FileReader를 통해 읽어 해석할 수 있습니다. 이상으로 웹소켓에서 바이너리 데이터를 주고 받는 코드에 대한 글을 정리한 글이였습니다.

Mr.Tiler-Xr을 이용한 배경맵 디자인 기능

Mr.Tiler-Xr을 통한 배경맵 디자인 기능에 대한 소개입니다. 공개된 DB를 활용했고, 활용한 레이어는 행정구역도, 실폭도로, 도로중심선, 건물입니다. 보다 더 다양한 레이어를 사용하면 더욱 세련된 배경지도를 디자인할 수 있습니다.

위처럼 디자인된 배경지도는 다시 Mr.Tiler-Xr에서 타일맵(Tile Map)으로 가공되어 웹에서 서비스 될 수 있습니다. 전국범위에 대해서도 매우 빠르게 가공될 수 있고, 변경된 영역에 대해서만 가공되어 다시 전체에 반영될 수 있습니다.

넥스젠(NexGen)의 DEM 데이터를 활용한 측정 기능

“넥스젠 GIS 기반 솔루션”은 항공영상, DEM, 수치지도 등과 같은 공개된 공간 DB를 활용할 수 있는 시스템으로, 주소 검색 등과 같은 기본적인 GIS 기능을 제공하는 솔루션으로써, 별도의 커스터마이징 작업을 통해 고객이 원하는 공간 DB와 기능을 추가할 수 있습니다. 아래는 넥스젠에서 DEM 데이터를 활용해 수행할 수 있는 표고 측정, 단면도 측정, 평균경사도측정과 3차원 가시화 기능에 대한 동영상입니다.

PostgreSQL의 Function 요약

아래는 PostgreSQL의 함수를 요약한 내용이며, 보다 자세한 내용과 예제는 https://www.techonthenet.com/postgresql/functions/index.php 참고하기 바랍니다.

String Functions

  • btrim : 문자열의 시작과 끝 양쪽에 지정된 문자들을 제거
  • char_length : 문자열의 길이를 반환
  • character_length : 지정된 문자열의 길이를 반환
  • || : 2개의 문자열을 합하여 반환
  • initcap : 문자열 중 첫번째 문자는 대문자로 변환하고 나머지는 소문자로 변환
  • length : 문자열의 길이를 반환
  • lower : 지정된 문자열을 모두 소문자로 변환
  • lpad : 지정된 문자열을 원하는 길이로 맞추는데, 이때 부족한 문자를 왼쪽에 채움
  • ltrim : 문자열의 왼쪽에서 지정된 모든 문자를 제거
  • position : 문자열에서 지정된 문자열이 존재하는 인덱스값을 반환
  • repeat : 문자열을 원하는 만큼 반복해서 반환
  • replace : 기존의 문자열을 구성하는 부분 문자열을 원하는 문자열로 변환
  • rpad : 지정된 문자열을 원하는 길이로 맞추는데, 이때 부족한 문자를 오른쪽에 채움
  • rtrim : 문자열의 오른쪽에서 지정된 모든 문자를 제거
  • strpos : 기존의 문자열에서 찾고자 하는 부분 문자열의 위치를 반환
  • substring : 주어진 문자열에서 원하는 부분 문자열을 추출
  • translate : 기존의 문자열 중 치환하고자 하는 문자열을 지정해 변환
  • trim : 문자열의 시작과 끝 양쪽에 지정된 문자들을 제거
  • upper : 문자열을 모두 대문자로 변환

Numeric/Math Functions

  • abs : 절대값 반환
  • avg : 평균값 반환
  • ceil : 소수점 자리를 무조건 올려 정수 반환
  • ceiling : 소수점 자리를 무조건 올려 정수 반환
  • count : 개수 반환
  • div : 2개의 수를 나눠서 그 몫(정수)을 반환
  • exp : e(2.71828182845904)의 제곱값 반환
  • floor : 지정된 수와 같거나 작은 정수 반환
  • max : 최대값 반환
  • min : 최소값 반환
  • mod : 2개의 수를 나눈 그 나머지 반환
  • power : 거듭 제곱의 결과 반환
  • random : [0~1) 사이의 난수값 반환
  • round : 원하는 자리수에서의 반올림한 값을 반환
  • setseed : 난수 발생시 그 씨앗값을 설정.
  • sign : 주어진 수에 대한 부호 반환.
  • sqrt : 루투(root) 값 반환.
  • sum : 합계 반환.
  • trunc : 원하는 자리수까지의 값을 반올림 없이 반환

Date/Time Functions

  • age : 두 날짜 사이의 시간 간격을 년, 월, 일로된 문자열로 반환
  • current_date : 현재의 날짜 반환
  • current_time : Time Zone을 갖는 현재의 시간을 반환
  • current_timestamp : Time Zone을 갖는 현재의 날짜와 시간을 반환
  • date_part : 시간 또는 날짜로부터 원하는 부분(년, 월, 일, 시, 분, 일, 초 등)을 반환
  • extract : 시간 또는 날짜로부터 원하는 부분(년, 월, 일, 시, 분, 일, 초 등)을 반환
  • localtime : 현재의 시간을 반환
  • localtimestamp : 현재의 시간과 날짜를 반환
  • now : Time Zone을 갖는 현재의 날짜와 시간을 반환

Conversion Functions

  • to_char : 숫자 또는 날짜를 문자열로 변환
  • to_date : 문자열을 날짜로 변환
  • to_number : 문자열을 숫자로 변환
  • to_timestamp : 문자열을 타임스탬프(Timestamp)로 변환

PostgreSQL의 프로시져(PL/pgSQL) 예제

추후 PostgreSQL에서 프로시져를 작성할 때 참조하기 위해 글을 남깁니다.

CREATE OR REPLACE FUNCTION 
    get_two_rows(id1 TEXT, lyr1 TEXT, id2 TEXT, lyr2 TEXT) 
RETURNS 
TABLE (geom GEOMETRY)
AS $$
BEGIN
	RETURN QUERY EXECUTE
		'SELECT the_geom FROM ' || lyr1 || ' WHERE networkid::text = ''' || id1 || '''' || 
		' UNION ALL ' || 
		'SELECT the_geom FROM ' || lyr2 || ' WHERE networkid::text = ''' || id2 || '''';

END; $$
LANGUAGE PLPGSQL;

SQL문을 문자열 형태로 조합해서 실행하기 위해 ‘QUERY EXECUTE’를 사용해야 하며, 외따옴표(‘)를 문자열에 넣기 위해 연속된 외따옴표 2개가 필요하다는 것에 주의해야 합니다.

사실 위의 프로시져는 단순해서 그냥 SQL문을 통해 Java의 PrepareStatement를 사용해 실행해도 되는데.. PrepareStatement를 통한 SQL 문 실행시 SQL의 문자열 값 중 SELECT의 FROM절에 대한 테이블명은 바인딩할 수 없다(?에 의한..)는 제약때문에 프로시져를 사용하게 되었습니다. 소스코드에 대한 정적검사에서 SQL문에 대한 SQL Injection 보안성 오류로 지적받아.. 위와 같이 상당히 불필요한 프로시져까지 사용하게 되었습니다.