2021년 9월 26일 일요일

Visual Studio 2019+ D(서브) 드라이브 설치

Visual Studio 2019 버전을 메인 드라이브인 C 드라이브가 아닌 다른 드라이브에 설치하는 방법에 대해 정리해 본다.


SSD 128 GB 정도의 작은 저장 장치를 메인 드라이브로 사용하는 경우 용량 부족으로 Visual Studio 2019 설치가 어려운 경우가 있는데 윈도우 시스템의 Junction(리눅스 시스템의 Symbolic Link) 기능을 이용해 일부 설치 용량을 서브 드라이브에 할당시킬 수 있다.


어느 정도의 공간 절약이 되냐면 Professional 버전 기준 .NET 데스크탑 개발 환경과 C++ 데스크탑 개발 환경을 설치할 때 12GB 가량 공간이 필요한데 Junction을 이용하면 4GB 정도 공간 절약이 가능하다.


원문 링크 : https://eventhorizon.tistory.com/110


방법>

1. 관리자 권한으로 cmd.exe를 실행한다.

2. 실제 설치가 이루어질 디렉토리를 D 드라이브에 생성한다.

3. 링크를 배치할 디렉토리를 C 드라이브에 생성한다.

4. mklink 명령어를 이용해 링크를 생성한다.

5. Visual Studio 설치를 진행한다.


ex) Professional 기본 설치 경로를 이용하는 경우 예시. 2단계 메인 드라이브에 디렉터리를 생성할 때 'Professional' 디렉토리는 제외해서 생성해야 한다.

1. mkdir -p "D:\Program Files (x86)\Microsoft Visual Studio\2019\Professional"

2. mkdir -p "C:\Program Files (x86)\Microsoft Visual Studio\2019"

3. mklink /j Professional "D:\Program Files (x86)\Microsoft Visual Studio\2019\Professional"




2021년 1월 26일 화요일

[Protocol Buffers] optimize_for 옵션

프로토콜 버퍼 컴파일러(protoc) 옵션으로 사용 목적에 따라 SPEED, CODE_SIZE, 또는 LITE_RUNTIME 값을 지정할 수 있다.


기본 값은 SPEED이다.


• SPEED (기본) : 기본 값인 만큼 프로토콜 버퍼의 모든 기능(Descriptor, Reflection)이 포함되며 최적화된 코드를 생성해 준다.


• CODE_SIZE : SPEED 옵션 대비 작은 코드 사이즈를 갖는 결과 파일을 만들어 주지만 SPEED 보다 동작 속도가 느려진다. 매우 많은 수의 .proto 파일을 포함하고(메시지 개수에 코드 사이즈가 비례하므로) 있거나 속도가 중요하지 않은 앱에서 유용한 옵션이다.


• LITE_RUNTIME : 'lite' 런타임 라이브러리에만 의존하는 클래스를 생성한다. (libprotobuf 대신 libprotobuf-lite) 전체 라이브러리보다 10배 작은 라이브러리로 동작이 가능하기 때문에 휴대폰과 같이 제한된 플랫폼에서 실행되는 경우 유용하다. 생성된 클래스는 Message 대신 MessageLite 인터페이스를 구현하며 이 옵션으로 컴파일 하는 경우 Descriptor, Reflection 등의 기능은 제외된다.


* 동일한 proto 파일을 여러 번 로드할 때 Descriptor로 부터 에러가 발생하는 경우가 있는데 이러한 경우엔 Descriptor 기능이 제외된 LITE_RUNTIME 옵션을 사용하는 것을 고려해볼 수 있다.

https://github.com/protocolbuffers/protobuf/issues/4126


일반적인 타겟 환경을 가진 프로그램이라면 기본 값을 그대로 쓰면 될 것 같고, 바이너리 사이즈가 중요한 프로그램이라면 CODE_SIZE, LITE_RUNTIME 등의 옵션을 고려해 볼만 한 것 같다. 사실 protoc에 의해 생성된 클래스를 그대로 사용하는 것이 일반적이라 Descriptor 같은 기능은 고급 사용자가 아니면 잘 쓰이지 않는다.


2021년 1월 11일 월요일

[Protocol Buffers] Base 128 Varints

프로토콜 버퍼의 인코딩 방식을 이해하려면 우선 Varint를 이해해야 한다. Varint는 하나 이상의 바이트를 사용해 정수를 직렬화 하는 방법으로 숫자가 작을수록 적은 바이트 수를 차지하게 된다. (아주 큰 숫자가 아니면 데이터 크기가 절약된다.)


Varint에서 마지막 바이트를 제외한 각 바이트의 최상위 비트(msb)는 1로 하기로 약속되어 있다. 이는 앞으로 올 바이트가 더 있음을 나타내기 위함이다. 

반대로 msb가 0이라면 Varint의 끝을 의미하게 된다. 따라서 1바이트를 차지하는 Varint로 표현할 수 있는 가장 큰 숫자는 127(0111 1111)이 된다. 또 하나의 룰로 Varint는 최하위 그룹을 먼저 위치시키는 방식을 택한다. (least significant group first).


표현 예시.

웹 페이지 설명에 나온 것처럼 숫자 1은 1바이트로 표현이 가능하므로 msb는 0이 되고 표현은 '0000 0001'이 된다.


그렇다면 숫자 300은 어떻게 표현될까? 앞서 언급된 것처럼 숫자 300은 하나의 바이트로 표현이 불가능 하므로 첫 바이트의 msb는 1로 셋 되어야 한다.

결과적으로 숫자 300은 아래와 같이 표현된다.


 1010 1100 0000 0010


여기서 msb를 떼면 010 1100 000 0010이 되는데, 앞서 적혀있는 대로 최하위 그룹이 먼저 위치하게 되므로 우리가 이해하는 숫자로 인식하기 위해선 7비트 단위 그룹의 위치를 서로 바꾸어 주어야 한다.


따라서 010 1100 000 0010은, 000 0010 010 1100 되어야 하고, 의미 없는 비트를 버린 뒤 두 그룹을 연결하면

→ 100101100 = 300 (256 + 32 + 8 + 4)이 된다.


https://developers.google.com/protocol-buffers/docs/encoding#varints


2020년 8월 12일 수요일

matplotlib 한글 깨지지 않게..

rc를 임포트한 다음에 한글이 지원되는 폰트의 이름을 지정해 주면 된다.
한글 윈도우 사용자라면 malgun.ttf는 있을거란 가정이 깔린다.

import matplotlib.pyplot as plt
from matplotlib import font_manager, rc

font_name = font_manager.FontProperties(fname="C:/Windows/Fonts/malgun.ttf").get_name()
rc('font', family=font_name)

x = list(range(1,11))
y = [a * 2 for a in range(0, 10)]

l = plt.plot(x, y, 'ro', label='빨강 닷')
plt.setp(l, markersize=4)
#plt.setp(l, markerfacecolor='C0')
plt.xlabel('X-축')
plt.ylabel('Y-축')
plt.title('차트 제목')
plt.legend(loc='best')
# plt.savefig('fig.pdf') # to pdf
plt.show()


https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.rc.html


log4jdbc-remix 사용법

https://code.google.com/archive/p/log4jdbc-remix/


프로젝트는 2013년 11월 중단된 상태고, 앞으론 log4jdbc-log4j2가 log4jdbc-remix(이건 2012년 4월에 시작된 프로젝트)를 대체한다고 한다. 


log4jdbc-remix의 주 기능은 쿼리문과 쿼리 결과를 보기 좋게 로그로 기록해 주는 것이다. 데이터베이스에 요청한 쿼리문이 의도와 맞게 작성되었는지 확인하는 용도로 활용할 때 좋다. (콘솔에 찍어보는 용도)


이건 Java 6 이상 버전에서 사용 가능하고, 제공되는 Proxy에서 기존에 정의해둔 DataSource를 참조하는 설정 방식을 따르기 때문에 사용하기 편리하다.


안정화 릴리즈 버전은 0.2.7이고, maven 기준 다음과 같이 끌어다 쓸 수 있다.

<dependency>

    <groupId>org.lazyluke</groupId>

    <artifactId>log4jdbc-remix</artifactId>

    <version>0.2.7</version>

</dependency>


log4j.xml엔 jdbc.sqlonly, jdbc.resultset 이름으로 로거 설정을 등록해주면 된다.

jdbc.sqlonly는 쿼리문을 기록하는 용도이고, jdbc.resultset은 쿼리 결과를 기록하는 용도이다.


프록시 빈 등록은 인터넷에 많이 돌아다니는 걸 그대로 쓰면 된다.

<bean id="dataSource" class="net.sf.log4jdbc.Log4jdbcProxyDataSource">

        <constructor-arg ref="dataSourceSpied" />

        <property name="logFormatter">

            <bean class="net.sf.log4jdbc.tools.Log4JdbcCustomFormatter">

                <property name="loggingType" value="MULTI_LINE" />

                <property name="sqlPrefix" value="SQL         :  "/>

            </bean>

        </property>

 </bean>




2020년 8월 10일 월요일

[펌] 비트겐슈타인이 남긴 명언

 

1889. 4. 26 빈~ 1951. 4. 29 잉글랜드 케임브리지셔 케임브리지. 오스트리아 태생 영국의 철학자. 1925~50년 영국 철학계에서 가장 영향력 있는 철학자 중 한 사람이었으며, 논리학 이론과 언어철학에 관한 독창적이며 중요한 철학적 사유체계를 제시했다.


1. 쓸모없는 문제에 관여하지 마라.

2. 말할 수 없는 것에 관해서는 침묵해야 한다.

3. 언어는 만물의 척도다.

4. 생각도 일종의 언어이다.

5. 말에는 음악이 깃들어 있다.

6. 내 언어의 한계는 내 세계의 한계를 의미한다.

7. 우리는 남에게 자신의 속마음을 감추고 싶어한다. 인간의 마음이란 아름답게만 간직되는 것은 아니기 때문이다.

8. 두려움이 아니라, 두려움의 극복이 칭찬받을만한 것이고, 인생을 보람차게 만든다.

9. 마음속 용기야말로 처음에는 겨자씨처럼 작아도 점점 성장해서 거목이 되는 것이다.

10. 어떤 돌이 전혀 움직이지 않고, 도저히 손을 쓸 방도가 없다면 먼저 주변의 돌부터 움직여라.

11. 문제를 해결하는 힘은 새로운 정보를 얻는데서 오는 것이 아니라, 이미 오래전부터 알고 있던 것을 체계적으로 정리하는데서 온다.

12. 철학자란 건강한 인식을 얻기 위해서 자기안에 박혀있는 다양한 사고의 오류를 고쳐야 하는 사람이다.

13. 반대되는 결론도 항상 함께 생각하라.

14. 오늘날 우리의 교육은 고뇌하고 인내하는 능력을 누르는 방향으로 흐르고 있다.

15. 생활이 자꾸만 변화하는 것은 인생에 있어서 가장 기본적인 일이다. 물론, 그것은 습관에 있어서도 마찬가지다.

16. 나는 왜 우리가 여기에 있는지 그 이유를 알지 못한다. 그러나, 나는 우리가 단지 즐기기 위해서 여기에 있는 것은 아니라는 그 사실만큼은 확신한다.

17. 자신과 아무런 상관이 없는 문제에 자신을 끌어들이지 않는 것은 철학자의 주요한 기술중 하나이다.

18. 자아성찰은 내 삶의 새로운 한 부분이어야 한다.

19. 의심은 믿음 이후에 온다.

20. 확실하다는 말로써 우리는 완전한 확신, 의심의 부재를 나타내며, 또한 그것으로 다른 사람들을 설득시키고자 한다. 하지만, 우리의 그 믿음은 주관적 확실성임을 알아야한다.

21. 인간의 몸은 인간의 정신을 표현하는 가장 훌륭한 그림이다.


22. 너무 많이 아는 사람이 거짓말을 하지 않기란 어렵다.

23. 인생이 견딜 수 없게 되었을때, 우리는 상황이 변화할 것을 기대한다. 그러나, 가장 중요하고 가장 효과적인 변화, 즉 자기자신의 태도를 바꿔야한다는 인식에는 거의 생각이 미치지 못한다.

24. 사물의 가장 중요한 측면은 그것이 너무나도 단순하고 친숙한 것이기 때문에, 우리의 눈길을 끌지 못한다. 따라서, 가장 기본적으로 탐구해야 하는 것은 그냥 스쳐가는 것 중에 있다.

25. 나는 구두점을 많이 써서 읽는 속도를 늦춰보려고 하는 편이다. 내가 쓴 글이 천천히 읽혀지기를 희망하기 때문이다. 나 자신이 읽는 것처럼 ...

26. 철학적 탐구는 인간생활에 보탬이 되는 쪽으로 국한되어야 한다.


2020년 7월 29일 수요일

포카 요케 (poka-yoke)

품질 관리의 측면에서 실수를 방지하도록 행동을 제한하거나 정확한 동작을 수행하게끔 하도록 강제하는 여러 가지 제한점을 만들어 실패를 방지하는 방법을 말하는 용어. 토요타의 시게오 신고에 의해 처음으로 고안됐으며, 실수를 피하다라는 뜻의 일본어에서 왔다.
... 인지 심리학 및 인간의 컴퓨터 상호작용 분야에서도 이를 이용하면 여러 가지 실수를 방지하는 디자인 원리의 하나로 받아들여져서 이용하고 있다.
[위키피디어]

생활에서의 포카 요케 예
- 자동차 기어가 "P"에 있지 않으면 시동이 걸리지 않도록 함.
- USB 장치를 꼽을 때 뒤집어서 꼽으면 작동하지 않음.
- 문이 닫히기 전에 전자 레인지가 작동하지 않음.

이 개념을 제안한 사람은 토요타 생산 시스템의 개척자 중 한 명인 시게오 신고로 '제로 결함'이라는 아이디어를 제안한 품질 전문가였다고 한다.

실수가 발생하지 않도록 끊임없이 노력한다는 철학이 포함된다. 최종 제품의 품질이 올라가려면 연결된 모든 프로세스에서 일정 수준 이상의 품질이 제공되어야 한다. 따라서 결함이 후속 프로세스로 이어지는 것을 방지해야 한다. (완제품 상태에서 결함이 발견되는 것이 가장 나쁜 케이스)

실수 방지 목표를 달성하는데 도움이 되는 특징은 다음과 같다.
- 단순함 : 솔루션이 복잡하지 않고 오류 발생 문제를 명확히 해결해줄 수 있어야 한다.
- 자동화 : 사람의 추가 개입이 없으면 좋다.
- 즉각적인 피드백 : 조건이 사양을 벗어난 경우 즉시 피드백을 해주면 좋다.

-
아예 실수를 할 수 없게끔 하면 사용자가 제품이나 프로세스에 대해 생각할 필요가 없을 것이다.
또는 프로세스를 벗어나는 경우 피드백을 줘서 프로세스 안에서만 행동이 있게끔 유도할 수 있다. 
(정해진 순서 또는 경우의 수 내에서만 행동을 제한하는 것.)