Homebrew

소개

Homebrew는 macOS와 Linux에서 사용할 수 있는 패키지 매니저다. 명령어로 쉽게 패키지를 설치, 삭제, 업데이트 할 수 있다. 여기서 말하는 패키지는 cli 프로그램, GUI 프로그램, 폰트, 라이브러리 등을 말한다. curl, wget 같은 cli 프로그램은 물론이고 .dmg, .pkg로 배포하는 macOS용 GUI 앱과 폰트까지 설치할 수 있다. mas 패키지를 설치하면 Apple App Store에 있는 앱도 설치할 수 있다.

다음은 Homebrew로 패키지를 사용하는 명령어 예시다. 설명이 필요없을 정도로 직관적이다.

$ brew list  # Homebrew로 설치한 패키지 리스트

$ brew search wget
$ brew info wget

$ brew update
$ brew outdated
$ brew upgrade  # 전부 업그레이드
$ brew upgrade <formula>  # 특정 앱만 업그레이드

# 업데이트/업그레이드를 하고 싶지 않을 때
$ brew pin <formula>
$ brew unpin <formula>

$ brew install wget
$ brew uninstall wget

$ brew install --cask aldente
$ brew uninstall aldente

updateupgrade는 헷갈릴 수 있으므로 설명한다. - update: - Homebrew의 패키지 목록(레시피) 갱신한다. - 새로운 패키지나 버전 정보를 가져온다. - 설치된 패키지를 업데이트하지 않는다. - upgrade: - 설치된 소프트웨어를 새 버전으로 업그레이드한다. - --dry-run 옵션을 사용하면 실제로 업그레이드 하지 않고, 업그레이드될 패키지 정보만 볼 수 있다.

Homebrew로 설치한 패키지는 일반 텍스트(plain text) 파일로 저장할 수 있다. 명령어 한 번만 실행하면 이 파일에 적힌 패키지를 한 번에 설치할 수 있기 때문에 개발자가 아니더라도 꼭 Homebrew를 사용하기 바란다.

다음은 설치된 패키지를 저장한 Brewfile 파일 중 일부이다.

Brewfile
brew "curl"
brew "wget"
cask "font-jetbrains-mono"
cask "ghostty"
mas "KakaoTalk", id: 869223134
mas "Movist", id: 461788075
vscode "ms-python.python"
vscode "vscodevim.vim"
노트

Homebrew는 독특한 용어를 사용하는데, 앱 이름처럼 술과 관련됐다. 개발자 Max Howell은 Homebrew 프로젝트가 이렇게까지 유명해질지 몰랐다고 한다. 이 프로젝트에서 사용하는 용어는 Homebrew terminology를 참고한다.

설치

홈페이지에 나와있는대로 다음 명령으로 간단하게 설치할 수 있다.

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Homebrew는 Xcode Command Line Tools가 필요한데, 설치되어 있지 않다면 자동으로 설치한다. 이미 설치됐다면 Homebrew 자체는 금방 설치된다.

노트Xcode Command Line Tools

개발에 필요한 기본 명령행 도구 모음이다. 용량이 약 900MB으로 생각보다 크다. Xcode Command Line Tools만 따로 설치하려면 xcode-select --install 명령을 실행한다.

Hombrew는 brew upgrade를 실행할 때 오래된 버전을 삭제한다. 그리고 30일마다 cleanup을 실행한다. 막으려면 이렇게 하면 된다.

export HOMEBREW_NO_INSTALL_CLEANUP=1  # 일괄 차단
export HOMEBREW_NO_CLEANUP_FORMULAE=foo,bar  # foo, bar만 차단

Homebrew는 다운로드한 패키지를 캐쉬하는데 이 명령으로 경로를 알 수 있다.

$ brew --cache
/Users/docsuri/Library/Caches/Homebrew

Formulae

소스코드를 다운로드해서 빌드하거나, 이미 빌드된 바이너리를 다운로드해서 설치할 수 있게 정의한 Ruby 스크립트다. cURL, Wget 같은 명령형 프로그램들이나 libpng 같은 라이브러리 등을 설치할 수 있다. https://formulae.brew.sh/formula/에서 Formula 패키지 리스트를 볼 수 있다.

소스코드를 빌드하기 위해 Xcode Command Line Tools가 필요하다. 하지만 패키지 설치 속도를 빠르게 하기 위해 아키텍처와 OS별로 미리 빌드해 둔 바이너리 파일을 직접 다운로드한다. 설치 방법 특성상 대부분 오픈소스이다.

다음은 wget.rb 파일 중 일부다.

여기서 desc, homepage, url 등을 스탄자라고 한다. 스탄자는 섹션 8.1 에서 설명한다.

wget.rb
class Wget < Formula
  desc "Internet file retriever"
  homepage "https://www.gnu.org/software/wget/"
  url "https://ftpmirror.gnu.org/gnu/wget/wget-1.25.0.tar.gz"
  sha256 "766e48423e79359ea31e41db9e5c289675947a7fcf2efdcedb726ac9d0da3784"
  license "GPL-3.0-or-later"

  no_autobump!  

  bottle do
    sha256    "8cbb5d277cd207e543c9b2e75953e89c7cc89105b2322f3ce652616c5d0f62fe"
    sha256  "a93dd95c5d63036e026b526e000d33fae7fb44d9a8fda5afc89bff112438c6b3"
    sha256   "4d180cd4ead91a34e2c2672189fc366b87ae86e6caa3acbf4845b272f57c859a"
    sha256  "7fce09705a52a2aff61c4bdd81b9d2a1a110539718ded2ad45562254ef0f5c22"
    sha256         "5650778a8e7a60c2dea9412dd21d2f5e8ff4f224dbefbdf54924b99012062edc"
    sha256        "78cee523a9b58a7b824b51767935f68c9838e9f673e70d001982858001e766ff"
    sha256    "2f06529fc47fa99e9d4a5ebd19f25c046dda236278c7c5979e080ad7e5387236"
    sha256   "ab5f3c1c60bef4e2a4781e9b29af8afb48ead837136c419edd7febdf44b59058"
  end

이런 Formula 패키지는 별다른 옵션 없이 brew install <package> 명령으로 설치하면 된다. url 스탄자 바로 아래 sha256 스탄자에 SHA256 해쉬가 있는데, url의 파일을 다운로드했을 때 이를 사용해서 검증한다.

히지만 실제로는 설치를 빠르게 하기 위해 아키텍처와 OS별로 미리 빌드해 둔 바이너리 파일을 다운로드한다. bottle 스탄자에 아키텍처별 sha256 해쉬가 미리 빌드한 바이너리별 해쉬이다. 이런 바이너리 파일은 url에 있는 주소에서 다운로드하는 게 아니라 Homebrew가 관리하는 ghcr.io에서 다운로드한다. 따라서 url 스탄자 아래 있는 sha256url에 있는 파일에 대한 해쉬이고, bottle 스탄자에 있는 SHA256은 ghcr.io에서 다운로드한 각 바이너리 파일에 대한 해쉬다.

미리 빌드한 바이너리 파일의 URL은 brew install <package>로 패키지를 설치할 때 볼 수 있지만, 권한 때문에 Homebrew를 통해서만 접근할 수 있다. 웹브라우저나 curl, wget 등을 통해 시도하면 다음과 같은 에러만 응답한다.

wget의 Sequoia 바이너리를 다운로드 해보자. 다음과 같은 에러 응답만 받는다.

{
  "errors": [
    {
      "code": "UNAUTHORIZED",
      "message": "authentication required"
    }
  ]
}

단일 bottle

cowsay라는 프로그램이 있다. 이런 기능을 한다.

cowsay "Hello, Homebrew"
_________________
< Hello, Homebrew >
 -----------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

cowsay.rb 파일을 보자.

class Cowsay < Formula
  desc "Apjanke's fork of the classic cowsay project"
  homepage "https://cowsay.diamonds"
  url "https://github.com/cowsay-org/cowsay/archive/refs/tags/v3.8.4.tar.gz"
  sha256 "c15bc10712835d3a9bcda780dc9453362567bf48d1185905dc7ef2334d79aadd"
  license "GPL-3.0-only"
  head "https://github.com/cowsay-org/cowsay.git",  "main"

  no_autobump!  

  bottle do
    sha256  ,  "345e99255a69e9cb188a5a8e6bd8e6f50c334830c8a72877fc6b504c95e5cbd1"
  end

  def install
    system "make", "install", "prefix=#{prefix}"
  end

  test do
    output = shell_output("#{bin}/cowsay moo")
    assert_match "moo", output  # bubble
    assert_match "^__^", output # cow
  end
end

bottle을 제공하긴 하는데, OS나 아키텍처별로 제공하지 않고 all 하나만 제공한다. 이는 cowsay 파일이 실제로는 바이너리가 아니고 Perl 스크립트이기 때문이다.

cowsay
#!/usr/bin/env perl

##
## Cowsay
##

use Cwd 'abs_path';
use File::Basename;
use File::Find;
use Getopt::Std;
use Text::Tabs qw(expand);
use Text::Wrap qw(wrap fill $columns);

$Getopt::Std::STANDARD_HELP_VERSION = 1;
...  생략

build-from-source

Homebrew는 가능한 bottle을 제공한다. 만약 소스로 직접 빌드하고 싶다면 다음 -s 옵션을 사용한다.

$ brew install -s w3m
==> Installing w3m dependency: bdw-gc
==> Downloading https://ghcr.io/v2/homebrew/core/bdw-gc/manifests/8.2.8
Already downloaded: /Users/docsuri/Library/Caches/Homebrew/downloads/89bb7c10cfa3482949e74e3e7687110dada74da8f2f584bd385aa97c1cb30c96--bdw-gc-8.2.8.bottle_manifest.json
==> Pouring bdw-gc--8.2.8.arm64_sequoia.bottle.tar.gz
🍺  /opt/homebrew/Cellar/bdw-gc/8.2.8: 82 files, 1.8MB
==> Patching
==> Applying 0002-CVE-2023-4255.patch
==> ./configure --disable-image --with-ssl=/opt/homebrew/opt/openssl@3
==> make install
🍺  /opt/homebrew/Cellar/w3m/0.5.3-git20230121: 30 files, 1.9MB, built in 15 seconds

configure, make install 등의 명령을 사용해서 빌드하는 것을 알 수 있다.

Casks

GUI 애플리케이션, 폰트, 플러그인 등의 바이너리를 설치할 수 있게 정의한 Ruby 스크립트다. Google Chrome 같은 GUI 앱이나 JetBrains Mono 같은 폰트를 설치할 때 사용한다. https://formulae.brew.sh/cask/에 Homebrew가 제공하는 Cask 패키지들을 볼 수 있다.

예전에는 cask 패키지를 먼저 설치한 후 --cask 옵션으로 Cask 패키지를 설치해야 했지만 지금은 --cask 옵션이 필수는 아니다. 하지만 관행적으로 여전히 사용한다.

$ brew install --cask pycharm
$ brew install pycharm  # 이것도 가능하다.

mas

mas는 명령어로 맥 앱 스토어에 있는 앱을 설치할 수 있게 해주는 인터페이스다. 이 명령을 사용하려면 먼저 mas 패키지를 설치해야 한다.

$ brew install mas

이제부터는 mas 명령을 사용할 수 있다. 이렇게 사용하지 않는다.

$ brew intall --mas kakaotalk  # ❌

패키지 이름으로 찾으면 엉뚱한 것들도 함께 나오는데 대부분 맨 처음 것이 맞다. 이 때 패키지 이름이 아닌 ID로 설치하면 된다.

$ mas search kakaotalk
   869223134  KakaoTalk                       (25.8.0)
   462054704  Microsoft Word                  (16.101.2)
   462058435  Microsoft Excel                 (16.101.2)
  1444383602  Goodnotes: AI 노트, 문서, PDF       (7.0.3)
   462062816  Microsoft PowerPoint            (16.101.2)
$ mas install 869223134  # KakaoTalk의 id

저 숫자는 KakaoTalk의 앱 스토어 URL https://apps.apple.com/kr/app/kakaotalk/id869223134?l=en-GB&mt=12에 있는 id와 같다.

그래서 id 중 일부를 알고 있다면 이렇게 검색하고 바로 설치할 수도 있다.

$ mas search pdfgear | grep 8692 | awk '{print $1}' | xargs mas install
# 또는 좀 더 확실하게
$ mas search pdfgear | grep -E '^[[:space:]]*8692' | awk '{print $1}' | xargs mas install

mas list 명령으로 mas로 설치한 패키지 리스트를 볼 수 있다.

$ mas list
869223134   KakaoTalk       (25.8.0)
461788075   Movist          (2.12.1)
1575283633  PDF Translator  (6.0.2)
1295203466  Windows App     (11.2.4)

brew 명령과 비슷하게 oudated로 새 버전이 있는지 확인할 수 있다.

$ mas outdated

Bundle

위에서 설명했듯이 Homebrew로 설치한 패키지 리스트를 일반텍스트파일로 저장할 수 있다. 자세한 건 Homebrew Bundle, brew bundle and Brewfile를 참고한다.

먼저 Homebrew로 설치한 패키지 리스트를 보자.

$ brew bundle list --all  # 모든 패키지
$ brew bundle list  # --formula 생략
$ brew bundle list --formula #
$ brew bundle list --cask
$ brew bundle list --mas
$ brew bundle list --tap
$ brew bundle list --taps  # --tap과 같다
$ brew bundle list --vscode

예시와 같이 Visual Studio Code Extension까지 포함한다.

덤프

dump 명령으로 설치한 패키지 리스트를 파일로 저장해보자.

$ brew bundle dump  # 파일명을 Brewfile로 저장
$ brew bundle dump --force
$ brew bundle dump --file=MyBrewFile
$ brew bundle dump --cask --file=CasksBrewFile
$ brew bundle dump --mas --file=MasBrewFile
$ brew bundle dump --vscode --file=VSCodeBrewfile

설치

이렇게 저장한 파일을 이용해서 패키지를 다시 설치할 때는 이 명령을 실행한다.

$ brew bundle  # `install`을 생략해도 된다
$ brew bundle install

Tap

Taps (Third-Party Repositories)는 Homebrew가 설치할 수 있는 formula, cask, font 등을 담고 있는 저장소다. Homebrew 공식 저장소인 core, cask 같은 저장소를 추가해서, 공식 저장소가 제공하지 않는 패키지나 폰트 등을 Homebrew로 관리할 수 있다.

현재 tap을 보는 방법은 간단하다.

$ brew tap

현재는 아무 사설 저장소를 등록하지 않았다.

Tap 추가

써드파티 Tap을 추가해보자. 필자가 만든 Tap인 https://github.com/docsuri/homebrew-cask를 이용해보자. Homebrew는 Github을 기본 저장소로 인식한다. 따라서 brew tap <user>/<repo>을 실행하면 Homebrew는 자동으로 gihhub.com//homebrew- URL으로 인식한다. 만약 GitHub이 아니라면 이렇게 URL을 명시해야 한다. 이 때 URL은 HTTP(S), SSH 등 Git이 이해하는 프로토콜이면 된다.

$ brew tap <user>/<repo> <URL>

실제 탭을 추가해보자.

# 저장소 이름 중 'homebrew-'는 생략한다.
$ brew tap docsuri/cask
==> Tapping docsuri/cask
Cloning into '/opt/homebrew/Library/Taps/docsuri/homebrew-cask'...
remote: Enumerating objects: 23, done.
remote: Counting objects: 100% (23/23), done.
remote: Compressing objects: 100% (18/18), done.
remote: Total 23 (delta 3), reused 23 (delta 3), pack-reused 0 (from 0)
Receiving objects: 100% (23/23), done.
Resolving deltas: 100% (3/3), done.
Tapped 2 casks (17 files, 13.9KB).

위에서 보는 바와 같이 $(brew --repository)/Library/Taps에 저장소를 복제한다.

$ brew tap
docsuri/cask
$ ls $(brew --repository)/Library/Taps
docsuri

tap-info 명령을 실행하면 저장소에 대한 정보를 볼 수 있다.

$ brew tap-info docsuri/tap
docsuri/cask: Installed
2 casks
/opt/homebrew/Library/Taps/docsuri/homebrew-cask (17 files, 13.9KB)
From: https://github.com/docsuri/homebrew-cask
HEAD: 01085899e214713f42f187f417b2ca97fd2b79f8
last commit: 3 hours ago

2개의 Cask 패키지가 있는 것을 알 수 있다. 이제 이 저장소에서 제공하는 패키지를 brew 명령으로 관리할 수 있다.

docuri/cask Tap에서 제공하는 패키지는 search <user>/<repo name> 명령으로 볼 수 있다.

$ brew search docsuri/cask
==> Casks
docsuri/cask/font-hcr-lvt                                                  docsuri/cask/font-monoplex-kr

패키지 관리 방식은 공식 저장소의 패키지와 동일하다.

$ brew install --cask font-monoplex-kr
==> Downloading https://github.com/y-kim/monoplex/releases/download/v0.0.2/MonoplexKR-v0.0.2.zip
Already downloaded: /Users/docsuri/Library/Caches/Homebrew/downloads/a2d809061fe5bf8a7046c7d54a3ef1899e5a005ff37c52c83529a504aab0cc9b--MonoplexKR-v0.0.2.zip
==> Installing Cask font-monoplex-kr
... 생략 ...
🍺  font-monoplex-kr was successfully installed!
==> No outdated dependents to upgrade!
노트

패키지 이름이 Homebrew의 패키지와 같다면 brew install <user>/<repo>/<package> 으로 설치한다.

Tap 삭제

써드파티 Tap을 삭제할 때는 untap 명령을 사용한다.

$ brew untap docsuri/cask
Error: Refusing to untap docsuri/cask because it contains the following installed formulae or casks:
font-monoplex-kr

하지만 이 Tap에서 패키지를 설치했다면 위와 같이 에러가 발생한다. 삭제하려는 Tap에서 설치한 패키지를 모두 삭제한 후 untap 명령을 실행해야 한다.

$ brew uninstall font-monoplex-kr
$ brew untap docsuri/cask
Untapping docsuri/cask...
Untapped 2 casks (17 files, 13.9KB).

Tap 만들기

자세한 내용은 How to Create and Maintain a Tap를 참고한다.

터미널에서 다음 명령을 실행하자. 저장소 이름이 꼭 homebrew-tap일 필요는 없지만, homebrew-로 시작해야 한다.

$ brew tap-new $YOUR_GITHUB_USERNAME/homebrew-tap
Initialized empty Git repository in /opt/homebrew/Library/Taps/docsuri/homebrew-tap/.git/
[main (root-commit) e88077c] Create docsuri/tap tap
 3 files changed, 107 insertions(+)
 create mode 100644 .github/workflows/publish.yml
 create mode 100644 .github/workflows/tests.yml
 create mode 100644 README.md
==> Created docsuri/tap
/opt/homebrew/Library/Taps/docsuri/homebrew-tap

When a pull request making changes to a formula (or formulae) becomes green
(all checks passed), then you can publish the built bottles.
To do so, label your PR as `pr-pull` and the workflow will be triggered.

tap-new 명령으로만 Tap을 만들 필요는 없다. 하지만 이 명령을 이용하면 자동으로 Git 저장소로 만들고, github workflow를 만든다. 또한 GitHub에 푸쉬, 클론을 하지 않아도 바로 사용할 수 있다.

├── .github
   └── workflows
       ├── publish.yml
       └── tests.yml
└── Formula
└── README.md

아직 이 Tap을 등록하지 않았지만 brew tap 명령을 실행해보면 이미 이 Tap이 등록된 것을 볼 수 있다.

$ brew tap
docsuri/tap

여기서 Formula 디렉토리는 필요없으니 삭제한다.

$ rm -rf Formula

스탄자(Stanza)

스탄자Stanza는 Cask 정의 파일 내의 각 설정 항목을 말한다. 예컨데, version, sha256, url, app, font, zap 등이다. 이 때 각 순서가 중요한데, Stanza order를 참고한다.

필수 스탄자 항목은 다음과 같다:

  • version
  • sha256
  • url
  • name
  • desc
  • homepage
  • livecheck
  • depens_on: 실제로는 생략할 수 있다.
  • zap: 앱을 삭제할 때 완전히 삭제하기 위해 함께 삭제할 파일을 나열하기 위해 사용한다. 사용자가 명시적으로 --zap 옵션을 사용할 때 효과가 있다(예: $ brew uninstall --zap firefox)

Monoplex-kr 패키지 만들기

이 문서에서는 Monoplex KR 폰트를 패키지로 만드는 방법을 보인다. 이 폰트는 IBM Plex Mono에 IBM Plex Sans KR의 글자를 더해서 만든 고정폭 글꼴이다.

  1. create 명령으로 패키지를 만든다. 이 때 --cask 옵션을 사용해야 한다.

    $ brew create --cask https://github.com/y-kim/monoplex/releases/download/v0.0.2/MonoplexKR-v0.0.2.zip --tap docsuri/tap
  2. Cask name은 기본값(“[MonoplexKR-v0.0.2”) 대신 font-monoplex-kr을 입력한다.

  3. 에디터가 실행되면 메타데이터를 적절히 입력한다. 이 때 URL이 GitHub 이라면 version, sha256, url, name 등 일부 메타데이터는 자동으로 입력된다. 폰트는 OS나 아키텍트별로 바이너리를 따로 제공할 필요가 없기 때문에 bottle 블록은 필요없다.

  4. 파일을 저장하면 $(brew --repository)/Library/Taps/<user>/homebrew-<repo>/Casksfont-monoplex-kr.rb 파일이 만들어진다.

그러나 이렇게 만든 font-monoplex-kr.rb 파일은 폰트 패키지와 어울리지 않는다. depends_on, app, zap trash 등은 필요없고, font 아이템이 필요하다. 다음과 같이 작성한다.

Casks/font-monoplex-kr.rb
cask "font-monoplex-kr" do
  version "0.0.2"
  sha256 "174fc23f2be15ef6d4d818ac469073f2e512d961d238ed2acec0c3375fe5ae81"

  url "https://github.com/y-kim/monoplex/releases/download/v#{version}/MonoplexKR-v#{version}.zip"
  name "Monoplex KR"
  desc "IBM Plex Mono에 IBM Plex Sans KR을 더하여 코딩창과 터미널에서 로마자에 어울리는 한글을 보여주는 글꼴입니다."
  homepage "https://github.com/y-kim/monoplex"

  livecheck do
    url 
    strategy 
  end

  font "MonoplexKR/MonoplexKR-Bold.ttf"
  font "MonoplexKR/MonoplexKR-BoldItalic.ttf"
  font "MonoplexKR/MonoplexKR-ExtraLight.ttf"
  font "MonoplexKR/MonoplexKR-ExtraLightItalic.ttf"
  font "MonoplexKR/MonoplexKR-Italic.ttf"
  font "MonoplexKR/MonoplexKR-Light.ttf"
  font "MonoplexKR/MonoplexKR-LightItalic.ttf"
  font "MonoplexKR/MonoplexKR-Medium.ttf"
  font "MonoplexKR/MonoplexKR-MediumItalic.ttf"
  font "MonoplexKR/MonoplexKR-Regular.ttf"
  font "MonoplexKR/MonoplexKR-SemiBold.ttf"
  font "MonoplexKR/MonoplexKR-SemiBoldItalic.ttf"
  font "MonoplexKR/MonoplexKR-Text.ttf"
  font "MonoplexKR/MonoplexKR-TextItalic.ttf"
  font "MonoplexKR/MonoplexKR-Thin.ttf"
  font "MonoplexKR/MonoplexKR-ThinItalic.ttf"

end

sha256 해쉬값은 자동으로 처리된다. 만약 자동으로 안 되면 shasum -a 256 <filename> 명령을 실행한다.

livecheck는 패키지의 새로운 버전이 나왔는지 자동으로 확인하는 기능이다. 위와 같이 작성하면 GitHub 릴리스 페이지에서 최신 버전을 가져온다.

fontMonoplexKR-v0.0.2.zip 파일의 압축을 풀면 나오는 파일이다. 실제로 이 압축파일을 풀면 4개의 폴더가 생긴다. font-monoplex-kr 패키지는 MonoplexKR 디렉토리에 있는 폰트만 지원할 것이므로 위와 같이 작성했다.

스크립트 스타일 및 오류 수정

스크립트 작성이 끝나면 style 명령을 실행해서 새로 만든 cask 파일의 스타일을 검사하자.

$ brew style --fix --cask font-monoplex-kr

스타일 검사가 필수는 아니다. Tap으로 등록하고 패키지 설치하는데 아무 문제 없다. 하지만 GitHub에 푸쉬했을 때 tests.yml 액션에서 오류가 발생할 수 있다. desc 마지막이 마침표(.)로 끝나도 오류로 처리하기 때문에 style --fix 명령으로 수정하는 것이 좋다. 위에서 보여준 예를 따라했다면 두 가지 오류가 수정될 것이다.

반면 audit 검사는 반드시 하자. SHA256 해쉬, URL 등 실제 유효성을 검증한다.

$ brew audit --cask --new font-monoplex-kr
경고

만약 docsuri/cask 탭을 사용중이라면 untap 명령으로 탭을 삭제한다.

$ brew untap docsuri/cask

그렇지 않으면 docsuri/cask 탭에 이미 font-monoplex-kr 패키지가 있기 때문에 에러가 발생한다.

$ brew audit --cask --new font-monoplex-kr
Error: Cask font-monoplex-kr exists in multiple taps:
       * docsuri/cask/font-monoplex-kr
       * docsuri/tap/font-monoplex-kr

Please use the fully-qualified name (e.g. docsuri/tap/font-monoplex-kr) to refer to a specific Cask.

--tap <user>/<repo> 옵션으로 탭을 명시하면 해결할 수는 있다.

$ brew audit --cask --new --tap docsuri/tap font-monoplex-kr

하지만 패키지 이름은 가능한 중복되지 않게 만들자.

GitHub에 푸쉬하기

탭을 GitHub에 올려두면 재사용하거나 공유하기 좋다. 다음 명령으로 쉽게 할 수 있다.

$ brew install gh
$ gh auth login
$ gh repo create $YOUR_GITHUB_USERNAME/homebrew-tap --push --public --source "$(brew --repository $YOUR_GITHUB_USERNAME/homebrew-tap)"
$ git add *
$ git commit -m "added monoplex kr font"
$ git push

brew style, brew audit 명령으로 오류없이 스크립트를 작성했다면 GitHub 액션에서 테스트를 통과할 것이다.

Formula가 아니면 publish.yml 워크플로우는 필요없다. 이 워크플로우는 Formula 패키지의 bottle을 다운로드해서 GitHub 릴리즈로 배포할 때 사용하는데, Cask는 bottle을 제공하지 않기 때문에 publish.yml 워크플로우가 실행되지 않는다. 앞으로도 이 탭에서 Formula 패키지를 제공할 일이 없다면 publish.yml 파일은 삭제해도 된다.

Unicorn Pro 패키지 만들기

유니콘 Pro는 광고 차단 등을 해주는 유틸리티 프로그램이다. macOS 설치 후 꼭 설치하는 프로그램이라 내 탭에 추가한다.

$ cd $(brew --repository)/Library/Taps/<user>/homebrew-<repo>
$ brew create --cask https://d3qgzxtdztblkk.cloudfront.net/v1/hello/macos/downloader/undefined/UnicornProInstaller.pkg

대충 입력하고 편집기를 종료하자. 폰트에 비해 할 일이 많으니 Visual Studio Code 등을 이용해서 편집하는 것이 편하다.

cask "unicorn-pro" do
  version "1.7.12"
  sha256 

  url "https://d3qgzxtdztblkk.cloudfront.net/v1/hello/macos/downloader/undefined/UnicornProInstaller.pkg",
       "d3qgzxtdztblkk.cloudfront.net/"
  name "Unicorn Pro"
  desc "모든 브라우저와 앱에서 가장 강력한 광고 차단 성능으로 최고의 만족도를 제공합니다"
  homepage "https://getunicorn.app/ko/product/unicorn-pro/macos"

  pkg "UnicornProInstaller.pkg"

  uninstall  "com.unicornsoft.unicornproformac.*"

  zap  [
    "/Library/LaunchDaemons/com.unicornsoft.unicornproformac.unicornprod.plist",
    "~/Library/Application Support/HTTPStorages/com.unicornsoft.unicornproformac",
    "~/Library/Group Containers/*.com.unicornsoft.unicornproformac",
    "~/Library/Preferences/com.unicornsoft.unicornproformac.autolaunchhelper.plist",
    "~/Library/Preferences/group.com.unicornsoft.unicornproformac.plist",
  ]
end
  • sha256: url에 버전 정보가 없으면 :no_check로 해야한다.
  • url: .pkg 파일 경로 다음에 verified 항목이 있다. urlhomepage의 호스트가 다를 때 이렇게 설정해야 한다.
  • pkg: 파일 포맷이 .pkg 이므로 pkg 스탄자를 사용한다.
  • uninstall pkgutil: .pkg로 설치된 파일을 제거하기 위해 작성한다.
  • zap trash: 유니콘 Pro 앱을 삭제할 때 함께 삭제할 파일을 나열한다. 경로는 Pearcleaner 등을 이용하면 된다.

작성을 마쳤으면 검사를 한다.

$ brew style --fix --cask unicorn-pro

오류가 있으면 고친다. zap trash 순서는 알파벳 순으로 정렬해야 하는데, --fix 옵션을 추가하면 자동으로 해준다.

마지막으로 audit으로 검사한다.

$ brew audit --cask --new unicorn-pro
Warning: No checksum defined for cask 'unicorn-pro', skipping verification.

sha256 해쉬가 :no_check라서 경고는 뜨지만 오류는 없다.

GitHub에 푸쉬하자. 체크섬 경고가 있지만 GitHub 액션에서 아무 오류가 없는 것을 알 수 있다.

간혹 brew install --cask로 패키지를 설치할 때 100%가 안 되는 경우가 있다. 이런 경우는 해당 앱의 .pkg, .dmg 파일을 웹사이트 등을 통해 직접 다운로드한다. 그리고 Homebrew 캐쉬 디렉토리에서 해당 파일을 이 파일로 교체한다.

$ ls `brew --cache`/downloads | grep -i input
'55f0c43e5cf8e7cce28423f6304153a7efa54a069e243ca5b78a62af0e10b526--Input Source Pro 2.6.1.dmg'
$ mv Input.Source.Pro.2.6.1.dmg `brew --cache`/downloads/'55f0c43e5cf8e7cce28423f6304153a7efa54a069e243ca5b78a62af0e10b526--Input Source Pro 2.6.1.dmg'
$

다시 brew install --cask를 실행하면 캐쉬된 파일이 있다고 판단해서 이 파일을 사용해서 설치하기 때문에 오류없이 설치할 수 있다.

맨 위로