(무려 3년 만의 포스팅.. 요즘엔 그냥 개인 노션에 정리만 하는 편...)

어쩌다보니 식당 한군데의 자잘한 일들을 봐주고 있다.
주로 네트워크, CCTV나 매장에서 메뉴판으로 쓰는 아이패드 관리 따위인데,,
어제는 매니저님에게 전화가 오더니 네트워크 어쩌구 하시더라.

이야기를 들어보니, 포스에서 주문을 넣으면 주방 등에 영수증으로 주문 내역이 출력되는데, 그 출력이 안되더란 이야기.
그래서 포스사 직원을 불렀는데 직원은 네트워크 문제일거라고 하셔서 나에게 도움 요청하신거였다.

내가 한건 아니지만,, 매장 구조상 한 곳으로 보인 랜선을 랜 커플러로 다시 다른 곳으로 보내서 연결이 주렁주렁된 터라 찔리는게 있어서 그러려니 하였고,, 그래도 현상이 이상해서 매장을 방문해봤다.

서론이 꽤나 길 것 같은데...

[토스 결제 시스템에 대한 배경 지식]

토스 플레이스는 위 사진과 같은 조합의 SW/장비들을 제공한다.
왼쪽은 포스 프로그램. 포스 프로그램이란게 늘 그렇듯 필수는 아니다. 있으면 매장 주문 관리 등이 조금 편해지는거고...
윈도우, 맥, 아이패드, 갤럭시 모든 플랫폼을 지원하는게 특이한 포인트 + 보통 사용 수수료를 받는데 토스 포스는 무료로 사용할 수 있다.
토스 포스 프로그램에 대해서도 써볼려면 글이 따로 하나 나올 것 같아서 하략...

그 다음은 토스 프론트. 주로 결제 단말기로 많이 사용하며 간단하게 메뉴를 표시하거나 사용자 입장에서 키오스크 주문기처럼 사용할 수도 있다. 안드로이드 기기임. 영수증 프린터 기능은 없기 때문에 유무선으로 다른 장비를 연결해줘야 한다. 보통 정말 결제만 되는 카드 단말기를 하나 백업으로 구비하고, 그 단말기가 영수증 프린터를 겸하기 때문에 거기다 연결하는 경우가 많은 것 같다.

그 다음은 터미널인데, 이번에 문제 생기면서 직원이 임시로 갖다줘서 처음 봤다. 프론트를 고객 쪽에 향하게 하고, 터미널은 안쪽 직원이 금액 입력, 영수증 출력 등의 용도로 사용하는 느낌인 듯. 생긴걸 보니 결제 단말기로써의 역할도 할 것 같다.

[토스 포스와 영수증 프린터]

토스 포스는 한 매장에서 동시에 여러개 실행할 수 있는데, 매장 현황(테이블 정보, 주문 내역) 등은 공유하지만 연결되는 결제 단말기나 프린터 정보는 공유되지 않는다.
다만, 한쪽에서 주문했을 프린터가 연결된 다른 기기가 켜져있다면, 그 기기가 주문 정보를 받아서 대신 인쇄를 해준다. 그래서 여러 기기에 걸쳐 프린터를 연결해두면 안됨. (이걸 모른 채로 자꾸 지운 프린터로 인쇄가 되어서 한참을 헤맸음ㅠ)

실행 중인 토스 포스에서 영수증 프린터로 인쇄 요청을 보내는 방식이기 때문에, 포스가 실행되는 장비 기준으로 시리얼/USB 연결된 프린터나, 블루투스, 와이파이 프린터로 인쇄시킬 수 있고, 토스 프론트와 연결하고 나면 토스 프론트에 유선 연결된 프린터로 인쇄시키는 것도 가능하다.
또한 A 프린터는 영수증만, B 프린터는 주방에 주문 내역을, C 프린터는 다른 곳에서 특정 주문만을 출력하는 등 프린터별로 인쇄 종류를 나눌 수 있다.

토스 터미널이 아니라면 인쇄는 ESC/POS 프로토콜로 인쇄 요청을 보내게 된다.

이 매장에서는 토스 프론트에 유선 연결된 결제 단말기 하나, ESC/POS 유선 이더넷 영수증 프린터 3대, 그리고 ESC/POS WiFi 프린터 1대를 사용 중이다.

세우테크 SLK-TS400W, 와이파이 영수증 프린터

[문제 상황]

다시 매장으로 돌아와서, 영수증 프린터 한대의 파손과 다른 프린터가 모두 작동을 하지 않아서 토스 플레이스 대리점 직원을 부른 상황.
직원 입장에선 토스 프론트와 직접 연결된 결제 단말기는 인쇄가 되고, 네트워크로 연결된 영수증 프린터가 작동하지 않으니 네트워크 탓을 할 수 밖에 없었을터다.

나도 현상이 너무 이상해서 이런저런 테스트를 해봤는데, 아무리 봐도 네트워크 문제는 아니였다.
그러다 내가 ESC/POS 프로토콜로 프린터에 직접 명령을 전송할 경우 인쇄가 잘 되는걸 발견하였다!!!

임시로 가져오신 토스 터미널 2대는 인쇄가 잘 되었다. 토스 터미널은 ESC/POS 프로토콜이 아니라 별도 방식을 사용하는 듯.

대리점에서 오신 분도 계속 네트워크만 의심하시다가, 내가 테스트한걸 보시더니 토스 포스 앱의 문제임을 99% 확신하시고 영상을 찍어가셨다. 토스 포스 앱이 갑자기 문제 생겼으리라곤 누가 의심했을까...
다른 매장에선 별도로 안된다는 리폿이 없어서 더 네트워크만 의심했던건데, 왜 다른 매장 리폿이 없었는지는 의문이다. 그냥 그러려니 하고 쓰거나... 토스 포스를 그만큼 안쓰거나....??

(수정) 다음날 대리점 직원으로부터 전달받았는데 다른 매장은 잘 된다고 한다... 저 매장도 전체 기기에서 프린터를 삭제하고 다시 등록하니 또 인쇄가 되기도 하는걸 발견....

대리점 직원분도 예전과 다르게 최근에는 매장에 설치해주러 갔을 때 프린터 연결이 잘 안되어서 힘들었는데, 포스 프로그램 탓이었던 것인가?! 하면서 한탄하시더라..ㅠㅠ 그건 아마 다른 문제일 것 같긴 하지만 그냥 그러려니 했다.

여튼 당장 할 수 있는게 없으니 둘 다 퇴근.

 

[해결 과정]

집에 가는 길에 문득 토스 포스에서 인쇄 요청을 어떻게 잘 못 보내는지 궁금해졌다.
위에서 얘기했듯, 포스 프로그램을 별도로 실행시키면 매장 영업에 큰 영향 없이 이런저런 테스트를 할 수 있다.
로컬에 소켓 서버를 열고, 뭐라고 오는지 받아봤다.

테스트 출력을 누르면 '테스트 프린트' 라고만 출력이 되는데, 그 요청을 받아봤다.
ESC/POS 프로토콜은 검색해봤음. ESC 는 0x1B 를, GS 는 0x1D 를 의미한다.
요청 받은 패킷을 해석하면 아래와 같다.

1B 52 0D
	ESC R n: Select international characters
    	n 13: Korea
1D 21 11
	GS ! n: Select character size
    	0 <= n <= 255
C5 D7 BD BA C6 AE 20 C7 C1 B8 B0 C6 AE 0A
	'테스트 프린트\n'
1B 21 00
	ESC ! n: Batch specify print mode
1D 21 00
	GS ! n: Select character size
1B 61 00
	ESC a n: Position alignment
    	00 or 48: left
        01 or 49: center
        02 or 50: right
1D 42 00
	GS B n: Specify/cancel white/black inverted printing

0A 0A 0A 0A 0A 0A
	'\n\n\n\n\n\n'
1D 56 31
	GS V: Cut paper
    
(아래 4개 중복)
1B 21 00
1D 21 00
1B 61 00
1D 42 00
(----------)
1B 40
	ESC @: Initialize printer

 

소켓을 제대로 못 열거나, 실수로 프린터 주소를 하드 코딩 해뒀거나.. 따위를 의심했는데 그런건 아니였다.
그저 소켓 연결 수립 직후 보내야하는 Initialize printer 패킷 (0x1B 0x40)을, 가장 먼저 보내지 않고 가장 늦게 보내고 있었다...ㅡㅡ;;

그래서 매장에 따로 오드로이드(라즈베리파이 같은거) 한대 꽂아두고, 파이썬 서버를 띄워서 1B 40 으로 시작하지 않는 인쇄 요청은 내가 붙여서 다시 프린터로 보내도록 간단하게 프로그램을 짜두고, 토스 포스 프린터 설정을 다 바꾸었다.

그러니 정상 작동!

코드는 오래 쓸게 아니니 대충 작성해서 돌렸다.

import socket
import binascii
import traceback
import os

PORT = int(os.environ.get('PORT', '9100'))
TARGET = '192.168.20.' + os.environ.get('TARGET', '250')

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
sock.bind(('0.0.0.0', PORT))
sock.listen(10)

while True:
	conn, client_addr = sock.accept()
	print('connection from', client_addr)
	
	proxy = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	is_first = True

	try:
		proxy.connect((TARGET, 9100))
		while True:
			data = conn.recv(1024)
			
			if data:
				if is_first:
					is_first = False			
					if data[:2] != b'\x1b\x40':
						proxy.send(b'\x1b\x40')
				
				# print('received', binascii.hexlify(data, ' ').upper())
				proxy.send(data)
			else:
				# print('no more data from', client_addr)
				break
	except:
		traceback.print_exc()
	finally:
		try:
			conn.close()
			proxy.close()
		except: pass

 

[추가 문제]

인쇄가 잘 되어서 싱글벙글하고 있었는데,, 어느순간 또 먹통이 되는 문제가 발생..
토스 터미널은 여전히 잘 되고... 토스 포스 프로그램을 완전히 종료하고 나면 또 잘 된다.
영상을 올리고 싶은데... 매장명이 노출되는데 영상 편집은 귀찮으니 생략....

매장 직원들에게 물어보니 예전부터 자주 그랬다고.... 직원들은 맺힌게 많았는지 포스 안 만들던 회사가 만드니 너무 불안정하다고 아예 시스템을 갈아버렸으면 좋겠다고 얘기하시더라.... (하지만... 토스 프론트가 예쁜걸.... 매장 주문 내역을 가져갈 수 있는 API 같은 것도 전혀 없어서... 바꿔야 한다는 의견도 프론트 예쁘다 원툴로 버텼는걸....)

그동안 안되는게 네트워크 문제일 줄 알았는데 전부 토스 문제였다니... 허허....

안될 때는 프린터로 소켓 연결 수립 조차 안한다. 이건 내가 어떻게 할 수 없으니 GG...
그냥 안되면 포스 앱을 한번 종료했다가 다시 실행해달라고만 전해뒀다.


방문하셨던 담당자분에겐 이 문제를 전달해드렸는데... 이게 과연 토스 포스 개발팀에게 전달이 될지.. 되면 언제 수정이 될지...
토스 포스 앱 자체는 업데이트가 되게 잦던데, 금방 해결되길 바라본다.

문제를 파악하고 해결하는 과정이 나름 재밌기도 했고,
누군가는 또 오작동이 자기 매장의 문제일거라 생각하고 고통받고 있을 것 같아서,, 혹시나 하는 마음에 짧게 남겨 보았음.


(추가 수정) 프린터로 요청 자체를 보내지 않는 문제 때문에 사용을 거의 못하셨다고 한다.
그래서 오늘은 토스 터미널 요청을 역분석해서, 터미널로 등록 → ESC/POS 프린터로 전송하도록 수정하였다.

토스 터미널은 :14555 포트에 http 서버가 띄워져 있으며, 토스 포스 앱은 3개의 엔드포인트를 요청한다.
- GET /: 404 반환됨
- GET /sn: { "serialNumber": "..." } 반환. 아무 값이나 뱉어도 무관함
- POST /print: 인쇄 요청, { "data": "base64 encoded..", "count": 1 }

헤더로도 몇가지 오지만 일단 무시.

base64 인코딩 된 문자열은 ESC/POS 명령어셋과 거의 동일하지만, 지원 인코딩 셋이 좀 다르다.
코드 상으론 좀 더 다양하게 지원하는 것 같긴 한데, 일단 ESC R n 에서 n = 0x0D Korean 표준을 따르지 않고, 0x0F 를 사용, 이는 GB18030 셋으로 인코딩 된다. 중국어 코드 집합인데,, 한국어도 잘 됨.

조금 귀찮지만 GB18030 을 디코딩한 후, cp949 에 없는 캐릭터셋은 대충 ? 로 치환해준 뒤, cp949 로 보내면 된다.

이를 위해 ESC/POS 명령어셋 파싱이 필요한데, 일단 내가 확인한 바로는 아래 명령어셋만 사용함.
- ESC @, ESC R, ESC !, ESC a, ESC E
- GS !, GS B, GS V

추가로 따로 포트번호가 없기 때문에 여러 대의 프린터랑 연결하기가 어렵다.
서버에 IP 를 여러개 할당한 후, 요청의 Host 헤더를 보고 적절한 프린터로 연결되도록 수정함.
도메인 주소는 토스 포스 앱에서 올바른 주소로 인정해주지 않는다...ㅎㅎ;;

조금 더 코드가 길어졌지만... 일단 이렇게라도 잘 되길 바라며....

(작성 중...)

보통 메일 서버를 직접 구축하는 짓은 하지 말라고들 한다.
스팸/바이러스 메일을 걸러내는 작업, 내 메일이 스팸처리가 되지 않게 하기 위한 작업, 메일을 중단 없이 수신할 수 있도록 지원 등등...
물론 직접 구축하는 작업이 아무나 할 수 있는게 아니기도 하고.

그래서 개인 도메인을 이용한 메일을 사용하기 위해선 유/무료의 기업용 서비스를 이용하거나 메일건 같은 서비스를 이용한다.
무료는 거의 없어지는 추세에 다음 스마트워크나 메일건 정도 남아있지만 제약들이 좀 불편했고, 유료도 서비스 자체나 과금 정책 등도 마음에 안드는 구석들이 하나씩 있어서 어떻게 하면 좋을까 고민하던 중, 어느정도 손이 가지만 타협할만한 방법이 있는 것 같아서 사용 및 설정을 해보았다.

일반 메일 서버 구축을 하듯이 Postfix + Dovecot 을 설정하지만, 실제 외부와 통신은 AWS SES를 거쳐서 진행하는 방식으로 구성을 하였다.
참고로 이미 이런 형태로 제공하는 가이드 등이 존재하지만, 다양한 계정으로의 수신을 지원하지 않아서 그 부분 등을 고려하여 세팅을 진행하였다.


AWS SES

AWS Simple Email Service 라고, 메일의 송수신을 지원하는 서비스이다.
다만 일반적인 메일 서비스처럼 지원을 하는건 아니고 송/수신이 조금씩 다르다.

일반적인 메일 서비스처럼 바로 사용할 수 있는건 아니지만(그런 목적으론 유료의 AWS WorkMail이 있다)
송신 기준으로 메일 전송에 필요한 각종 서버 설정을 하지 않고 AWS의 신뢰도에 기댈 수 있고, 수신 기준으로도 AWS가 일단 안정적으로 받아주고 시작하는게 좋아보여서 사용하기로 하였다. (바이러스 검사나 스팸 체크도 해주지만 내가 후처리를 따로 해줘야 한다.)

사용 방식 / 비용

먼저 송신은 초당, 일당 전송 제한이 있으며
AWS API를 이용하여 전송(월 62,000건 무료 후 과금)을 하거나, AWS IAM 사용자를 이용한 SMTP로 전송이 가능하며,
1000건당 $0.1 및 용량 기준으로 GB당 $0.12 가 과급된다.

후자의 SMTP 방식을 이용하면 일반 메일 클라이언트에 등록해서 사용할 수 있긴 한데, IAM을 사용하기 때문에 사용자 아이디/비밀번호를 내가 설정할 수도 없고 권한 부여도 까다롭다.

수신은 정한 규칙에 따라 AWS 람다를 실행하거나, S3에 저장하거나, SNS 토픽을 발행하는 등의 방식으로 이루어진다.
이 또한 1000건당 $0.1 (1000건 무로) / 256KB 1 chunk 기준으로 chunk 1000건당 $0.09 과금된다.
작성일 기준으로 한국 리전은 수신을 지원하지 않아 us-east-1 에서 사용하였음.

AWS SES 설정

AWS 에서 메일 송신을 위해선
1. 도메인 혹은 메일 주소 인증
2. 도메인의 경우 DKIM 등 설정
3. 외부로 메일 전송을 위한 Sandbox 해제 요청
작업을 해야하고,

수신을 위해선 MX레코드 설정이 필요하다.
이런 부분은 다른 사람들이 쓴 글이나 AWS 가이드에도 설명이 잘 되어있으니 생략.

이 후 Rule set 설정, Lambda, S3, SNS 등 설정은 분량 관계상 별도 포스팅으로. (작성 후 링크 예정)


Postfix

SMTP 프로토콜을 이용하여 메일을 수발신 할때 사용하는 프로그램. MTA (Mail Transfer Agent) 의 한 종류이다.
예전엔 sendmail 이 사용되었으나 요즘엔 Postfix를 가장 많이 사용한다.

Postfix 기능들

이 프로그램이 하는 역할이 겉으로 보기엔 단순 메일 수발신이지만 자세히 보면 좀 다양하다. 적절히 필요한 것만 취하면 됨.

1. 서버 내에서 내/외부로 메일 전송시 처리
    -> 안 써서 필요없음

2. 외부 클라이언트에서 서버를 통하여 메일 전송 (SMTP Submission)
    -> AWS의 SMTP를 사용해도 되는데, 메일 주소(사용자)별 인증을 쓰고 싶어서 이용.

3. 외부 클라이언트로 전송할때 사용자 인증 / 메일 검증 등
    -> 인증은 Postfix 자체적으로 할 수 있게 설정도 가능한데, 후술할 Dovecot과 연결하여 Dovecot의 인증을 사용하는 방법도 가능하다. 다 따로 구현하면 관리가 번거로워지니 이 방법을 사용할 예정.

4. 내 도메인으로 전송된 메일을 수신
    -> 나의 경우 수신을 AWS가 해주기 때문에 불필요한 기능이지만, 발송 과정에서 Postfix를 사용하고 있고 내 도메인으로 전송하는 경우가 발생할 수 있기 때문에 적절한 설정을 해줘야한다. (예시로 a@naver.com 에서 b@naver.com 으로 메일을 보내는 경우.)
        기본적으론 서버 내 해당하는 경로에 메일 원문을 저장하게 되어 있지만, 난 Dovecot 으로 전송하도록 설정할 예정

5. 메일 수신시 사용자 존재 여부 확인 / alias (다른 주소로 수신하는 기능)
    -> 메일 수신자에 따라 실질적으로 어떤 계정이 해당 메일을 받을지 결정하는 기능..
        support@도메인 으로 전송하면 CS팀에 속한 직원이 모두 해당 메일을 받는다거나.. 하는 목적으로 사용된다.
        난 내 도메인으로 오는 전체 메일을 내가 사용할 한두개 계정으로 받기 위해 사용할건데, 메일 수신을 Postfix만 하는게 아니라서 Postfix 와 Lambda 양쪽에 동일하게 작동하도록 구성해주어야 한다.

6. 다른 서버가 전송하는 메일을 다른 서버로 릴레이
    -> 보안 상의 이유 등으로 보통 비활성화

 

Postfix 설정

분량 관계상 포스팅을 분리하여 작성 (작성 후 링크 예정)


Dovecot

메일 박스를 관리하며 POP3, IMAP 등 프로토콜을 지원하여 다른 프로그램에서 메일을 받아갈 수 있도록 지원한다.
SMTP Submission 기능도 지원하는 것 같긴 하던데, 어차피 Postfix도 필요할 것 같아서 사용하지 않았음.

MTA(Postfix)가 메일을 수신해서 폴더에 저장하면 Dovecot이 알아서 그걸 읽는 방법도 있고,
MTA가 다시 Dovecot으로 LDA(Local Delivery Agent)나 LMTP(SMTP 개량 프로토콜)를 통해 보내줄 수도 있다.
예전엔 LDA를 썼었는데 최근엔 설정 편의성과 성능 때문에 LMTP를 더 많이 쓴다고 한다.

나의 경우 역시 Postfix - LMTP -> Dovecot 로 설정을 하였고,
AWS SES에서 수신한 메일도 AWS SES -> S3 -> SNS -> Lambda - LMTP -> Dovecot 으로 구성을 하였다.
보통 Lambda에서 Dovecot의 메일박스로 파일을 바로 전송시키는 방법을 사용하는데, 이러면 폴더 구조 같은걸 내가 신경 써줘야해서 난 수신자/alias 구분만 Lambda에서 하고 LMTP로 Dovecot에 떠넘겼음.

Dovecot 설정

역시 분량 관계상 포스팅 분리하여 작성 (작성 후 링크 예정)


사용 포트 / TLS

Dovecot 에서 사용할 POP3 와 IMAP 은 TLS 암호화가 추가된 버전인 POP3S(995/tcp), IMAPS(993/tcp) 만 사용할 예정이다.
내부 메일 전달을 위한 LMTP는 Postfix만 쓸거면 unix socket으로 해도 되지만, Lambda에서 사용해야 하니 적당히 임의로 2525/tcp 포트도 추가로 사용.

사용자가 메일 전송을 위해 Postfix에 접속할 때는 SMTPS(tcp/465) 대신 SMTP + STARTTLS 을 사용할거고, 25/tcp 가 OUTBOUND로 차단되는 경우가 많기 때문에, 587/tcp 포트를 사용한다.

즉 587, 993, 995 3개 포트는 모두 열려있어야 하며, 2525 포트는 내부에서 사용할 수 있게만 열려있으면 된다.

TLS 연결을 위해 인증서를 발급받아야 하는데, Let's encrypt(certbot) 을 이용한 웹서버용 인증서를 그대로 사용할 수 있다.
이 인증서의 발급 방법은 생략.
발급된 경로만 잘 확인하여 후에 설정할 때 적절한 경로를 넣어주면 된다.

이 후 발급된 인증서를 Dovecot / Postfix 각각 설정에 적절히 넣어주면 된다.


전체 구성도

아직 시작도 안했지만 벌써부터 복잡한, 전체 구성도는 아래와 같다.

DB와 메일 서버는 동일 서버여도 되지만 난 분리되어 있기 때문에 이미지상 분리해뒀다.

이미지에서 볼 수 있다시피 Lambda가 DB와 EC2 서버에 각각 접근해야 하는데, DB는 당연하고 LMTP도 Public 오픈을 권장하지 않기 때문에 Lambda를 private subnet에 넣고 동일 VPC 네트워크 내에 사설망을 이용하도록 구성하였음.


나중에 사용자 인증을 LDAP 으로 사용한다거나.. 등도 고민 중인데..... 갈길이 멀다.....ㅠ

iDRAC 에 접속하면 Virtual Console 이라고,, 간단하게 말해서 원격으로 서버 콘솔에 접근할 수 있다.
일종의 원격제어...
서버가 죽어도 서버실에 갈 필요 없이 왠만한 복구는 다 할 수 있게 해주는 한줄기 빛같은 존재

Java Web Start 라고, 웹브라우저에서 바로 자바를 실행할 수 있게 만들어진 프레임워크를 사용하는데, 요즘에 보안때문에 그런게 될일은 당근 없고, 그냥 viewer.jnlp 파일이 다운받아지는걸 자바로 실행해주면 된다.

평소엔 쓸 일이 없으니 봉인해두다가, 오늘 쓸일이 있어서 열어봤는데

안된다...ㅠㅠㅠ

검색해보니 Java Web Start 가 Java 9에서 deprecated 되었고, Java 11에서 삭제되었다고 함.
웹에서 실행해줄 뿐이지 어쨋든 자바니까, 직접 실행할 수 있는 방법을 찾아봤다.

우선 jnlp 파일을 열어보면 연결에 필요한 인자값들과 OS와 아키텍쳐에 따른 java 파일 링크가 걸려있다.
avctKVM.jar 파일과 연결하려는 시스템에 맞는 lib 파일들을 받는다.

그리고 구버전 JRE를 구한다. 설치할 필요는 없으니 오라클 홈페이지에서 tar.gz 버전으로 다운로드 받으면 됨.
1.7.0_80 (7u80) 버전이 된다길래 난 이걸로 했음.
bin, lib 등이 있는 폴더를(Mac버전 기준 Home) jre 라는 이름으로 바꿔서 가져온다.

정리하면,
┣ avctKVM.jar
┣ lib/
┃    ┣avctKVMIOMac64.jar
┣    ┗avctVMAPI_DLLMac64.jar
┣ jre/
    ┣ bin/...
┗    ┗ lib/...
이런느낌의 디렉토리 구성이 되도록..

이 후 viewer.jnlp 파일의 인자를 참고하여 다음과 같이 명령어를 실행하면 된다.
- viewer.jnlp 에는 일회용 ID/PW가 있는데, 그걸 써도 되지만 원래 계정을 입력해도 접속이 잘 됨.
- 없어도 되는 인자도 있겠지만 난 그냥 다 넣어줌.
- vmprivilege는 참고한 글에서 넣어줬길래 그냥 넣어줌.

./jre/bin/java -cp avctKVM.jar \
	-Djava.library.path=./lib com.avocent.idrac.kvm.Main \
	ip=SERVER_HOST \
	vm=1 \
	user=USER_ID \
	passwd=USER_PW \
	kmport=9595 \
	vport=9595 \
	apcp=1 \
	reconnect=1 \
	chat=1 \
	F1=1 \
	custom=0 \
	scaling=15 \
	minwinheight=100 \
	minwinwidth=100 \
	videoborder=0 \
	version=2 \
	vmprivilege=true

아, java 를 인터넷에서 받았다고 실행을 안해줄텐데, 파인더에서 option+열기로 먼저 실행해주거나,,, 여러가지 방법으로 허용해주면 됨.
난 걍 개인 정보 보호 - 개발자 도구 옵션에서 터미널을 추가했음

이러면 원래 쓰던거처럼 연결이 잘 됨.
다만 맥 기준,
한번이라도 한글인 상태로 타이핑을 하면 키 입력이 이상하게 들어가서 재접속을 해야하고
macOS 보안 옵션 문제인지 전체 키스트로크를 받을 수 없다고 오류가 난다. 이건 설정에서 직접 허용해주면 될 것 같기도 함.

 

zigbee2mqtt 설치

(이전 글에 합쳐져있던 내용을 새 글로 분리)

zigbee2mqtt (이하 z2m) 은 mqtt 란 프로토콜을 기반으로 작동하는건데,
z2m은 mqtt 클라이언트로서 연결할 mqtt broker (서버라고 생각하면 됨)가 필요하다.

docker 로 mqtt broker 인 eclipse-mosquitto 와 z2m 둘 다 설치할거임.

# eclipse-mosquitto 이미지 다운 및 실행
docker pull eclipse-mosquitto
sudo docker run -d \
    --name=mosquitto \
    -p 1883:1883 \
    -p 9001:9001 \
    --restart=always \
    -v /home/pi/ha/mosquitto/data:/mosquitto/data \
    -v /home/pi/ha/mosquitto/log:/mosquitto/log \
    eclipse-mosquitto

# z2m 이미지 다운 및 실행
docker pull koenkk/zigbee2mqtt
docker run -d \
    --name="z2m" \
    --net=host \
    --restart=always \
    -v /home/pi/ha/z2m:/app/data \
    --device=/dev/ttyACM0 \
    -v /run/udev:/run/udev:ro \
    -e TZ=Asia/Seoul \
    --privileged=true \
    koenkk/zigbee2mqtt


설정 파일 경로는 이전글에 이어서 /home/pi/ha/ 폴더 안에 각 폴더를 만들고 지정해주었다.

z2m 실행시 필요한 --device 이름 역시 필요하다면 알아서 바꿔주자.


z2m 의 설정을 조금 변경해준다.

기본값으로 꺼져있는 homeassistant 를 켜주고, devices, group 을 관리하기 편하게 별도 파일로 만든다

cd ~/ha/z2m
sudo touch devices.yaml groups.yaml
sudo vi /home/pi/ha/z2m/configuration.yaml
homeassistant: true
permit_join: true
mqtt:
  base_topic: zigbee2mqtt
  server: 'mqtt://localhost'
serial:
  port: /dev/ttyACM0
devices: devices.yaml
groups: groups.yaml

zigbee 장비가 다 추가되고 나면 permit_join: false 로 바꿔주면 됨.


그 다음 HA의 설정도 변경, mqtt 항목을 추가해준다.

mqtt broker 를 추가하는거기 때문에 혹시나 eclipse-mosquitto 를 다른 장비나 다른 포트에서 작동시킬 경우 적당히 수정해주자.

sudo vi ~/ha/config/configuration.yaml
mqtt:
  broker: 127.0.0.1
  discovery: true


둘 다 재시작

docker restart z2m home-assistant


이제 HA의 통합 구성요소에 MQTT 가 나타나고 기기와 구성요소에도 z2m을 통해 연결된 장비가 나타단다.

deCONZ 로는 안 보였던 다원 스마트 플러그의 전력량도 잘 보이고, 다원 전등 스위치도 연결이 잘 됨.


실시간으로 올라오는 z2m의 로그를 보려면

tail -f $(ls -td ~/ha/z2m/log/*/ | head -1)log.txt

이렇게 하면 됨. z2m을 재시작할 때마다 실행 시간으로 디렉토리가 생긴다.

tail 명령어로 열었는데, 지난 로그를 보고 싶으면 vim이나 nano 등으로 직접 열어봐도 됨.

단점/불편한 점이 많아서 사용하지 않는 중.

기본 스토로지를 사용하되 s3에 백업하는 방식으로 구성이 더 나을 것 같다.


NextCloud 는 기본적으로 시스템의 디렉토리를 사용하지만,

추가로 External Storage Support 기능을 사용해서 FTP, S3 등등 외부 저장소를 마운트하여 사용할 수 있다.

 

처음엔 이렇게 연결하려고 했는데, 뭔가 안되어서 찾다보니, S3자체를 NextCloud의 주 저장소로 사용하는 방법이 있어서 그냥 그걸 사용해보기로 했음.

참고로 지금 하려는 주 저장소가 아니라 외부저장소로써 S3를 사용할 경우

(1) 사용자마다 S3 연결을 직접하지 못하고 관리자가 해줘야함

(2) 저장공간 사용 제약을 할 수 없음

(3) NextCloud의 공유 기능을 사용할 수 없음

요런 3가지 단점이 있다고 한다.

 

참고로 Amazon S3 뿐만 아니라 S3와 비슷한 object storage 류들도 사용이 가능하다고 함.

또한 S3와 연결된다고 해서 S3에서 직접 파일 브라우징을 할 순 없다고 한다. 파일 자체는 있지만 메타데이터가 없어서...

기존 설치된 NextCloud를 옮길 수도 없다. 새로 설치해야 됨.

 

nextcloud/config/config.php 파일 설정에

  'objectstore' => array(
    'class' => '\\OC\\Files\\ObjectStore\\S3',
    'arguments' => array(
      'bucket' => '버킷이름',
      'autocreate' => true,
      'key'    => 'IAM Access Key',
      'secret' => 'IAM Secret',
      'use_ssl' => true,
      'region' => 'AWS 리전, 서울이면 ap-northeast-2'
    ),
  ),

요 부분을 추가해두고 설치를 진행하면 된다.

 

이미 진행된 인스턴스가 있을 경우 nextcloud/data 폴더와 DB 테이블들을 날려버리고, config.php에 installed: true 라인 지우고, 마지막으로 config 폴더에 CAN_INSTALL 파일을 생성하고 접속하면 다시 설정부터 진행할 수 있다.

 

S3를 주 저장소로 할 경우 php의 파일 업로드 제한에 영향을 받지 않는 것 같다. 아마 S3 API 로 바로 업로드 시키는 듯?

 

참고: Configuring Object Storage as Primary Storage - https://docs.nextcloud.com/server/15/admin_manual/configuration_files/primary_storage.html

 

+ File lock 비활성화

NextCloud 는 공유된 파일을 2명 이상의 사용자가 동시에 편집해서 꼬이는 문제를 방지하기 위해 File locking 기능을 사용한다.

DB, 혹은 설정된 mem cache 에 lock 정보를 가지고 있고, 30분마다 cron이 지워주는 방식으로 작동한다는데, S3를 사용할 경우 끄는걸 권장한다는 듯? ( https://autoize.com/s3-compatible-storage-for-nextcloud/ )

 

일단 당장 내가 lock 으로 인한 문제를 발견해서(생성되고 파일을 빠르게 지울경우 뭔가 이상하게 lock 이 걸려서 파일 삭제가 안됨..) 그냥 꺼버렸음.

 

config.php에

  'filelocking.enabled' => false,

를 추가해주면 된다.

Docker로 설치해봤는데, docker 이미지는 web installer 방식이라 초기 설치시간이 오래걸리길래 그냥 네이티브로 깔았다.

참고로 아래 설치법은 일부 선택 옵션들을 포함하니 참고.

Installation on Linux &mdash; Nextcloud 여기 잘 설명되어 있으니 그냥 여길 봐도 된다. 좀 귀찮게 해서 그렇지...


1. apache2 + php7.4 설치

Ubuntu 18.04의 기본 php 는 7.0이다. 7.3 이상을 권장하니 7.4를 깔아주자

nginx도 못쓰는건 아닌데,, 왠지 apache2 가 기본값인 것 같아서 그냥 apache2 로 진행하였다.

sudo apt -y install software-properties-common
sudo add-apt-repository ppa:ondrej/php

sudo apt install apache2 libapache2-mod-php7.4 php7.4 php7.4-bcmath php7.4-bz2 \
    php7.4-curl php7.4-gd php7.4-gmp php7.4-intl php7.4-json php7.4-mbstring \
    php7.4-mysql php7.4-xml php7.4-zip libxml2


NextCloud 에서 imagic 모듈도 설치를 추천한다.

sudo apt install php-imagick


2. NextCloud 설치

php 기반의 프로그램이다. 웹사이트에서 받아서 적절한 위치에 압축을 풀어만 주면 됨.

https://nextcloud.com/install/#instructions-server


3. apache2 설정

/etc/apache2/site-available/cloud.conf (당연히 이름과 각종 경로는 알아서 수정..)

<VirtualHost *:80>
        ServerName 사이트주소

        DocumentRoot /var/www/nextcloud/
        <Directory /var/www/nextcloud/>
                Require all granted
                AllowOverride All
                Options FollowSymLinks MultiViews
        </Directory>

        LogLevel emerg
</VirtualHost>

apache2 에 필요/선택 모듈을 활성화해준다.

a2enmod rewrite headers env dir mime


4. php 설정

php 기본 설정은 업로드 용량이 2MB이므로, 조금 늘려준다.

메모리 제한값도 기본은 128MB이지만 추천은 512MB

sudo vi /etc/php/7.4/apache2/php.ini
memory_limit = 512M
post_max_size = 10G
upload_max_filesize = 10G


5. HTTPS 설정

이건 알아서 해주자.

zigbee IoT 장치들(End Device)를 사용하기 위해선 장치들이 연결되기 위한 Coordinator가 필요하다.

코디네이터를 중심으로 end device 들이 연결되는데, 중간에 네트워크 확장을 위해서 라우터를 추가하기도 함.

코디네이터 혹은 라우터로 사용할 수 있는 CC2531 을 구매 후 펌웨어 변경 작업을 정리해 보았음.


CC2531 펌웨어 플래싱 with RPi

* 참고: 
    * What do I need? | zigbee2mqtt.io - https://www.zigbee2mqtt.io/getting_started/what_do_i_need.html
    * Flashing the firmware on the CC2531 USB stick | zigbee2mqtt.io - https://www.zigbee2mqtt.io/getting_started/flashing_the_cc2531.html
    * Alternative flashing methods | zigbee2mqtt.io - https://www.zigbee2mqtt.io/information/alternative_flashing_methods.html
    * ConBee implementation #72 - https://github.com/jmichault/flash_cc2531/issues/9


우선 CC2531(약 $5) 이랑 다운로더 케이블(약 $2)를 준비한다. 난 AliExpress 에서 주문하였음.

칩안테나(회로에 안테나가 그려져 있는) 버전이 있고 안테나 단자가 달려 있고 안테나를 같이 파는 버전도 있다.

CC2531 을 그냥 쓸 경우 신호가 약하다는 글을 많이 봐서 난 안테나 버전으로 구매하였음.


펌웨어 작업이 이미 되어 있는 CC2531을 팔기도 한다던데 그걸 살 경우 다운로더 케이블과 이 작업이 필요없다.


위에 참고로 건 글 중 Flashing the firmware on the CC2531 USB stick 글을 보면 Windows, Mac, Linux 에서 플래싱을 할 수 있지만, 왠지 pi에서 하는게 더 편할 것 같았다.

pi나 아두이노로 진행하는 방법은 Alternative flashing methods 글을 참고하면 됨.


1. 파이에 WiringPI 설치

sudo apt install wiringpi


2. 파이에서 툴 다운로드

git clone https://github.com/jmichault/flash_cc2531.git


3. 파이와 다운로더 모듈 간에 GPIO핀 연결

연결을 위해선 암-암 점퍼 케이블 4개가 필요함.

다운로더 모듈

 파이

 pin 1 (GND)

 pin 39 (GND)

 pin 7 (reset)

 pin 35 (GPIO24, BCM19)

 pin 3 (DC)

 pin 36 (GPIO27, BCM16)

 pin 4 (DD)

 pin 38 (GPIO28, BCM20)

다운로더 모듈의 핀보드는 모듈에 적혀있으니 그걸 보면 되고, 파이의 핀 위치는 https://pinout.xyz/ 사이트 참고.


4개 핀도 연결하고 전원 공급을 위해 CC2531 을 파이의 USB단자에도 연결해준다.


4. 플래싱

1) 먼저 잘 연결이 되었는지 확인해본다.

cd flash_cc2531
./cc_chipid -m 90
  ID = b524.

ID가 0000, ffff 등이 나온다면 뭔가 오류가 있음.

원래 -m 90 을 붙여주지 않아도 되는데, 나의 경우 계속 붙여줘야 정상적으로 진행이 가능했다.


2) 펌웨어 파일 다운로드

코디네이터 버전 - https://github.com/Koenkk/Z-Stack-firmware/tree/master/coordinator/Z-Stack_Home_1.2/bin/default

라우터 버전 - https://github.com/Koenkk/Z-Stack-firmware/tree/master/router/CC2531/bin

# 코디네이터
wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/coordinator/Z-Stack_Home_1.2/bin/default/CC2531_DEFAULT_20190608.zip
unzip CC2531_DEFAULT_20190608.zip

# 라우터
wget https://github.com/Koenkk/Z-Stack-firmware/raw/master/router/CC2531/bin/CC2531_router_2020_09_29.zip
unzip CC2531_router_2020_09_29.zip


라우터 버전은 펌웨어가 3개가 나온다.

- router-cc2531-std.hex: 라우터 기능만 작동
- router-cc2531-diag.hex: 라우터 + 진단 정보
- router-cc2531-diag-usb.hex: 라우터 + 진당전보 + USB 시리얼포트로 인식 (진단정보를 USB로 읽기 가능)

진단정보가 뭘 말하는건지 모르겠어서 난 그냥 -std 버전을 사용하였음.


3) 펌웨어 플래싱

./cc_erase -m 90
./cc_write -m 90 CC2531ZNP-Prod.hex (혹은 해당하는 펌웨어명)


보통 HA에서 Zigbee 를 사용하기 위해 CC2531 칩 + zigbee2mqtt 를 많이 사용하지만,
ConBee II 라는 애가 "Very powerful"⁽¹⁾ 라고 소개되어 있어서가 있어서 구매해보았다.

아마존에서 $47에 구매, 57,304원이 빠져나갔다. CC2531 한개가 약 $5 인걸 고려하면 무시무시한 금액...ㅠㅠ


zigbee2mqtt 와 아직 호환이 완벽하지 않다고 적혀있어서⁽²⁾ deCONZ 란걸 사용해보았음

(1) Supported adapters | zigbee2mqtt.io - https://www.zigbee2mqtt.io/information/supported_adapters.html
(2) ConBee implementation - #72 https://github.com/Koenkk/zigbee-herdsman/issues/72


deCONZ 설정

# USB 제어를 하기 위해 현재 사용자를 dialout 그룹에 추가
# RPi 에서 pi 계정의 경우 이미 추가가 되어 있음.
sudo usermod -a -G dialout $USER

# 이미지 받아오기
docker pull marthoc/deconz

docker run -d \
    --name=deconz \
    --net=host \
    --restart=always \
    -v /home/pi/ha/deconz:/root/.local/share/dresden-elektronik/deCONZ \
    --device=/dev/ttyACM0 \
    -v /etc/localtime:/etc/localtime:ro \
    -e DECONZ_WEB_PORT=2000 \
    -e DECONZ_WS_PORT=2001 \
    marthoc/deconz


설정 파일 위치는 지정하기 나름. 이전 글에 이어서 /home/pi/ha/deconz으로 지정하였음.

--device=/dev/ttyACM0 부분은,, zigbee 모듈을 연결하고 해당 USB 항목을 넘겨주는건데 알아서 하자.

포트는 기본이 80, 443 인데 마음에 안들어서 각 2000, 2001 로 바꾸었다.

이제 http://RPi주소:2000로 접속 가능.


HA 웹페이지 통합 구성요소로 가면 deCONZ가 나타나고 클릭해서 연결하면 된다.

deCONZ 웹에서도 그룹을 만들거나, 제어를 하는게 가능하지만 어차피 HA로 제어를 할테니 zigbee 장비 연결만하고 돌아오면 됨.

그룹을 만들 경우 HA에도 나타나서 거슬린다.


문제점

 localhost 주소가 아닌 경우 pi의 IP가 바뀌면 HA와 deCONZ가 서로 통신을 못하는 어처구니 없는 일이 발생한다.

로컬주소로 바꿔봤는데도 이상함.. 그냥 deCONZ 자체가 IP가 바뀌면 이상하게 작동을 한다..ㅡㅡ


그리고 다원 DNS의 Zigbee Smart plug 는 연결은 되지만 제어만 되고 전력 소모량 등의 값은 올라오지 않는다.

Zigbee 전등 스위치는 아예 연결도 안됨...


결국 deCONZ 대신 zigbee2mqtt 를 다시 깔았다.. 이건 따로 글을 쓸 예정.

deCONZ 를 안쓸 경우 만들었던 docker 이미지를 꺼주거나, 지워주자.


# 인스턴스 정지
docker stop deconz

# 컨테이너 삭제
docker rm deconz

# 이미지 삭제
docker rmi marthoc/deconz


Home Assistant(이하 HA)를 설치하는 방법은 다양한 것 같지만, 난 RPi3B+ 에다가 docker 로 설치하였음.


# 도커 설치
sudo curl -fsSL https://get.docker.com/ | sudo sh

# 사용자 계정을 docker 그룹에 추가
sudo usermod -aG docker $USER

# HA 이미지 받아오기
docker pull homeassistant/raspberrypi3-homeassistant:stable

# 실행
docker run --init -d \
    --name="home-assistant" \
    --net=host \
    --restart=always \
    -v /home/pi/ha/config:/config \
    -e "TZ=Asia/Seoul" \
    homeassistant/raspberrypi3-homeassistant:stable


타임존은 어차피 다시 설정하던데 왜 적으라는지 모르겠다.. 혹시 모르니 일단 지정.

설정 파일이 저장될 위치는 그냥 적당히 /home/pi/ha/config 으로 지정했다.


실행이 되면 http://RPi주소:8123 으로 HA 관리 페이지에 접속할 수 있다.

계정 생성시에 처음에 적는 이름이 아니라 두번째 란인 사용자 이름이 ID 임에 주의..


HomeBridge 설정

iOS HomeKit 사용을 위해 HomeBridge를 활성화하려면 설정 파일에 한줄 추가해줘야 한다.

sudo vi /home/pi/ha/config/configuration.yaml

# Configure a default setup of Home Assistant (frontend, api, etc)
default_config:

# Text to speech
tts:
  - platform: google_translate

group: !include groups.yaml
automation: !include automations.yaml
script: !include scripts.yaml
scene: !include scenes.yaml

homekit:

이 후 HA 서버를 재시작

iOS 홈 앱에서 액세서리 추가 - HA 웹페이지 알림에 뜬 QR 혹은 코드로 등록하면 된다.


* 추가한 후에 HA에 새로운 기기가 추가되거나 삭제해도 홈킷에 제깍제깍 반영이 되지 않는다...

그럴 땐 HA를 재시작 하면 바로 반영 되는 것 같음...


근무지에 라벨프린터가 있었고, 업무상 자주 필요했는데, 생각보다 엄청 유용했다.

나도 하나 샀으면 좋겠다 싶어서 구매를 하게 되었음.


근무지에서 사용하던 모델은 EPSON LW-OK730 모델이다. 아래 사진과 같음

키보드가 달려 있어서 입력 후 바로 출력할 수 있고, 배터리로 작동하지만 콘센트를 연결해서 사용할 수도 있다.

우측 상단 초록색 영역을 통해 프린팅된 라벨의 모서리를 둥글게 깍아줄 수도 있는 제품.


저걸 쓰다가 마음에 들어서 라벨프린터를 구매하려는 것이었기에 가능하면 동일 모델을 구매하려 했으나...

음.. 이건 아닌 것 같다... 얼마나 쓸지 모르는 라벨프린터에 250,000원을 지불할 순 없어...


라벨프린터에는 여러 회사의 제품이 있지만 일단 도박을 하고 싶진 않아서 Epson 제품으로 한정하기로 했다.

Epson 라벨프린터엔 되게 다양한 제품이 있지만, Epson에서 분류하기로 대부분 비즈니스용 제품이고, 가정용 제품도 존재한다.


바로 이렇게 두개. K200 은 디자인에 따라 변형이 다양한 듯?


C410 은 휴대폰이나 PC에 블루투스로 연결하여 인쇄를 하는 방식이고, K200 은 키보드로 입력해서 바로 출력하는 방식이다.

C410 의 경우 인쇄 결과는 앱에서 정보를 보내주기 나름이니까 디자인 폼, 폰트, 세로쓰기 등등이 앱이 지원하기 나름에 따라가고, K200은 기기에서 지원을 해야하는데... 왠만한건 다 지원할거다 아마. 세부적인 기능은 일할거 아니면 필요없음...

그 외에 주요 성능상의 차이를 정리해보았다. LW-OK730은 참고용.

 

 LW-C410

 LW-K200

 LW-OK730

 카트리지 크기

 4~18mm

 4~18mm

 4~24mm

 출력 해상도

96 dots / 180 dpi 

 64 dots / 180 dpi

 128 dots / 180dpi

 출력 속도

최대 9mm/s 

 최대 6mm/s

최대 15mm/s 

 연속 인쇄 기능

 O

 X

 O

 자동 컷팅

 O

 X

 O

 전원 어댑터 연결

 X

X

O

카트리지 크기는 라벨의 세로폭을 말한다. 6~24까지 다써봤는데, 18,24는 정말 쓸일 없는 것 같다.

일상에서는 9mm / 12mm 면 충분한 느낌?


연속 인쇄는 같은 내용을 이어서 자동으로 인쇄를 할 수 있는 기능을 의미하는 것 같다. 쉽게 말해 N매 인쇄 기능.

자동컷팅은 인쇄가 끝나고 자동으로 잘라주는 기능이다.

LW-K200의 경우는 우측에 있는 버튼을 눌러줌으로써 칼날을 작동시켜 직접 잘라야 하는 듯?


검색을 해보니 키보드 있는 모델이 무조건 편하다고 하던데... LW-K200 은 별로 사고 싶지 않아서 그냥 LW-C410 모델을 구매하였다.


그리고 수령!

보통 옵션으로 추가테이프를 끼워주는걸 일부러 그거 없고 좀 더 저렴한 판매자를 골랐는데, 샘플용 흰색배경 검정글씨 12mm가 기본으로 들어있었다. AA 건전지 6개가 필요한데 건전지도 동봉.


처음 박스를 열고 당황했던건 생각보다 컸다...

뭔가 휴대폰 크기 정도일거라 생각했는데... 가로세로두께 모든게 내 예상보다 커서 당황...ㅠ


일단 샘플 카트리지로 테스트.

설명서에 카트리지 넣는법이라던가 휴대폰과 연결해서 인쇄하는 법 등이 잘 적혀있다.


앱은 Epson iLabel 혹은 Epson Home & Craft Label 둘중에 하나를 받으라고 적혀있었다.

iLabel 이 좀더 사무적인 느낌이라 난 이걸 다운받았음. (왠지 리뷰가 개판인건.. 기분탓이겠지.. 기분탓일거야...)


내용이나 정렬, 크기, 폰트, 미러모드, 가로세로, 여백, 컷팅 여부 등을 선택한 후 인쇄할 수 있다.

폰트는 그냥 다 영문폰트인 것 같은데.. 안드로이드 버전은 좀 다를려나?


인쇄는 잘 됨!


OK730도 살짝 느리다고 생각했는데 이 친구는 당연히 더 느리다.. 그래도 기다려줄만 함.

이것보다 더 느린 LW-K200 은 대체 어느정도일까...


컷팅 되는 부분이 생각보다 깊숙히라서 잘린 라벨이 튕겨나오지 않는다 (OK730은 툭 하고 라벨이 튀어나가 버림)

튕겨나오는걸 싫어하는 사람도 있던데,, 난 뭔가 튕겨 나오는게 더 좋은 듯.

좁은 여백을 설정해서 앞 쪽 여백이 잘릴 경우 잘린 부분이 안쪽에 갇혀서 안 나오는 문제도 있고...


당연하지만 카트리지도 따로 사야하고.. 막 사모으기에는 부담되게 비싸다.

그래도 한번 사놓으면 오래오래 쓰니까... 생각날때마다 하나씩 사모으면 부담이 덜 될 듯.

개인적으로는 9mm, 12mm 각 흰색, 투명 하나씩 있으면 기본기로는 충분한 것 같다.

+ Recent posts