2018년 10월 25일 목요일

한글 환경에서 자주 접하는 인코딩 정리. (UTF-8, EUC-KR, CP949)

대부분의 출처는 나무 위키. 나무 위키는 볼수록 놀랍다.
https://namu.wiki/w/%EC%9C%A0%EB%8B%88%EC%BD%94%EB%93%9C

ASCII: American Standard Code for Information Interchange. 미국 정보 교환 표준 부호. 미국 산업 표준화 단체인 ANSI에서 표준화한 7비트 부호체계. 한글자당 1바이트를 할당하는데 영문 키보드로 입력할 수 있는 모든 기호들이 할당되어 있다. 2바이트 이상의 코드를 표현할 수 없기 때문에 국제표준의 위상은 유니코드로 넘어갔다. 참고로 초기엔 1바이트 중 7비트만 사용했는데 맨 앞 비트는 통신 에러 검출을 위한 Parity Bit로 쓰였다고 한다. 8비트 버전의 확장형 ASCII 코드도 있다. ASCII는 UTF-8과 호환되지만 UTF-16과는 호환되지 않는다.

Unicode: 전 세계의 모든 문자를 다루도록 설계된 표준 문자 전산 처리 방식. Unicode는 문자를 숫자로 매핑하는 것(예를 들어 A는 숫자 65)에 대한 개념이고 Unicode 인코딩으로 UTF-8, UTF-16, UTF-32가 있다. 일반적인 상황에선 Unicode를 UTF-8로 이해해도 무리가 없다. UTF-32의 경우 낭비가 심해 잘 쓰지 않지만 가변 길이를 고려하지 않아도 된다는 장점 또한 존재해 프로그램 내부적으로 사용하는 경우도 있다고 한다.

UTF-8: 가장 많이 쓰이는 가변 길이 유니코드 인코딩 방식. CP65001. 하나의 글자는 1~4 바이트 중 하나로 인코딩 되고, 1바이트 영역은 ASCII 코드와 하위 호환성을 갖는다. 재미있는게 한글의 경우 주로 3바이트 구간에 존재해서 한글로 작성된 문서의 경우 EUC-KR이나 UTF-16으로 저장한 것 보다 UTF-8로 저장했을 때 파일의 크기가 더 커진다.
MS 계열 프레임워크에서 C/C++등을 이용해 비 유니코드의 멀티바이트 캐릭터를 UTF-8 형식으로 변환하기 위해서는 와이드바이트 형식의 완전 2바이트 유니코드로 변환한 다음 다시 UTF-8 플래그를 주어 멀티바이트 형식으로 다시 변환하는 과정이 필요하다.

ANSI: 일반적으로 MS-DOS의 기본 인코딩인 OEM-US 내지 영문 Windows의 기본 인코딩인 Windows-1252를 지칭. 메모장에서 인코딩을 지정하지 않고 저장한 경우 'ANSI'라고 표시되는데 이는 잘못된 표기임. 실제 인코딩은 System Locale을 따라가므로 한글 Windows에선 CP949가 된다.

EUC-KR: 완성형 한글 인코딩 방식 중 하나. 현재 산업 표준이다. 시작은 '가', 끝은 '힝'. 지원하는 한글 글자 수는 2,350자로 현대에 사용되는 한글 11,172자에 비해 부족하다. 나름 빈도를 조사해 2,350자를 선정했다고 하지만 역부족.

CP949: 통합 완성형 (확장 완성형). 한국어판 Windows의 기본 코드 페이지로 EUC-KR의 확장이다. EUC-KR이 지원하지 않던 8000여자를 지원한다. 마이크로소프트가 개발했기 때문에 MS949, Windows-949 등으로 불리기도 한다.

* GCC 같은 비 MS 진영 컴파일러를 이용해 C/C++ 등의 네이티브 프로그래밍 언어를 갖고 UTF-8로 한글 출력을 하면 한글이 깨지는 현상이 있다. 이럴 땐 소스 코드 자체는 UTF-8로 하되, wchar_t 같은 와이드바이트 자료형을 사용해야 한다.

* Nodepad++의 경우 EUC-KR, CP949를 구분하는데 CP949로 작성된 문서를 Notepad++로 열면 시스템 기본 인코딩(ANSI)로 읽히는 경우가 흔해, 한글 버전이 아닌 다른 언어 윈도우에서는 글자가 깨진다고 함.

* BOM : Byte Order Mark. 문서의 처음에 눈에 보이지 않는 특정 바이트를 넣어 문서가 어떤 Endian, 인코딩 방식을 사용하고 있는지 알려주기 위한 장치다. 상황에 따라 이게 오히려 문제를 일으키기도 한다. 유닉스/리눅스 계열에서는 쓰지 않는 것이 관례. 웹 프로그래밍에서도 사용하지 않는 것이 좋다.
 . UTF-8 >> EE BB BF (UTF-8 Signature, 단지 UTF-8로 인코딩되었다는 사실을 알리는 사인.)
 . UTF-16 Big Endian >> FE FF
 . UTF-16 Little Endian >> FF FE
 . UTF-32 Big Endian >> 00 00 FE FF
 . UTF-32 Little ENdian >> FF FE 00 00

[파이썬과 인코딩]
https://datascienceschool.net/view-notebook/250c1869eab54157827adf54c5e9f064/

Kafka 간단 개념 정리.

참고로 Kafka 안써봄.. ㅠㅠ

카프카는 1)영속적, 2)분산, 3)분할, 4)복제되는 대량의 데이터를 수집하기 위한 메시징 시스템이다. 카프카는 데이터 소스와 데이터 처리기 사이에서 버퍼 역할을 해주는데 이는 스트림 처리에서 꼭 필요한 요소다. 참고로 링크드인에서 데이터 흐름을 한곳으로 모으기 위해 만들었다고 한다. 분산 시스템이기 때문에 한 두개 장비가 망가져도 잘 동작하며 Queue를 기본으로 하는 메시징 시스템이기 때문에 데이터의 순서를 보장해준다. 카프카는 프로듀서, 컨슈머, 브로커로 구성된다. 프로듀서는 데이터를 만들어 넣는 역할, 컨슈머는 데이터를 꺼내 쓰는 역할, 그리고 브로커는 프로듀서와 컨슈머의 메시지를 관리하는 클러스터 서버의 역할을 수행한다. (DDS와 유사한 형태의 Publish/Subscribe 모델.) 분산 코디네이터로는 주키퍼를 쓴다.

카프카는 높은 성능, 다양한 언어를 지원하기 위해 클라이언트와 서버 간 통신으로 TCP 프로토콜을 이용하며 카프카 브로커는 FIFO 형태의 토픽이라는 카테고리를 가지고 있다. 토픽은 Queue의 구조와 같다.. 각 메시지는 자신의 고유한 식별자인 인덱스를 가지고 있는데, 카프카에서는 이를 오프셋이라 한다. 각각의 컨슈머는 어디까지 읽었냐에 대한 오프셋을 관리하게 된다. 오프셋 관리만 잘하면 장애로 인해 예상치 못하게 중단되거나 운영 상의 이유로 언제든지 중단하여도, 안심하고 장애 처리나 업그레이드 같은 작업을 하고 재시작할 수 있다. 단, 중단된 시간이 길어지면, Kafka에서 버퍼링하며 저장할 수 있는 데이터 크기를 넘어설 수 있으므로 주의해야 한다. (근데 오프셋 관리가 어렵다고 함.)

기본적으로 토픽은 1개 이상의 파티션(물리적으로 분할된 Queue)을 가지고, 하나의 브로커나 다수의 브로커에 분산 배치될 수 있다. 토픽을 다수의 파티션에 나누어 여러 브로커에 분산 배치함으로 메시지 전송에 따른 부하를 분산시키는 구조다. 카프카는 영속성을 제공하기 위해 파일 시스템에 메시지를 저장한다. 데이터를 파일에 쓰면서도 메모리 대비 성능을 잃지 않는 것이 특징이다. OS 페이지 캐싱을 통해 read()에 의한 블락 없이 직접 매핑된 주 메모리를 참조하여 파일에 데이터를 기록하면서도 빠른 성능을 보장한다. 또한 Zero Copy 기법을 채택한 Java nio의 FileChannel.transferTo()를 통해 메모리의 데이터를 커널 레벨에서 소켓으로 바로 넘겨 버리는 방식으로 성능을 높이고 있다.

* OS 페이지 캐싱
주 메모리에 가능한 많은 파일을 미리 캐싱해서 실제 요청이 왔을 때 파일 Read 시간을 최소화 하는 기법.

결과적으로 메모리 사용을 최소화하는 구조이므로 GC에 의한 성능 감소를 예방한다. (자바 오브젝트의 메모리 오버헤드는 매우 높고, 종종 저장된 데이터의 크기보다 더 크게 부풀려진다. 자바 GC는 힙 안의 데이터가 증가할수록 점점 더 다루기 어렵고 느려지는 특성이 있다.)

각 파티션은 설정한 서버의 숫자만큼 복제되고, 각 파티션은 카프카 클러스터에 분산되 저장된다. 파티션은 Leader 역할을 하는 하나의 서버와, 0개 이상의 Follower 서버를 갖는데 Follower가 Leader를 복제하는 동안, Leader는 파티션을 위한 모든 읽기와 쓰기 요청을 처리한다. 복제는 파티션 단위로 처리되는데 복제 계수가 3이면 1개의 Leader, 2개의 Follower 구성을 뜻한다. 복제 계수는 브로커 개수 이상으로 설정할 수 없다. (한 서버에 동일한 파일을 저장할 필요가 없기 때문.) 사용자의 모든 요청은 리더 파티션이 담당하며, 카프카의 복제는 가용성(Availability)을 높일 뿐, 성능 향상에 영향을 주진 않는다. 카프카는 프로듀서가 특정 토픽 파티션에 전송한 데이터의 순서를 보장한다. 그리고 컨슈머는 저장된 순서대로 메시지를 처리하게 된다. 카프카는 메시지의 순서와 메시지가 단한번 소비되는 것을 보장하지만 처리 순서는 하나의 파티션에 대해서만 보장한다. 여러 개의 파티션으로 분산된 데이터의 순서는 보장하지 않는다는 뜻이다. 게다가 비동기 방식이라 클러스터 구성이 복잡해지면 골때리는 경우가 제법 생기는 듯 하다.

* 주키퍼
주키퍼 = 분산 코디네이터. 분산 코디네이터라고 하면 뭔가 어렵게 다가온다. 클러스터 구성원 간의 데이터 공유를 위한 데이터 저장 기법(기술)이라 생각하면 조금 편해지려나.. 데이터를 디렉터리 구조로 저장한다. 데이터를 저장할 때 해당 세션이 유효한 동안 데이터가 저장되는 Ephemeral Node라는 것이 존재하고, 데이터를 저장하는 순서에 따라 자동으로 일련번호가 붙는 Sequence Node라는 것이 존재한다. 이러한 기능이 주키퍼의 전부. 이러한 기능을 가지고 입맛에 맞게 확장해서 사용하면 된다.
(입맛? 서버 투입/제거 시에 대한 이벤트 처리, 분산 환경에서 서버들 간의 정보 공유, 서버 모니터링, 분산 락 처리, 장애 상황 판단, 분산 시스템에서 리더 선출, 클러스터 멤버십 관리를 통한 데이터 변경 통지..)

주키퍼는 일반적으로 3대 이상을 사용하며 홀수로 구성한다. 서버 간의 데이터 불일치가 발생하면 보정이 필요한데 이떄 과반수의 룰을 적용하기 때문이다. 주키퍼 서버는 Leader와 Follower로 구성되어 있다. 서버들끼리 자동으로 Leader를 선정하며 모든 데이터 저장을 주도한다. 클라이언트가 Follower 서버로 데이터 저장을 시도한다면
Client > Server(Follower) > Server(Leader) > 나머지 Server(Follower) 순으로 데이터를 전달한다. 저장을 마치면 클라이언트에게 성공/실패를 동기 방식으로 알려준다. 즉 모든 주키퍼 서버는 동일한 데이터를 가지고 있고, 클라이언트가 어떤 서버에 연결되어 데이터를 가져가더라도 동일한 데이터를 가져가게 된다. 주키퍼에 잦은 변경이 일어나는 애플리케이션 성격의 데이터를 저장하는 것을 옳지 않으며 Read:Write 비율이 10:1 이상이 권장된다.

Apache ZooKeeper is an effort to develop and maintain an open-source server which enables highly reliable distributed coordination. // Zookeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services. 

읽어볼만한 국문 링크.
1] http://www.chidoo.me/index.php/2016/11/06/building-a-messaging-system-with-kafka/
2] http://readme.skplanet.com/?p=12465

2018년 10월 13일 토요일

hilite.me - 코드 시각화.

구글 블로거에 code 태그는 따로 처리 안하고 있었는데 가독성이 너무 안좋은것 같아서 몇군데 찾아보다가 hilite.me라는 사이트를 발견했다. 시간 오래 안걸리고 사이트 이름 잊어먹을 일 없으니 종종 이용하기로.
(결과물은 div랑 pre로 뽑히는게 함정.)



스타일은 vs에 css 값은 요정도가 깔끔한듯.
background-color: #f8f9fa;
border: 1px solid #eaecf0;
padding: 10px;
white-space: pre-wrap;

print 'hello world!'
print 'hello world!'

근데 별로네 ㅋㅋㅋ

가벼운 Django 사용 후기.

정말 단기간에 가볍게 사용해본거라 잘 모르지만 정리는 해두는게 나으므로.

#
2년전이던가. 사내에서 간단하게 쓸 웹 서비스를 만들기 위해 여러가지 프레임워크를 살펴보다가 Admin 기능 하나에 끌려 파이썬의 Django를 사용해보게 되었다.

최근 흐름은 모르겠지만 그래도 아직까진 Django와 Flask가 파이썬에서 가장 인기있는 웹프레임워크인 것으로 알고 있다. Django가 풀스택 프레임워크에 가깝다면 Flask는 개발자가 상황에 맞게 필요한 라이브러리를 조합해 사용하는 경량 프레임워크란 차이가 있다.

Django와 Flask 둘 중에 꼭 뭐가 배우기 쉽고 뭐가 좋다고 말하긴 어려운 것 같다. 특정 프레임워크의 선택은 만드는 목적과 달성하려는 수준, 그리고 개인과 팀의 취향에 따라 갈리는 부분이기 때문이다.

어쨌든 난 Django의 Admin 기능 하나를 보고 Django를 선택했었다. 물론 엄청 괜찮은 수준의 문서 지원도 한 몫 했지만 지금 다시 살펴봐도 Django의 Admin 기능은 쿨하다. models.py와 admin.py만 만져주면 뚝딱 생기는 Admin 페이지는 많은 수고를 줄여준다. 빌트-인 미들웨어 지원도 좋았고, 데이터베이스나 웹서버에 대한 지식 없이도 쉽게 서비스를 띄울 수 있는 점도 큰 장점이다.

Django는 웹프레임워크가 제공했으면 하는 거의 모든 기능을 기본적으로 지원해준다. 요청, 응답에 대한 다양한 변환, 참조, 그리고 렌더링 함수를 제공하고 있고, 다양한 빌트-인 미들웨어 제공은 딱히 창의적일 필요없는 지루한 작업을 줄여준다. (물론 상용으로 확장되면 꽤나 어렵고 까다로운 문제점들이 있다곤 하나 그건 다른 프레임워크에서도 마찬가지지 않나 싶다.)

# 설치
pip install django=={version}

# 버전 확인
console;
python -m django --version
code; 
import django
print(django.VERSION)
print(django.get_version())

# 프로젝트 생성
django-admin startproject {project_name}
L manage.py - Django 프로젝트와 상호작용 하는 커맨드라인 유틸리티. (python manage.py shell 과 같은..)
L {project_name}/settings.py - Django 프로젝트의 환경 구성을 지정.
L {project_name}/urls.py - 라우팅을 위한 프로젝트의 URL 선언. path()에 대해 알아야 한다. 정규 표현식이나 파라미터를 받아 처리할 수 있고, 처리 함수(view 함수), 사전형 인수(kwargs), 그리고 프로젝트에서 참조가능한 이름(name)을 지정할 수 있다.
L {project_name}/wsgi.py - WSGI 호환 웹 서버의 진입점.

* WSGI?
Web Server Gateway Interface. WSGI는 정적인 컨텐츠를 처리하는 웹서버와 파이썬 웹애플리케이션 사이의 인터페이스를 위한 파이썬 프레임워크다. 이에 대한 구현체인 WSGI 미들웨어로는 mod_wsgi, uwsgi, gunicorn, twisted.web, tornado 등이 있다. 웹서버의 관점에선 애플리케이션이고, 웹애플리케이션의 관점에서는 서버로 동작하게 되는 셈인데 애플리케이션 컨테이너의 역할을 수행한다고 보면 된다. WSGI 서버는 독립적인 웹서버로서의 기능이 약하고 DDOS 공격에 취약하므로 Nginx나 Apache 같은 독립적인 웹 서버와 함꼐 사용하는 것이 권장된다.

# 앱 생성
python manage.py startapp {app_name}
L {app_name}/admin.py
L {app_name}/apps.py
L {app_name}/migrations/
L {app_name}/models.py
L {app_name}/tests.py
L {app_name}/views.py - MVC의 V, View가 아님에 유의하자. Django는 MTV (Model - Template - View) 패턴을 따르는데 views.py는 MVC C, Controller와 유사한 역할을 한다.

# 모델 변경과 적용
1. models.py에서 모델을 추가하거나 변경.
2. python manage.py makemigrations 명령을 통해 변경사항을 migration 파일로 기록하낟.
3. python manage.py migrate 명령을 통해 변경사항을 데이터베이스에 적용한다.
4. Admin에 노출시킬 필요가 있는 모델은 admin.py에 admin.site.regiter()로 등록해준다.

* makemigrations 명령어 : 모델에 대해 변경된 내역을 migration이라는 개념의 파일로 저장해준다. migration은 Django가 모델의 변경사항을 저장하는 방법으로 디스크상의 파일로 존재하게 된다.
* migrate 명령어 : settings.py 내 INSTALLED_APPS의 설정을 탐색하여 필요한 데이터베이스 테이블을 생성한다. 클래스 1개는 Table 1개로 생성되며 id (Primary Key)는 자동으로 생성되므로 신경쓰지 않아도 된다. (ORM에 대한 기본적인 개념을 알고 접근하면 좋다. 결국 Django-ORM이 지저분한 뒷작업을 다 해주는거다.)
https://docs.djangoproject.com/ko/2.1/intro/tutorial01/

# 관리자 생성
python manage.py createsuperuser # 관리자 사이트 접근 가능한 user 생성.
생성후 Admin 페이지에서 기본으로 보여지는 Groups, Users 내용은 INSTALLED_APPS에 선언된 django.contrib.auth 모듈이 제공하는 인증 기능이다.
관리자 페이지 편집에 대한 내용은 다음 링크를 참고해보자.
https://docs.djangoproject.com/ko/2.1/intro/tutorial07/

# settings.py
DEBUG; 디버그 모드 설정
INSTALLED_APPS; 설치된 앱 또는 본인이 만든 app 추가
MIDDLEWARE_CLASSES; request와 response 사이에서 동작하는 기능 레이어 지정
TEMPLATES; Django template 관련 설정과 실제 view 위치.
DATABASES; 데이터베이스 엔진의 연결 설정
STATIC_URL; 정적 파일의 URL(css, js, image, etc.)

# 기타
1. XSS, CSRF 등의 보안 이슈에 Django가 어떻게 대응하고 있는지 살펴볼 필요가 있다. (autoescape, safe // {% csrf_token %}
2. 템플릿 생성, 처리 관련 내용은 튜토리얼 문서를 천천히 읽어보는 것이 낫다.
https://docs.djangoproject.com/ko/2.1/intro/tutorial03/
3. 배포 관련해서는 다음 링크를,
http://pythonstudy.xyz/python/article/316-Site-Deployment-Nginx
4. 한국어로 학습할 수 있는 방법은, 공식 문서나 장고-걸스에서 제공하는 문서의 질이 좋고, 위키독스 자습 페이지도 괜찮아 보인다.
https://wikidocs.net/6609
5. 책중에 Two Scoops of Django가 괜찮다 하여 구매해두었는데 잘 안읽히는 걸 보면 입문서는 아닌듯 하다.



2018년 10월 10일 수요일

WPF - telerik 차트 다루기

WPF GUI 툴킷으로 Telerik 제품을 사용하고 있다. (텔레릭으로 읽어야 하는지 떼레릭읽어야 하는지 아직도 궁금함.) 다양한 기능이 있는듯 하지만 아무래도 자주 쓰게되는 건 차트 컨트롤이다. Telerik의 차트는 제품 내부적으로 X,Y축을 두고 그리는 일반적인 형태의 RadCartesianChart와 방사형의 RadPolarChart로 큰 구분을 두고 있다. 방사형의 RadPolarChart는 아직 써보지 못했으나 RadCartesianChart를 표현하는 방식과 크게 다른 점은 없을거라 생각한다.

이 글은 RadCartesianChart에 대한 정리글인데 최근 차트 관련 컨트롤을 사용하게 될때마다 기억이 잘 안나서 자료 써칭하다가 허비하는 시간을 줄이기 위함이다. RadCartesianChart의 골격은 Axis를 정의하고, Series에 데이터 컬렉션을 지정해 그리는 방식으로 다른 라이브러리에서 제공하는 형태와 매우 유사하다.

Chart
 - Axes (Horizontal, Vertical)
 - Series
* 기타 Annotation, Grid 등이 있다.

Axis

Axis는 세로 축을 담당하는 VerticalAxis와 가로 축을 담당하는 HorizontalAxis가 있는데 세세한 표현을 위해 각 축이 갖는 속성을 잘 알아둘 필요가 있다. 속성을 잘못 지정하게될 경우 축의 특정 Label이 다른 Label을 덮어버리거나 축의 Step 값이 너무 크거나 세밀해서 데이터를 한 눈에 파악하기 어려운 경우가 생긴다. Axis엔 수치 값을 표시하는데 적합한 LinearAxis와 Category를 구분하는데 적합한 CategoricalAxis, 그리고 DateTimeAxis가 있다.

Axis의 주요 속성.
1. PlotMode (for CategoricalAxis, DateTimeAxis) : 데이터를 표시할 때 데이터의 Tick와 Label 표시 방식에 대한 것으로 기본값은 BetweenTicks이다. 그리고 OnTicks와 OnTicksPadded가 있다. (https://docs.telerik.com/devtools/wpf/controls/radchartview/axes/plotmode#plot-mode)
2. LabelInterval : Label이 표시되는 간격을 지정할 수 있다.
3. Minimum, Maximum, MajorStep (for LinearAxis) : 최소값, 최대값, 주-표시선 간격에 대한 설정. 값을 지정해주지 않아도 자동으로 계산되지만 지저분한 결과물이 나오기 마련이라 이 값들은 직접 지정해주는 것이 좋다.
4. LabelFitMode : Label이 서로 겹치지 않도록 Label 표시 방법을 지정할 수 있다. Label을 여러 행으로 표시하는 MultiLine과 Label을 회전해서 표시하는 Rotate가 있는데 MultiLine의 경우 차트를 지저분하게 만드므로 LabelInterval과 Rotate를 적절히 사용하는 방식이 나은 것 같다. (내부 알고리즘 방식으로 동작하는 SmartLabelsMode 속성도 확인해볼 필요가 있다. https://docs.telerik.com/devtools/wpf/controls/radchartview/axes/axis-smart-labels)


Series

실제 표현하려는 데이터 컬렉션이 담길 개체.
자주 쓰게되는 것은 아무래도 Line, Scatter Point, Scatter Line 시리즈. 주식 차트를 그리는데 쓰이는 CandleStick도 제공한다.
https://docs.telerik.com/devtools/wpf/controls/radchartview/series-and-axes


GridLine Annotation

차트 데이터 내부의 특이구간을 표시하거나 Limit 값을 표시하는 용도로 GridLine Annotation을 사용할 수 있다. Axis 방향과 값, 그리고 Stroke를 지정하는 방식이다. Annotation에 대한 Label도 붙일 수 있고, Annotation Label의 Definition 정의를 통해 Label 표시 위치 또한 설정할 수 있다.
<telerikChart:RadCartesianChart.Annotations>
<telerikChart:CartesianGridLineAnnotation Axis={Binding ElementName=#ChartYAxis}" Value="..." Label="..." DashArray="..."/>
http://docs.telerik.com/help/windows-8-xaml/chart-annotations-gridline-types.html
http://docs.telerik.com/help/windows-8-xaml/chart-annotations-labels.html


Grid

차트 Background의 X, Y 보조 표시선을 긋는 용도로 쓰인다.
<telerikChart:RadCartesianChart.Grid>
<telerikChart:CatesianChartGrid MajorLinesVisibility="XY"/>
</telerikChart:RadCartesianChart.Grid>
와 같이 해주면 무난하다.


No data to plot

차트에 정의한 Series에 담긴 데이터가 하나도 없으면 기본 값으로 No data to plot이 출력된다. 실제 쓰다보면 데이터가 나중에 바인딩 되는 경우가 잦은데 그럴 때마다 보이는 No data to plot 문구는 꽤나 거슬리는 부분이다. 다행히 이 문구는 새롭게 정의할 수 있다. 차트 속성 중 EmptyContent라는게 있는데 단순히 EmptyContent=""와 같이 빈 값으로 지정해주면 표시를 막을 수 있다. 빈 데이터 셋에 대해 출력되는 문구를 이미지로 대체한다던가 하는 작업이 필요한 경우엔 차트 하위 속성은 EmptyContentTemplate를 다시 정의하는 방법을 사용할 수도 있다.
https://docs.telerik.com/devtools/wpf/controls/radchartview/features/empty-content

2018년 10월 4일 목요일

[링크] 자바는 어디로 가고 있을까?

요즘엔 새로운 기술에 대한 내용보다 이런 글이 더 자극이 되는 것 같다.

https://medium.com/@jongdae.lim/%EC%9E%90%EB%B0%94-java-%EB%8A%94-%EC%96%B4%EB%94%94%EB%A1%9C-%EA%B0%80%EA%B3%A0-%EC%9E%88%EC%9D%84%EA%B9%8C-37dc915f00f1

[C#] Delegate, Func, Action

Delegate

Delegate는 C/C++의 함수 포인터와 유사하다.
* Caller -> Delegate (-> Callee)

이론적(?)으론 원하는 메서드를 안전하게 감싸는(캡슐화) 것이지만
주 활용 목적은 1) 콜백, 2) 메서드-체인 구성(멀티캐스트~이벤트), 3) '동작을 지정하는 틀'을 만드는 것에 있는 것 같다.

예}
string을 인수로 사용하고 void 반환 타입 메서드를 캡슐화 하고자 한다면 동일하게 string을 인수로 사용하고 void 반환 타입을 갖는 delegate를 선언해 주면 된다.

public static void DelegateMethod(string message) { ... }
public delegate string Del(int id);

Generic Delegate로도 선언할 수 있다.
public delegate void Del<T>(T message);

대리자의 형식은 대리자의 이름으로 정의된다.
위 예시에서 Delegate의 이름이 'Del'이므로 형식은 'Del'이 된다.
Del handler = DelegateMethod;
handler("hello world");

익명 메서드나 람다도 물론 허용한다.
{익명 메서드} Del handler = delegate(string message) { Console.WriteLine(message); };
 -> 익명 메서드는 이름이 없는 메서드기 때문에 이를 호출하기 위해서 delegate 키워드가 필요한 것이다.
{람다} Del handler = (string message) => Console.WriteLine(message);

Delegate는 객체이기 때문에 매개 변수로 전달하거나 속성에 할당할 수 있다.
메서드의 매개 변수가 될 수 있는 점은 꽤나 유용하다. (ex. 비동기 콜백)

Delegate의 또 하나의 큰 특징으로 둘 이상의 메서드를 호출할 수 있다.
이러한 호출을 멀티캐스트라고 한다.
Del d1 = Func1;
Del d2 = Func2;
Del d3 = Func3;
Del allMethodsDelegate = d1 + d2;
allMethodDelegate += d3;

allMethodDelegate("hello world"); // Func1 > Func2 > Func3 으로 호출된다.

멀티캐스트 대리자는 이벤트 처리에서 광범위하게 사용된다.


C#에서의 Delegate vs Event

Delegate는 자신이 속한 클래스 외부에서도 호출이 가능하지만,
Event는 자신이 속한 클래스 내부에서만 호출하도록 강제된다.

! 참고로 event는 단지 delegate 앞에 'event' 키워드만 붙이는 것으로 선언이 된다.
Del myDelegate; -> event Del myEvent;


Func, Action

Func와 ActionFunc와 Action은 미리 선언된 Delegate 변수로
Func는 반환값이 있고, Action은 반환값이 없는 차이가 있다.

Func 선언은 매개변수를 앞에 지정하고, 반환 값은 가장 뒤에 지정한다.
Func<int, float> func = (a) => a * 0.1f; // int형 매개변수를 1개 갖고, 반환값은 float 형.