글쓴이 보관물: 나루

나루에 대하여

클린 코드를 지향하는 개발자입니닷~*

Jenkins 외부 접속을 위한 방화벽 설정

Jenkins를 설치한 후 localhost로는 접속이 되는데, 외부에서 접속이 되지 않는 경우가 있는데, 방화벽에서 해당 젠킨스 서비스를 구동하는 포트를 java에 대해 인바운드 접근을 허용해 주어야 외부 머신에서 접속이 가능하다.

투자를 잘 하려면

뭐 엄청난 비법이 있나 싶겠지만,
맘 편안히 하는 게 제일 잘 하는 거다.

건강을 해쳐가며 잘 벌어봐야,
그동안 번 것을 치료하는데 다 쓰게 된다.

그러니, 투자를 잘 하고 싶다면,
가장 편안하게 투자할 수 있는
자신만의 방법을 찾으면 된다.

끝!

투자에 대한 관점

요즘 너 나 할 것 없이 모두들 투자를 하고 있다. 부동산, 주식, 채권, 선물, 해외선물, 코인 등 다양한 영역에 자산을 투입하고 결과를 기다린다. 그런데 신기한 것은 투자자의 80% 이상은 큰 수익을 보지 못한다. 거의 약 5% 정도의 투자자들만 수익을 보고 있다는 사실은 정말 슬픈 일이다. 개인들이 열심히 피땀흘려 모은 자산을 투자해서 날리는 일은 심리적으로 타격감이 상당하기 때문이다. 따라서 투자할 준비가 되지 않았다면 투자를 하지 않는 게 낫다. 그러면 최소한 손실을 보지 않을테니 말이다.

하지만 우리는 이미 인생을 살아가면서 금전적 투자 외에도 다양한 투자를 이미 하고 있다. 내 인생, 내 시간과 정성을 들이는 모든 일들은 투자라고 할 수 있다. 가족과의 관계, 친구와의 관계, 업무 역량, 건강 등 다양한 영역에 투자를 하고 있다. 건강 유지를 위해서 운동을 하고 식단을 조절하고, 업무 역량을 향상 시키기 위해서 추가적인 학습을 하기도 하고, 사람들과의 관계를 잘 유지하기 위해서 적당히 연락도 주고 받고 함께 만나서 밥과 차를 즐기기도 한다. 이 과정에서 일정량의 자본이 투입되기도 한다.

표준국어대사전에서는 ‘투자’를 “이익을 얻기 위하여 어떤 일이나 사업에 자본을 대거나 시간이나 정성을 쏟음.”이라고 표현하고 있다. 이 한 문장만으로도 투자가 무엇이며 무엇을 해야 하고, 무엇을 하면 안 되는지 분명히 알 수 있다.

우선 투자는 ‘이익을 얻기 위한’ 목적이 있는 행동이다. 따라서 이익을 얻을 수 있는 일에 투자를 하는 것이다. 앞서 금전적 투자 외에 인생에 대한 투자 행위를 말했다. 건강 유지를 위해서 투자했는데, 건강 유지에 실패한다면 실패한 투자다. 업무 역량을 증진시키려고 했는데 되려 역량이 망가졌다면, 실패한 투자다. 사람들과의 좋은 관계를 만들려고 했는데 오히려 관계가 발전하기는 커녕 퇴보한다면 실패한 투자다. 필자는 이런 것들을 모두 겪어봤다. 이 글을 읽는 분들도 이런 경험들이 다들 있을 것이라 믿어 의심치 않는다. 즉, 투자를 하게 되면 반드시 실패의 경험을 하게 된다는 것을 알 수 있다.

‘어떤 일’이나 ‘사업’이 망할 일이라고 생각되면 투자하지 말아야 한다. 망할 일이라고 생각되는 것에 투자하는 사람은 없다. 일이 잘 될 것이라고 희망을 가지고 투자를 한다. 하지만 투자하고 나면 망하는 게 문제인 거다. 그렇다면 내가 잘못 평가하고 예측한 탓이다. 누구를 탓할 수 없다. 즉, 투자를 하는 모든 책임은 나에게 있다.

투자에는 ‘시간’이 들어가거나 ‘정성을 쏟아’야 한다. 인간관계, 건강, 업무역량을 증진하기 위해서 다양한 시간을 들인다. 모든 것이 뚝딱 한 순간에 얻어지는 것은 없다. 최근에 필자는 피아노를 배우고 있다. 처음 배우는 것이다보니 모든 것이 서툴다. 그런데 시간을 들여서 연습을 하니 조금씩 나아지는 게 느껴진다. 즉, 투자를 하는 것에는 시간 및 정성 투입을 빼놓고 생각할 수 없다.

표준국어대사전에 있는 의미들만 몇 가지 살펴보았는데, 우리는 이미 다양한 투자를 경험하고 있다는 것을 알 수 있다. 이제 이런 의미들에서 투자의 원칙들 몇 가지만 얘기해 보려 한다.

투자에는 실패가 반드시 뒤따른다고 했다. 손실을 보기 위해 투자하는 사람은 없다. 그런데 투자를 하면 실패가 꼭 따라온다. 그렇다면, 어떻게 해야 성공적인 투자를 할 수 있겠는가. 실패를 할 때 작은 규모의 실패를 하고, 성공을 할 때 크게 성공하는 투자를 하면 된다. 여기에서 그 흔한 손익비 개념이 탄생한다.

결혼이라는 투자는 인생에서 꽤 무게감이 있는 투자다. 인생의 반려자와 함께 남은 인생을 살아가는 일이기 때문이다. 그런데 하필 폭력을 사용하는 배우자를 만났다고 가정하자. 결혼 전까지는 전혀 그럴 것 같지 않았던 상대가 어느 날 폭력을 사용하기 시작했다. 그렇다면 바로 손절해야 한다. 사람을 때리는 행동은 해서는 안 되는 일이기 때문이다. 그런데 여기에서 손절을 하지 못한다. 희망을 가져본다. 한 번 그런거지, 저렇게 싹싹 비는데 봐주면 다음부턴 그러지 않을 거라고 생각한다. 하지만 그러다가 두 번째 폭력을 경험하게 되고, 인생이 힘들어지고 고달파지게 된다. 빨리 이혼을 하고, 심리 상담이나 정신과치료를 통해 필요한 도움을 받고, 결혼을 하고 싶다면 좋은 배우자를 다시 만나고, 결혼을 하지 않을 거라면 혼자 사는 것이, 인생 전반으로 봤을 땐 성공적인 투자가 될 것이다. 실패한 결혼 생활 1년, 성공한 결혼/비혼 생활 50년이라면 성공한 것이라고 생각할 수 있겠다. 반대로 실패한 결혼 생활 51년이라면 그냥 실패한 결혼 생활로 마무리 되는 것이다.

자본을 투자하는 일도 마찬가지다. 잃을 때 적게 잃고 벌 때 크게 벌어야 하는데, 잃고 있으면서도 조금만 있으면 반등할 거야. 일시적인 하락일 거야. 이제 여기가 바닥일 거야라는 희망회로를 돌리는데 그건 자산 증식에 아무 도움이 되지 않는다. 앞서 폭력적인 배우자에 대한 손절에서 살짝 언급했듯이, 여기에서 손절 개념이 들어간다.

사실 투자에서 손절과 익절을 따로 이야기하는 경우들이 많이 있는데, 투자에서 모든 익절 또한 다 손절이다. 물론 수익금만 놓고 봤을 땐 먹었으면 익절이고, 손해를 봤으면 손절이라고 할 수 있겠지만, 투자과정은 심리적인 특성들 또한 반영되기 때문에 사실상 모두 손절이라 생각한다. 예를 들어, 1,000원에 산 주식이 2,000원까지 올랐다. 2,000원에 판다면 벌었으니 익절이기도 하지만, 더 올라갈 가능성을 포기하는 측면에서는 손절이기도 한 것이다. 수익 1,000원을 확정짓고, 2,000원을 벌 기회를 포기하는 것이기 때문이다. 또, 1,000원에 산 주식이 3,000원까지 올랐다가 다시 2,000원까지 내려왔을 때 매도로 수익을 확정짓는다고 하자. 금전적으로는 앞 사례와 똑같은 1,000원의 수익을 보는 것이지만, 심리적으로는 고점 대비 1,000원을 잃은 것이기도 하면서, 앞으로의 추가하락을 막는 것이다. 반대로 1,000원에 산 주식이 500원까지 내려갔다. 손실을 확정하고 매도한다면 금전적으로는 500원 손실을 확정하는 것이지만, 심리적으로는 200원까지 내려갈 가능성을 잘라내는 것이다. 그래서 모든 청산은 다 손절이다. 여기에서 리스크 관리의 필요성을 배우게 된다.

아무리 잘 벌어도 한 순간에 다 까먹으면 아무 의미가 없다. 100만원으로 100% 수익을 내면 200만원이 된다. 거기에서 50% 손실을 보면 다시 100만원이다. 이게 투자의 현실이다. 그래서 손실을 최대한 적게 보기 위해서 노력해야 한다. 손익비가 아주 뛰어나지 않는 이상 승률이 낮으면 심리적으로 버티기 힘들어진다. 매일 8번의 작은 실패와 2번의 매우 큰 수익으로 늘 하루를 수익으로 마감하는 전략이라면 해볼만 하겠지만, 매일 6번의 실패와 4번의 수익인데 수익과 손실이 들쑥날쑥이라면 투자하기 망설여진다.

투자는 심리적으로 편안하게 할 수 있어야 한다. 그러려면 꾸준히 할 수 있는 투자 방법을 선택해야 한다. 손실을 최소화하고 수익을 극대화할 수 있는 전략을 찾아야 하고, 그걸 매 순간 정한 방법대로 꾸준히 투자해야만 수익을 확정짓는 자리로 갈 수 있다. 업무의 현장에서도 심리적으로 편안할 때 성과가 가장 좋지 않은가. 마찬가지 원리다.

이 글을 읽으시는 분들의 투자가 모두 성공하기를 기원한다.

QEMU/KVM 호스트OS와 게스트OS 동일 네트워크에 연결하기 – 브릿지 네트워크 설정

호스트 OS는 Ubuntu 22.04, 그리고 Virtual Machine Manager를 이용해서 VM을 구동하였다.

그런데 네트워크 장치가 기본적으로 NAT로 설정되어 있었다.
그러면 호스트 OS에서 VM으로 접근할 수가 없다.
그럴 땐 macvtap을 이용하면 호스트 OS와 게스트 OS를 동일 네트워크로 연결할 수 있다.
하지만 macvtap을 이용하면 게스트 OS에서 호스트 OS에 엑세스 하지 못하는 문제가 생긴다.

결론은 Bridge 설정을 해야 한다.

  1. 브릿지 넷필터 비활성화
  2. 브릿지 추가
  3. QEMU/KVM에서 브릿지 선택

우선 브릿지 넷필터 비활성화가 필요하다. 다른 설정을 아무리 잘해도 이 문제 때문에 계속 네트워크 설정이 안 되는 문제를 겪었다. 모든 트래픽을 브릿지로 보내고 VM으로 보내려면 이 작업을 꼭 해야 한다. 아래의 내용을 /etc/sysctl.d/bridge-filter.conf로 저장한다.

net.bridge.bridge-nf-call-ip6tables=0
net.bridge.bridge-nf-call-iptables=0
net.bridge.bridge-nf-call-arptables=0

이제는 /etc/udev/rules.d/99-bridge-fileter.rules 파일에 아래와 같이 적어준다.

ACTION==”add”, SUBSYSTEM==”module”, KERNEL==”br_netfilter”, RUN+=”/sbin/sysctl -p /etc/sysctl.d/bridge-filter.conf”

재부팅 해주면 반영된다.

이제 브릿지를 추가해 줄 차례다. nm-connection-editor를 실행한다. 혹시나 GUI를 이용할 수 없는 경우에는 참고자료를 살펴보길 바란다.

  1. + 버튼을 누른 후 Connection Type을 Virtual의 Bridge로 선택한 후, Create를 눌러서 Bridge Connection을 추가한다.
  2. Connection Name을 bridge0, Interface name을 bridge0로 변경해 준다.(bridge0는 예시로 적은 것이다 희망하는 이름을 적어주면 된다.)
  3. bridged connections의 Add 버튼을 누른다.
  4. Connection Type에 Ethernet을 선택.
  5. Connection name에 eth-bridge0 입력.
  6. Device에서 LAN선이 꼽혀 있는 NIC 선택(예, enp8s0). 그리고 Save 클릭.
  7. IPv4 Settings에서 Method를 Manual로 변경한다.
  8. Addresses에 Add를 누른 후 브릿지의 IPv4를 설정해 준다. DNS Server도 설정해 준다.
  9. Save를 눌러서 저장한다.
  10. Bridge에 bridge0이 추가되었고, Ethernet에 eth-bridge0이 추가 되었다면 성공.
  11. terminal에서 nmcli con up eth-bridge0 해주면, 브릿징 완료.
  12. 세팅이 잘 됐는지 확인하고 싶으면, 첫째 nmcli con show해서 bridge0와 eth-bridge0이 올라가있고 enp8s0이 내려가 있는지 확인하면 된다. 그리고, ip a 해보면 공유기와 연결된 NIC에 master bridge0이 보일 것이며, IP는 bridge0에 잡혀 있을 것이다. 이제 브릿지 사용 준비 완료.

이제 마지막이다. QEMU/KVM에서 NIC 설정에 들어간다.

  1. Network source를 Bridge device로 선택한다.
  2. Device name은 위에서 설정한 브릿지 이름을 적어준다.(위에서는 bridge0)
  3. Device model을 e1000e로 선택한다.
  4. Apply를 눌러서 적용한 후, VM을 실행하면 된다.

끝.

참고자료
https://levelup.gitconnected.com/how-to-setup-bridge-networking-with-kvm-on-ubuntu-20-04-9c560b3e3991

https://wowgold-seller.com/ko/stories/285-how-to-use-bridged-networking-with-libvirt-and-kvm

구글 애드센스 주소 인증

오늘 드디어 아래와 같이 종이 우편물로 된 구글 애드센스 주소 인증 편지가 도착했다.
12월 6일 발송 후, 14일이 지난 12월 20일에 받았다. 2~4주 정도 걸릴거라고 했는데, 정확히 2주가 걸렸다.

편지를 열어보면 아래 내용과 같이 상세한 설명과 함께 PIN 번호가 적혀있다.

구글 애드센스에 들어가서, 아래의 6자리 인증 PIN 자리에 입력해 주고 제출버튼 누르면 끝.

난생 처음 애드센스 주소 인증이라는 걸 경험하다보니, 처음에 이게 뭐지? 주소 인증이라고? 어떻게 되는 거지? 했는데, 결국 알아보고 기다려본 후 알게된 내용이다.

요약하면, 구글 애드센스 주소 인증을 할 때가 되면 드디어 수익이 USD 10을 넘겼구나 싶은 마음으로 PIN이 담긴 우편물을 기다렸다가, 우편물이 도착하면 인증하면 된다.

구글 애드센스로 주소 인증 처음 해 보시는 분들께 도움이 되길 바라는 마음으로 적어보았다.

구글 애드센스 주소 확인 PIN

구글 애드센스에 들어갔더니, 처음 보는 문구를 발견하였다.
“주소가 확인되지 않아 지급이 보류 중입니다” 라는 Alert 이었다.

구글 애드센스에서 수익금을 지급하기 위해서는 지급받는 주소에 대해 인증을 해야 한다.
이를테면, 휴대전화 인증을 할 때 폰으로 인증문자에 있는 인증번호로 인증하는 것과 같은 원리다.
구글 애드센스는 수익이 USD 10을 초과했을 때 주소 인증 작업에 들어간다.

필자의 경우 어제 PIN을 발송했다고 한다.
2~4주 안에 우편물이 도착하면 우편물에 들어있는 PIN을 입력해주어야 한다.
PIN 발송 후 4주가 지났는데도 PIN을 입력하지 않으면, 광고게재가 중단된다고 한다.

뭐 광고 수익 지급까지는 한참 멀었지만, 처음으로 수익금이 USD 10을 넘었다.
아직 작은 금액이지만 나름 뿌듯하기도 하고, 욕심을 좀 내보고 싶기도 하고 그렇다.

일단은 PIN에 대한 간략한 이야기 끝~*

참고자료
https://support.google.com/adsense/answer/157667?hl=ko

Web Canvas에서 화면에 출력할 문자열의 길이 알아내기

Canvas의 Context에 measureText라는 메소드를 사용하면, TextMetrics라는 객체를 돌려받게 되고, width 속성을 통해서 화면에 그려질 텍스트의 크기를 알아낼 수 있다.

var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var text = ctx.measureText('12345');
console.log(text.width);

참고자료:
https://developer.mozilla.org/ko/docs/Web/API/Canvas_API/Tutorial/Drawing_text

크레온 플러스 API 연동관련 IsConnect 확인 후 강제종료

크레온 플러스 API 연동시 특정 시스템에서 발생하는 문제가 있다.

결론부터 이야기하자면, 윈도우즈 운영체제에서 인식하는 CPU 개수가 1개인 경우에 CpCybos의 IsConnect 값을 확인하는 경우에 실행중인 어플리케이션이 강제 종료되는 현상이 있다. CPU 개수가 2개 이상인 경우에는 문제없이 작동하는 것을 확인했다.

원인을 파악하는 상세한 과정은 아래에 적어두었다. 과정에 대해 궁금하지 않은 사람은 읽지 않아도 괜찮다.

테스트한 머신은
Vultr 가상 머신 1 CPU, 2G RAM
python 3.9.6
pywin32 302

필자가 작성한 파이썬 코드에서 IsConnect에서 문제가 생기는 것을 확인하고, 문제를 파악하기 위해서 다시 작성한 코드는 아래와 같다.

import win32com.client
import time

print("START")
cp_cybos = win32com.client.Dispatch('CpUtil.CpCybos')
print("LOADED")
a = time.time()
is_connected = cp_cybos.IsConnect
b = time.time()
d = b - a
print("%.8f" % d)

for i in range(10):
print(i)
time.sleep(1)

print("END")

화면 출력 결과는 오류 없이 아래와 같이 출력되고 끝난다.

START
LOADED
5.55898523
0
1

너무 당황스러웠다, For Loop을 돌다가 어플리케이션이 강제종료된다는 것은 상식적인 코드의 실행결과가 아니었다.

흥미로운 것은 IsConnect 값을 얻어오는 과정이 문제가 생기지 않는 머신에서는 1초 미만의 시간만 걸리는 한 편, 문제가 생기는 머신에서는 5초 이상의 시간이 걸린다는 것이었다.

집에 있는 PC에서도 동일한 python 버전과 동일한 버전의 pywin32 라이브러리를 사용했는데, 결과가 달랐다.

1차적으로는 OS 버전이 달랐기 때문에, 혹시나 하는 마음으로 집에 있는 운영체제와 같은 버전의 윈도우를 Vultr의 동일 사양의 인스턴스에 설치해보았다. 하지만 결과는 같았다. 동일한 문제가 생기고 있었다. OS 버전의 차이가 영향을 주는 게 아니라는 것을 확인했다.

크레온 플러스 API Q&A 게시판에서 관련 게시물들을 검색하다가, “Re : 비주얼 스튜디오 닫힘 현상”이라는 게시물을 확인했고, 디버깅 하는 경우에는 “메모리 보안 프로그램 사용”을 끄고 사용해야 한다는 것이다.

그래서 동일한 시스템에서 “메모리 보안 프로그램 사용”의 체크를 해제하고 크레온 플러스를 실행하니, 정상 작동이 되는 것이다. 그러면 보안 프로그램 끄고 쓰면 되겠네 싶겠지만, 집에 있는 피씨에서는 보안 프로그램을 끄지 않고도 잘 된다. 보안 프로그램을 쓸 수 있는 PC와 쓸 수 없는 PC에는 어떤 차이가 있어서 그런 것일까 의문이 들었다.

가상 머신이라서 안 되는 것일까 싶은 생각이 들어서, 현재 개발용 머신으로 사용하는 Ubuntu 20.04에 Gnome Boxes 위에 동일한 윈도우즈를 설치하고 테스트해봤다. 전혀 문제가 생기지 않았다.

그렇다면 Vultr 서비스에 어떤 문제가 있어서 그런 것 아닐까 싶었다. 그런데 지난 번에 사용했던 $20 짜리 인스턴스는 문제가 생기지 않았었는데, 왜일까 싶은 생각이 들었다. 현재 테스트한 Vultr의 인스턴스는 CPU 1개짜리, 잘 되던 인스턴스는 CPU 2개짜리 였다. 잽싸게 떠놓은 Snapshot으로 CPU 2개짜리 인스턴스를 띄우고 테스트 해 봤고, 잘 작동하는 것을 확인했다.

이게 정말 원인이라면 Gnome Boxes에서도 동일한 문제가 생겨야 한다는 생각으로 Gnome Boxes의 CPU 개수를 1개로 변경하고 다시 테스트 해봤는데, 동일한 문제가 생겼다.

결론을 다시 정리해 보았다.

첫째, AOS는 CPU 개수가 1개인 머신에서 크레온 플러스의 IsConnect 값을 얻어오는 과정에서 문제를 일으킨다.

둘째, 가상머신이나 클라우드 서비스와는 아무 상관이 없다.

해결책
IsConnect 값을 얻어온 이후에 얼마 안 있다가 어떠한 오류 메시지도 없이 작성한 어플리케이션이 종료된다면, CPU 개수를 운영체제가 몇 개로 인식하고 있는지 확인하고, 만약 1개라면 2개 이상인 머신에서 구동한다.

끝!

리눅스 운영체제에서 타임존 설정하기

클라우드 서비스를 이용하게 되면 기본적으로 시간은 UTC +00:00 기준으로 설정된다. 한국시간 기준으로 타임존을 설정하려면 timedatectl 명령어를 사용하면 된다.

우선 timedatectl만 입력하면 상태값들을 확인할 수 있다.

그리고, 아래와 같이 입력하면 Asia/Seoul 기준의 타임존 설정이 끝난다.

sudo timedatectl set-timezone Asia/Seoul