2023-02-25
파인더에서 숨김 파일이 보이지 않아 불편해 변경했다.
$ defaults write com.apple.finder AppleShowAllFiles -bool true;killall Finder
macOS에서는 프로그램 설정을 속성 목록(plist)을 편집해서 바꿀 수 있다. plist
파일을 찾아서 열어 해당 속성을 바꾸거나 셸에서 defaults
프로그램을 사용해 속성을 변경할 수 있다.
참고
2023-01-29
winget을 사용하면 windows에서 커맨드라인으로 프로그램을 설치할 수 있다. apt-get
, brew
처럼 손쉬운 설치가 windows에서 가능하다. 회사에서 코드 사이닝을 안 한 powershell 스크립트 파일을 사용 못 하게 도메인 정책으로 막아놓곤 해서 사용 못하던 chocolatey 대신 사용할 수 있다.
C:\> winget install -e --id JetBrains.dotUltimate
dotUltimate를 설치하면 너무 조용히 설치가 끝난다. 이렇게 조용할 리가? 설치 프로그램을 찾아보니 하나도 설치가 안 됐다.
C:\> winget install -e --id JetBrains.dotUltimate --override "/SpecificProductNames=ReSharper;dotTrace;dotMemory;dotCover;dotPeek;Rider /Silent=True /VsVersion=17.0"
JetBrains.dotUltimate.installer.yaml 파일을 참고해 --override
옵션을 사용해 변경했다. 디폴트로 설정한 VsVersion
이 안 맞아서 설치가 제대로 안 됐던 것 같다. 17.0
으로 변경하고 설치할 프로그램을 지정하니 잘 된다.
2022-11-19
마이크로소프트에서 만든 윈도우 터미널(windows terminal)은 셸(shell)을 호스팅하는 애플리케이션(application)이다. 즉 이 애플리케이션을 사용해 cmd, bash, powershell 등을 띄울 수 있다. 화면 분할도 지원해서 그동안 사용하던 ConEmu를 버리고 윈도우 터미널을 사용하고 있다.
C:\> winget install --id=Microsoft.WindowsTerminal -e
윈도우 패키지 매니저인 winget을 사용해 간단히 설치할 수 있다.
Win+R wt
로 실행할 수 있다. 실행 파일 이름이 wt.exe
인 걸 몰라서 한참 찾았다.
이제 git bash를 세팅할 차례다. C-, 를 눌러 설정창을 연 후 ‘+ 새 프로필 추가’ 를 클릭한다.
- 명령줄: “C:\git-sdk-64\git-cmd.exe” –no-cd –command=usr/bin/bash.exe -l -i
- 시작 디렉터리:
%USERPROFILE%
이제 윈도우 터미널에서도 git bash를 사용할 수 있다.
2022-10-16
case val do
200 -> true
404 -> true
_ -> false
end
case
문에서 200 이거나 404일 때, 검사를 한 번에 하려면 어떻게 하면 될까?
case val do
n when n in [200, 400] -> true
_ -> false
end
case val do
n when n == 200 or n == 400 -> true
_ -> false
end
when
키워드로 가드(guard)를 사용하면 된다. 다만 이걸 쓰기 위해서는 심볼을 바인딩하고 이 심볼을 when
으로 검사해야 한다. 위 코드에서 바인딩한 심볼이 n
이다. or
연산자를 써도 되고 in
연산자를 써도 된다.
참고
2022-09-17
사내 linux 가상 머신 인스턴스에 gitlab runner를 설치하려고 했을 때였던 걸로 기억한다.
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" \
| sudo bash
gitlab 저장소를 추가한다. 이렇게 해야 이후에 업데이트도 쉽게 따라갈 수 있다. sudo apt-get update
명령만 내리면 최신 버전 정보를 가져오기 때문이다.
하지만 저 명령이 이상하게 동작하지 않는다. 특정 단계에서 시간이 오래 걸리며 시간 초과 에러가 난다. 스크립트 파일을 직접 다운로드 받아서 어디서 문제가 나는지 하나씩 실행해봤다. 아무런 문제 없이 잘 실행된다. 과연 뭐가 문제일까?
환경 변수 문제였다. 프록시 서버를 통해 인터넷 접근이 가능했는데, 그 설정을 https_proxy
, http_proxy
환경 변수로 하고 있었다. sudo bash
명령은 환경 변수 유지 없이 superuser로 bash를 실행한다. 그래서 프록시 서버 세팅이 안 되니 인터넷에 접근해 파일을 받아오는 스크립트에서 시간 초과 에러가 발생한다.
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" \
| sudo -E bash
-E
옵션을 사용하면 환경 변수를 유지한다. sudo bash
를 sudo -E bash
로 바꿔주면 잘 동작한다.
링크
2022-07-16
defaults write -g ApplePressAndHoldEnabled -bool false
Android Studio IDE의 vim 플러그인 ideavim을 설치해서 사용하다 보니 키 반복 입력을 활성화하는 방법을 알려주더라. 친절하다. 터미널을 열어서 위 명령어를 입력하면 된다.
링크
2022-06-25
‘에어팟(AirPods, 2019) 2세대‘를 잘 사용하고 있다. iOS, iPadOS 14 이후로 지원되는 자동 전환을 켜서 사용하고 있었다. macOS도 지원돼서 기기간 연결이 잘 넘어간다. macOS에서 음악을 듣다가 별도 작업 없이 iOS로 듀오링고를 켜서 영어 공부를 하면 에어팟이 iOS에 연결이 되는 식으로 동작한다.
하지만 대부분의 부모가 그렇듯이 내 것인 줄 알았던 아이패드(iPad)가 자녀 교육용으로 넘어갈 때, 문제가 생긴다. 한창 코로나19 때문에 원격 수업을 많이 할 때, 문제가 발생했다. 화장실에 가려고 딸기부엉이 방 근처로 가면 원격 수업을 하는 아이패드에 내 에어팟이 연결되곤 했다. 방에선 갑자기 아이패드에서 소리가 안 들린다며 나를 찾기 시작한다.

에어팟이 연결된 상태에서 블루투스(bluetooth) 설정으로 들어간다. 연결된 에어팟 옆에 보이는 i 버튼을 누르면 상세 설정에 들어갈 수 있다. 거기서 연결 메뉴를 볼 수 있는데, 자동 연결이 아닌 마지막으로 연결된 기기일 때만 연결되는 옵션을 선택한다. 이제는 소유권이 애매해진 아이패드에서는 자동연결을 끄고 사용 하고 있다.
2022-05-01

시스템 환경설정 > 사용자 및 그룹 > 로그인 항목
목록에 보이면 클릭한 후 밑에 -
버튼을 눌러서 제거하면 된다.
macOS steam 프로그램에 환경 설정 > 인터페이스 > 컴퓨터를 시작할 때 Steam 자동 실행
옵션이 있지만 동작하지 않는다. Disable Steam auto start on Mac 글을 참고해서 자동 실행을 껐다.
2022-04-10

macOS 업데이트가 실패했다. 복구 모드로 와이파이를 잡고 운영체제를 다운로드받아 설치하는 것도 실패했다. 그냥 로컬에 저장된 복구 OS를 설치할걸. 그걸로 다시 시도해본다. 또 실패했다. USB에 macOS를 설치해 이걸로 부팅해서 설치해야겠다. 보안 칩이라니 있으니 좋겠지 하며 흘려들었던 T2 보안 칩이 부팅을 막는다.
한번 고생을 한 후에는 macOS 업데이트를 할 때, 항상 USB로 부팅할 수 있게 만들어 놓는다.
- Mac을 켠 다음 Apple 로고가 표시되면 곧바로 command(⌘)-R 키를 길게 누릅니다. Mac이 macOS 복구로 시동됩니다.
- 암호를 알고 있는 사용자를 선택하라는 메시지가 표시되면 사용자를 선택하고 ‘다음’을 클릭한 후 관리자 암호를 입력합니다.
- macOS 유틸리티 윈도우가 나타나면 메뉴 막대에서 유틸리티 > 시동 보안 유틸리티를 선택합니다.
- 인증하라는 메시지가 나타나면 ‘macOS 암호 입력’을 클릭한 다음 관리자 계정을 선택하고 해당 암호를 입력합니다.
- Apple T2 보안 칩이 탑재된 Mac의 시동 보안 유틸리티에 관하여
외부 또는 제거 가능한 미디어에서 시동 허용
라디오 버튼을 체크하면 된다.
2022-03-09
iex> match?(%{a: _}, %{a: 1, b: 2})
true
iex> match?(%{c: _}, %{a: 1, b: 2})
false
match?/2 매크로는 패턴에 매칭(matching)하는지를 boolean으로 리턴한다.
iex> match?(%{a: c}, %{a: 1, b: 2})
warning: variable "c" is unused (if the variable is not meant to be used, prefix it with an underscore)
iex:17
true
iex> c
c
** (CompileError) iex:18: undefined function c/0
매크로 안에서 심볼에 값을 바인딩 되지 않는다. context를 공유하지 않는 macro hygiene이 적용된다.
iex> match?(%{a: x} when x > 2, %{a: 4, c: 2})
true
iex> match?(%{a: x} when x < 2, %{a: 4, c: 2})
false
안에서 쓸 수 없을 것 같은 가드 절(guard clause)도 사용할 수 있다.
그래서? 단독으로 사용할 때는 시큰둥해진다. 여기에 다른 함수를 끼얹는다면?
iex> list = [a: 1, b: 2, a: 3]
[a: 1, b: 2, a: 3]
iex> Enum.filter(list, &match?({:a, _}, &1))
[a: 1, a: 3]
iex> Enum.any?(list, &match?({_, 3}, &1))
true
iex> Enum.all?(list, &match?({_, 3}, &1))
false
iex> Enum.find(list, &match?({:a, x} when x > 2, &1))
{:a, 3}
Enum.filter/2, Enum.any?/2, Enum.all?/2, Enum.find/3 등 술어(predicate)를 인자로 받는 모든 함수에 편하게 쓸 수 있다.
2022-02-20
닌텐도 스위치와 컴퓨터를 USB 케이블로 연결한다. 바로 인식하지 않는데, 별도 프로그램이 필요하다. 닌텐도 스위치 OS가 안드로이드인가보다. Android File Transfer 프로그램을 설치해야 한다.
닌텐도 스위치에서 설정 > 데이터 관리 > 화면 사진과 동영상 관리 > USB를 연결하여 컴퓨터에 복사
메뉴를 선택한다. 그 후 설치한 Android File Transfer 프로그램을 실행하면 닌텐도 스위치 디렉터리가 보인다.
macOS에서 테스트했다. windows에서도 잘 동작하지 싶다.
2022-02-13

apple 단축어 앱을 사용하면 wifi 접속 QR 코드를 만들 수 있다.
- 텍스트:
WIFI:S:와이파이이름;T:WPA;P:패스워드;;
- QR 코드 생성
- 훑어보기
QR 코드를 찍으면 wifi 접속할 것인지 묻고 접속한다. 아이폰, 갤럭시 상관없이 동작한다. 둘 다 동작한다니 표준 스팩 같은 게 있는 게 아닐까? 표준 문서는 못 찾았다. 대신 email, vCard, sms, facetime, map, calendar event, wifi network 설정이 적힌 barcode 스캐닝 라이브러리 ZXing의 Barcode Contents 문서를 찾았다.
만드는 법을 설명한 youtube를 보고 따라서 액자를 만들어봤다. 액자가 구려서 안 예쁘다. airbnb 숙소를 운영하는 것도 아니어서 사진만 찍고 폐기했다. 친척이 놀러 왔을 때, wifi 비번을 물어보면 apple 단축어 앱으로 만든 QR 코드를 보여주는 거로 충분할 것 같다. 그래도 찍기만 했던 QR 코드를 만드니 재미있었다.
PS: 사진에 찍힌 QR 코드는 와이파이 SSID와 패스워드는 임의로 만든 거니 스캔해도 쓸모가 없다.
참고
2021-12-11
"+p
커맨드로 OS 클립보드 내용을 붙일 수 있다.
커맨드를 분해하면 다음과 같다.
- ”
- +
- p
- 붙이기(paste) 동작. 복사하려면 y 키를 사용하면 된다.
set clipboard=unnamed
이 세팅으로 OS 클립보드를 같이 사용할 수 있지만 기본 세팅으로 놔두고 쓰고 있다. emacs는 OS 클립보드를 구분하지 않는데, 이참에 vim도 바꿀까 싶기는 하다.
참고
2021-11-24
map = for i <- 1..100, into: %{}, do: {i, Enum.random([false, true])}
키는 숫자, 값은 boolean인 map을 만든다. %{1 => true, 2 => false}
이런 식으로 만들어진 map이다.
value가 true인 key, value 쌍을 뽑아서 map을 만들려면 어떻게 하면 될까? Enum.filter/2
함수를 써서 value가 true인 key, value 쌍을 걸러내 보자.
map |> Enum.filter(&match?({_, true}, &1))
[
{12, true},
{38, true},
{93, true},
{53, true},
{46, true},
{23, true},
{80, true},
{96, true},
{75, ...},
{...},
...
]
Enum.filter/2
리턴 값이 list라서 map이 아닌 list가 나온다.
map |> Enum.filter(&match?({_, true}, &1)) |> Map.new()
%{
48 => true,
62 => true,
39 => true,
83 => true,
63 => true,
34 => true,
68 => true,
...
}
map에 filter를 적용하려면 list를 리턴하는 Enum.filter/2
함수 다음에 Map.new/1
함수를 사용해 list를 map으로 만들어야 한다.
erlang도 이럴까? erlang 라이브러리에는 둘러가지 않고 한방에 가는 maps.filter/2 함수가 있다.
:maps.filter(fn _, value -> value end, map)
%{
48 => true,
62 => true,
39 => true,
83 => true,
63 => true,
34 => true,
...
}
pipe 연산자에 친화적이지 않다. map을 첫 번째 인자로 받지 않아 마음에 안 들지만 잘 동작한다. 중간에 list를 생성하지 않아 훨씬 더 빠르다.
다행히 elixir 1.13.0에 추가된다. Map.filter/2
함수뿐만 아니라 Map.map/2
함수도 추가된다.
버전업이 곤란하면 구현 함수를 복사해서 사용하면 된다. 단순 :maps.filter/2
함수 호출인가 싶어서 코드를 살펴봤다. :maps.iterator/1, :maps.next/1 함수로 반복자(iterator)를 만들어서 요소들을 차례로 순회하며 filter 함수를 호출한다. 생각해보니 map 요소에 접근하는 함수 시그니처(signature)도 다르다. elixir에서는 tuple을 인자로 받는데, erlang에선 2개의 인자를 받는다. 그래서 직접 순회하며 filter 함수를 호출하게 했다.
참고
2021-10-13
defp ask_and_schedule(producers, from) do
case producers do
%{^from => {pending, interval}} ->
# ...
%{} ->
# ...
end
end
GenStage 코드를 보다가 발견했다. Map.get(producers, from)
혹은 producers[from]
으로 값을 가져오는 게 아니라 패턴 매칭을 사용한다.
Map.get/3 함수보다 빠를까?
defmodule Map do
def get(map, key, default \\ nil) do
case map do
%{^key => value} ->
value
%{} ->
default
other ->
:erlang.error({:badmap, other}, [map, key, default])
end
end
end
당연. 빠를 수밖에 없다. Map.get/3
함수를 패턴 매칭으로 구현했다. 패턴 매칭이 더 근본이다. 하지만 크게 의미있는 속도 차이는 없으니 가독성을 보고 선택하면 된다.
2021-09-29
EDATE(DATE(1969,7,20), 1)
EDATE(B1,-3)
인자로 시작일과 개월 수를 받는다. 달마다 기록하는 항목이 있을 때, 편리하게 사용할 수 있다.
PS: 앞에 e는 무슨 의미일까?
2021-07-11
UTF-8 인코딩으로 출력하는 한글이 깨져서 한참 찾았다. locale 명령으로 인코딩 설정을 봐도 이상한 게 없다. 아~ windows에서 실행하는 거였지.
Settings... > Startup > Environment
chcp 65001
ConEnum 설정에서 환경 변수를 세팅하는 곳이 있다. 추가하니 잘 나온다. 이런 설정이 나만 필요한 게 아니었는지 Environment에 이런 걸 설정할 수 있다며 든 예제 중에 chcp 프로그램을 사용한 인코딩 변경이 있다.
2021-06-09
프로그래밍할 때는 숫자를 인자로 넣어서 pid(프로세스 아이디)를 만들 일이 없지만, elixir 대화형 셸(iex, elixir’s interactive shell)을 사용해 프로세스에 직접 메시지를 보낼 때, 가끔 사용한다.
#PID<0.101.0>
이런 식으로 출력되는 로그를 보고 pid를 만들어서 메시지를 보내야 하는데, pid를 어떻게 만들면 될까?
iex> pid("0.101.0")
#PID<0.101.0>
iex> pid(0, 101, 0)
#PID<0.101.0>
iex> :c.pid(0, 101, 0)
#PID<0.101.0>
IEx.Helpers.pid/1, IEx.Helpers.pid/3 함수를 사용하거나 :c.pid/3 erlang 함수를 사용하면 된다. common interface module 이름을 c
로 짓다니 과감하시다.
참고
2021-05-16
때가 어느 때인데, EUC-KR 인코딩을 UTF-8 인코딩으로 변환하는 걸 찾아봐야 하는가? 대부분 UTF-8
인코딩을 사용하고 있지만 많은 레거시 시스템은 아직도 EUC-KR
인코딩을 사용하고 있다.
:iconv.convert("euc-kr", "utf-8", content)
iconv 라이브러리를 설치 후 :iconv.convert/3
함수를 사용한다. iconv 프로그램을 사용하기 때문에 시스템에 설치되어 있어야 한다. macOS에 설치되어 있어서 따로 설치는 하지 않았다. windows에서 프로그램을 돌린다면? 당연히 설치해야 한다.
참고
2021-05-02
is_atom(nil)
값은 뭘까? is_atom/1 함수는 인자가 atom 일 때, true를 리턴하고 아니면 false를 리턴한다.
true
true가 나온다. nil은 atom이기 때문이다.
iex> is_atom(true)
true
iex> is_atom(false)
true
true와 false도 마찬가지다. nil, true, false 모두 atom이다.
iex> nil == :nil
true
iex> true == :true
true
iex> false == :false
true
Elixir allows you to skip the leading : for the atoms false, true and nil.
- Basic types
nil, true, false는 atom인데도 :
문자를 빼고 쓸 수 있게 편의 문법(syntactic sugar)으로 지원한다.
atom이기 때문에 guard를 쓸 때, 주의해야 한다.
def some_function(param) when is_atom(param), do: # do somthing
이런 함수를 만들면 param으로 nil과 true, false도 들어올 수 있다. 만약 이걸 의도하지 않았다면
def some_function(param) when is_atom(param) and
not is_boolean(param) and
not is_nil(param),
do: # do somthing
이렇게 boolean과 nil을 guard로 거르게 한다던지
def some_function(param) when is_boolean(param) , do: # nothing
def some_function(param) when is_nil(param), do: # nothing
def some_function(param) when is_atom(param), do: # do somthing
먼저 nil과 boolean 일때 매칭해서 처리하도록 코드를 짜야 한다.
참고