[미국 SGIP 2016 전시회] MicroGrid Platform 중 GIS Studio

금번 미국에서 SGIP 2016 전시회에 한국전력연구원에서 개발 중인 MicroGird Platform이 세계적으로 소개 되고 있습니다. MicroGrid Platform은 전력설비 감시를 위한 SCADA Platform, 전력 분석을 위한 SCL Studio, 전력 사업자 및 개발자들을 하나로 모아 참여할 수 있는 Smart Portal & API, 위치기반의 전력설비 관리를 위한 GIS Studio, 전력 사업자가 자신이 생산한 전력을 판매하기 위한 입찰 시장인 New Market Service 등으로 구성되는데요. 이중 회사에서는 GIS Studio를 개발하고 있습니다. 전시회를 위해 만든 팜플렛이 있기에 GIS Studio를 올려 봅니다.

웹 기반의 Map Viewer 및 Editor는 FingerEyes-Xr for HTML5를 사용했고, 공간서버(Spatial Server)는 GeoService-Xr이 이용되었으며, DBMS는 PostgreSQL + postGIS가 사용 되었습니다.

현재 전력 설비 표출과 신규 및 변경된 전력 설비를 웹에서 바로 편집할 수 있는 기능을 마무리하는 단계이고, 이제 역률, 부하, 전압, 주파수 등에 대한 전력 계측값 및 분석값을 지도 상에 어떻게 효과적으로 표현함으로써 해당 분야의 전문가에게 새로운 영감을 줄 수 있을지 상당한 고민이 반영되어야 할 단계입니다.

FingerEyes-Xr for HTML5 – ShapeMapLayer의 도형정보 및 속성 정보 접근

FingerEyes-Xr for HTML5의 레이어 중 ShapeMapLayer에 대해, 도형 정보 및 속성 정보에 접근하는 코드를 정리해 봅니다. 참고로 아래 코드는 Point 타입의 ShapeMapLayer에 대한 코드입니다.

var snodeLayerId = snode.layerId(); // Layer Id
var snodeNetworkId = snode.nodeId(); // 검색할 필드값
var snodeLayer = g_map.layers(snodeLayerId);
var snodeRowset = snodeLayer.shapeRowSet();
var snodeAttrRowset = snodeLayer.attributeRowSet();
var snodeFieldSet = snodeLayer.fieldSet();
var snodeRows = snodeRowset.rows();
var idxNetwordId = snodeFieldSet.fieldIndex('networkid'); // 검색 대상 필드명

for (var fid in snodeRows) {
    var attRow = snodeAttrRowset.row(fid);
    var vNetworkId = attRow.valueAsString(idxNetwordId);

    if (vNetworkId == snodeNetworkId) {
        var psRow = snodeRows[fid];
        var psData = psRow.shapeData();
        var pt = psData.data();

        alert(pt.x + " " + pt.y);

        break;
    }                    
}

Java8, Stream에 대한 병렬처리

Java 8에서 제공하는 스트림(Streams)에 대한 기능에 대해 정리한 적이 있습니다. Java 8에서 스트림은 List 등과 같은 자료구조를 통해 생성할 수 있는 메모리 상의 또 다른 자료구조인데요. 이 스트림 자료구조를 통해 Filter, Sorted, map, forEach, anyMatch, allMatch, noneMatch, count, Reduce 맴버 함수를 호출할 수 있으며, 이러한 함수 호출에 대해 하나의 스레드만을 사용해 처리할 것인지, 아니면 멀티 스레드를 통해 병렬로 처리할 것인지 개발자가 매우 간단히 정할 수 있는 매커니즘을 제공합니다.

예를 들어서, 백만개의 UUID 문자열을 담고 있는 리스트가 있다고 합시다. 즉, 아래의 코드를 통해 메모리 상에 구성될 수 있습니다.

public static void main(String args[]) {
    int max = 1000000;
    List values = new ArrayList<>(max);
		
    for (int i=0; i

11번과 12번 코드가 각각 백만개의 문자열를 갖는 리스트를 정렬하는 방식을 하나의 스레드로 할 것인지, 멀티 스레드로 처리할 것인에 대한 함수 호출입니다. 먼저 sequential 함수를 살펴보면 아래와 같습니다.

public static void sequential(List v) {
    long t0 = System.nanoTime();
    /*long count = */ v.stream().sorted().count();
    long t1 = System.nanoTime();
		
    long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
    System.out.println(String.format("sequential sort took: %d ms", millis));
}

3번 코드가 스트림에서 제공하는 sorted 함수를 통해 직관적으로 정렬하는 것으로써 코드 한줄이지만 그 내부는 다소 복잡하고, 특히나 백만개에 대한 정렬이므로 상당한 CPU 리소스를 사용할 것입니다. 그리고 다음은 멀티 스레드를 통한 parallel 함수입니다.

public static void parallel(List v) {
    long t0 = System.nanoTime();
    /* long count = */ v.parallelStream().sorted().count();
    long t1 = System.nanoTime();
		
    long millis = TimeUnit.NANOSECONDS.toMillis(t1 - t0);
    System.out.println(String.format("parallel sort took: %d ms", millis));
}

sequential 함수와의 차이점이라고는 오직 스트림을 생성하기 위해 3번 코드의 stream() 대신 parallelStream() 호출입니다. 이제 실행해 보면 제 노트북에서는 다음과 같은 결과가 나옵니다.

sequential sort took: 708 ms
parallel sort took: 244 ms

제 노트북이 멀티 코어 CPU이므로 동일한 연산이지만 병렬로 정렬하는데 소요되는 시간이 훨씬 더 빠른 처리된 결과를 볼 수 있습니다. Java 8에서 제공하는 스트림을 통해 데이터의 덩어리를 매우 직관적이며 매우 쉽게 병렬로 처리할 수 있다는 것을 알 수 있습니다.

요즘 golang과 같은 최신의 언어에서도 그렇고... Java나 C++과 같은 언어에서 람다 지원을 통해 작성된 코드를 살펴봐도 그렇고.. OOP 보다는 함수 지향적인 코딩이 상당히 강조되는 것을 느낍니다. OOP 적인 사고방식 보다는 컴포지션(Composition)과 재귀적 호출을 통한 함수 작성 그리고 짧은 코드로 구성한 단위 함수들의 조합을 통한 프로그래밍 방식에 익숙해 지는 것이 필요할 듯 합니다.

[Golang] 변수가 어떤 interface의 매서드를 제공하는지 여부 확인하기

다음과 같은 타입이 있다고 치십시다.

type Boy int

func (b Boy) fight() {
	fmt.Println("Kaho-!")
}

func (b Boy) laugh() {
	fmt.Println("Kuwek-!")
}

type Girl float32

func (b Girl) laugh() {
	fmt.Println("kaka~")
}

또 다음과 같은 interface가 있다고 치자구요.

type Laughter interface {
	laugh()
}

type Fighter interface {
	fight()
}

이제 main 함수에서 Boy와 Girl 타입에 대한 객체를 정의할껀데요. 이 2개의 객체 변수가 Laughter, Fighter 인터페이스를 충족하는지의 여부를 검사하는 코드는 아래와 같습니다.

func main() {
	var b Boy
	var g Girl

	if _, ok := interface{}(b).(Laughter); ok {
		fmt.Println("Boy is laughter.")
	} else {
		fmt.Println("Boy is not laughter.")
	}

	if _, ok := interface{}(g).(Fighter); ok {
		fmt.Println("Girl is fighter.")
	} else {
		fmt.Println("Girl is not fighter.")
	}
}

그 결과는 예상하는 것처럼 아래와 같습니다.

Boy is laughter.
Girl is not fighter.