개발 서버가 실행 중인지 확인하려고 터미널을 열고 Git 브랜치를 보려고 명령을 입력하고 배포 페이지를 찾으려고 브라우저 탭을 뒤지는 일이 반복됩니다. 한 번 확인하는 데는 오래 걸리지 않지만 작업 중에 여러 번 되풀이하면 번거롭습니다.

SwiftBar를 쓰면 이런 정보를 macOS 화면 위쪽의 메뉴바에 띄워둘 수 있습니다. 메뉴바에는 DEV 실행 중처럼 짧은 상태를 표시하고 클릭하면 확인 시각이나 관련 링크를 펼쳐 보는 식입니다. 별도의 macOS 앱을 개발할 필요 없이 텍스트를 출력하는 스크립트로 만들 수 있습니다.

아래에서는 날짜를 표시하는 작은 플러그인부터 만든 뒤 개발 서버 상태 확인으로 확장합니다. 설치와 동작 설명은 SwiftBar 공식 문서 를 바탕으로 정리했습니다.

스크립트의 출력이 메뉴바가 되는 방식

SwiftBar에서 말하는 플러그인 은 메뉴에 표시할 내용을 출력하는 실행 파일입니다. 여기서는 macOS에 기본으로 포함된 Bash로 실행할 수 있는 .sh 스크립트를 사용합니다.

터미널에서 echo "작업 상태"를 실행하면 화면에 작업 상태라는 글자가 나옵니다. 이런 일반 출력을 표준 출력(stdout) 이라고 합니다. SwiftBar는 이 출력을 읽어서 메뉴바와 드롭다운 메뉴를 구성합니다.

스크립트가 아래 텍스트를 출력한다고 생각하면 이해하기 쉽습니다.

DEV 실행 중
---
주소: http://localhost:3000
확인 시각: 09:30:00

첫 번째 --- 위의 내용은 메뉴바에 표시되는 헤더(Header) 입니다. 아래의 내용은 메뉴바 항목을 클릭했을 때 펼쳐지는 본문(Body)입니다. 위 예시라면 메뉴바에는 DEV 실행 중이 보이고 클릭하면 주소와 확인 시각을 읽을 수 있습니다.

메뉴바는 공간이 좁으므로 헤더에는 상태를 한 줄로 쓰고 자세한 정보는 본문에 두는 편이 좋습니다. 헤더를 여러 줄 출력하면 SwiftBar가 제목을 번갈아 표시하므로 처음에는 한 줄로 시작하면 됩니다.

설치하고 플러그인 전용 폴더 지정하기

Homebrew가 설치되어 있다면 터미널에서 아래 명령을 실행합니다.

brew install --cask swiftbar

현재 Homebrew cask 페이지 와 공식 README는 macOS Monterey 12 이상을 요구합니다. 이전 자료에 있는 macOS 11 이상 안내와 차이가 있으므로 설치할 때 자신의 macOS 버전을 확인합니다.

설치가 끝나면 응용 프로그램 폴더에서 SwiftBar를 실행합니다. 첫 실행 시 Plugin Folder 를 지정하는데 SwiftBar가 플러그인 파일을 읽어오는 폴더입니다. 예를 들어 터미널에서 다음 폴더를 만든 뒤 선택할 수 있습니다.

mkdir -p "$HOME/SwiftBarPlugins"

이 명령은 홈 폴더 아래에 SwiftBarPlugins 폴더를 만듭니다. 이후 예제 파일은 모두 이 폴더에 저장합니다. 다른 폴더를 선택했다면 예제의 경로도 그에 맞게 바꿔야 합니다.

플러그인 폴더는 전용으로 두는 편이 관리하기 쉽습니다. SwiftBar는 하위 폴더와 심볼릭 링크로 연결된 폴더도 탐색합니다. 심볼릭 링크는 다른 위치의 파일이나 폴더를 가리키는 연결입니다. 팀 공용 플러그인을 연결할 때 유용하지만 저장소 전체를 연결하면 실행할 생각이 없던 파일까지 읽어올 수 있습니다. 숨김 폴더는 무시하며 특정 파일을 제외할 때는 .swiftbarignore를 사용할 수 있습니다.

첫 플러그인으로 날짜와 시각 표시하기

먼저 외부 서비스나 추가 프로그램 없이 실행할 수 있는 예제로 출력 형식을 익혀봅니다.

파일명에 갱신 주기 적기

SwiftBarPlugins 폴더에 date.1m.sh라는 파일을 만듭니다. 파일명은 다음처럼 구성합니다.

date.1m.sh
이름.갱신주기.확장자

date는 구분하기 위한 이름이고 1m은 1분마다 다시 실행한다는 뜻입니다. .sh는 셸 스크립트 파일을 나타냅니다. 갱신 주기에 쓸 수 있는 단위는 다음과 같습니다.

단위의미파일명 예시
ms밀리초sample.500ms.sh
s초devserver.10s.sh
m분date.1m.sh
h시간weather.1h.sh
d일links.1d.sh

이 표는 파일명 문법을 보여 주는 예시입니다. 외부 API를 밀리초 단위로 호출하라는 권장은 아닙니다.

날짜를 출력하는 스크립트 작성하기

코드 편집기로 date.1m.sh를 열고 다음 내용을 저장합니다. 일반 텍스트 파일로 저장해야 하며 파일명 뒤에 .txt가 붙지 않았는지도 확인합니다.

#!/bin/bash

/bin/date '+%m/%d %H:%M'
echo '---'
echo "오늘 날짜: $(/bin/date '+%Y년 %m월 %d일')"
echo "마지막 확인: $(/bin/date '+%H:%M:%S')"
echo '지금 새로고침 | refresh=true'

첫 줄의 #!/bin/bash는 이 파일을 Bash로 실행하라는 뜻입니다. /bin/date는 macOS의 날짜 명령이며 $(...)는 명령을 실행한 결과를 문장 안에 넣는 셸 문법입니다.

첫 번째 날짜 출력이 메뉴바 제목이 됩니다. echo '---'가 제목과 드롭다운을 나누고, 그 아래의 echo 명령이 메뉴 항목을 하나씩 만듭니다. 마지막 줄의 refresh=true는 해당 항목을 클릭하면 스크립트를 다시 실행하라는 옵션입니다.

이 플러그인은 1분마다 실행되므로 초 단위로 움직이는 시계는 아닙니다. 드롭다운의 마지막 확인은 스크립트가 마지막으로 실행된 시각입니다. 클릭할 때마다 자동으로 다시 실행하도록 설정한 것은 아니며 즉시 갱신하려면 지금 새로고침을 누릅니다.

터미널에서 출력 확인하기

실행 권한을 부여한 뒤 파일을 직접 실행합니다.

chmod +x "$HOME/SwiftBarPlugins/date.1m.sh"
"$HOME/SwiftBarPlugins/date.1m.sh"
echo "종료 코드: $?"

chmod +x는 파일에 실행 권한을 부여합니다. SwiftBar도 기본 설정에서는 새 플러그인에 실행 권한을 부여하지만 직접 실행하는 과정에서 권한과 출력 형식을 함께 확인할 수 있습니다.

출력은 다음과 같은 형태여야 합니다. 날짜와 시각은 실행한 때에 따라 달라집니다.

10/27 09:30
---
오늘 날짜: 2026년 10월 27일
마지막 확인: 09:30:00
지금 새로고침 | refresh=true
종료 코드: 0

마지막의 종료 코드: 0은 앞선 명령이 정상 종료됐는지 확인하려고 터미널에서 출력한 값입니다. 플러그인 파일에는 들어 있지 않으므로 메뉴에 표시되지 않습니다. $?는 바로 앞 명령의 종료 코드이므로 파일을 실행한 직후 확인해야 합니다.

SwiftBar가 파일을 읽으면 메뉴바에 날짜가 표시됩니다. 바로 반영되지 않는다면 SwiftBar가 실행 중인지, 선택한 Plugin Folder 안에 파일을 저장했는지 확인합니다. 아래 명령으로 전체 플러그인의 새로고침을 요청할 수도 있습니다.

open -g 'swiftbar://refreshallplugins'

색상과 클릭 동작은 출력 줄 뒤에 붙이기

앞선 예제의 | refresh=true처럼, 각 출력 줄에는 표시 방법이나 클릭 동작을 덧붙일 수 있습니다. 형식은 제목 | 옵션=값입니다. 옵션이 여러 개면 공백으로 구분합니다.

echo 'DEV 실행 중 | color=green sfimage=checkmark.circle'
echo '---'
echo '브라우저로 열기 | href=http://localhost:3000'
echo '지금 상태 확인 | refresh=true'

이 출력은 메뉴바에 초록색 상태 문구와 아이콘을 표시합니다. 드롭다운에서 브라우저로 열기를 누르면 주소를 열고, 지금 상태 확인을 누르면 플러그인을 다시 실행합니다. sfimage는 macOS의 SF Symbols 아이콘 이름을 지정하는 옵션입니다.

자주 쓰는 옵션은 역할을 구분해 두면 이해하기 쉽습니다.

옵션역할예시
color글자 색상 지정color=green
sfimageSF Symbols 아이콘 지정sfimage=checkmark.circle
tooltip마우스를 올렸을 때 보조 설명 표시tooltip=localhost:3000
href클릭하면 URL 열기href=http://localhost:3000
refresh클릭하면 플러그인 다시 실행refresh=true
bash클릭하면 지정한 실행 파일 실행bash=/usr/bin/open
terminalbash 실행 시 터미널 창 사용 여부 지정terminal=false

여기서 출력 안의 |는 SwiftBar가 읽는 구분자입니다. 셸에서 명령을 연결하는 파이프와 모양은 같지만 위 코드에서는 따옴표 안의 텍스트이므로 셸이 파이프로 실행하지 않습니다.

명령 실행이 필요하다면 bash에 실행 파일의 절대 경로를 적고 param1, param2 등으로 인자를 전달합니다. 예를 들어 아래 항목은 클릭했을 때 Finder에서 응용 프로그램 폴더를 엽니다.

echo '응용 프로그램 폴더 열기 | bash=/usr/bin/open param1=/Applications terminal=false'

개발 서버 상태를 메뉴바에서 확인하기

이제 날짜 대신 실제 작업 상태를 표시해 봅니다. 로컬 개발 서버가 3000번 포트에서 실행 중인지 확인하는 예제입니다. 포트는 프로그램이 네트워크 연결을 받는 번호이며 여기서는 브라우저에서 http://localhost:3000으로 접속하는 서버를 가정합니다.

같은 폴더에 devserver.10s.sh 파일을 만들고 아래 코드를 저장합니다. 자신의 개발 서버가 다른 포트를 쓴다면 코드의 3000과 접속 주소를 함께 바꿉니다.

#!/bin/bash

if /usr/sbin/lsof -nP -iTCP:3000 -sTCP:LISTEN >/dev/null 2>&1; then
  echo 'DEV 실행 중 | color=green sfimage=checkmark.circle'
else
  echo 'DEV 중지 | color=gray sfimage=pause.circle'
fi

echo '---'
echo '확인 대상: TCP 3000번 포트'
echo "마지막 확인: $(/bin/date '+%H:%M:%S')"
echo '브라우저로 열기 | href=http://localhost:3000'
echo '지금 상태 확인 | refresh=true'

lsof는 파일이나 네트워크 연결을 사용하는 프로세스를 확인하는 도구입니다. 여기서는 TCP 3000번 포트에서 연결을 기다리는 프로세스가 있는지 검사합니다. 있으면 DEV 실행 중, 없으면 DEV 중지를 출력합니다. >/dev/null 2>&1은 lsof의 출력과 오류 메시지가 메뉴 항목에 섞이지 않도록 숨기는 부분입니다.

앞선 날짜 예제처럼 실행 권한을 부여하고 터미널에서 먼저 실행합니다.

chmod +x "$HOME/SwiftBarPlugins/devserver.10s.sh"
"$HOME/SwiftBarPlugins/devserver.10s.sh"

파일명의 10s에 따라 SwiftBar는 10초마다 상태를 확인합니다. 서버를 켜거나 끈 직후에는 다음 갱신 전까지 이전 상태가 남을 수 있습니다.

이 예제가 확인하는 범위는 해당 포트에서 연결을 기다리는 프로세스가 있는지 입니다. 다른 프로그램이 같은 포트를 쓰고 있을 수도 있고 서버가 연결은 받지만 페이지나 API에서는 오류를 낼 수도 있습니다. 애플리케이션이 정상 응답하는지까지 확인하려면 별도의 상태 확인 URL을 요청하고 HTTP 응답 코드나 본문을 검사하는 방식으로 확장해야 합니다.

내 작업에 맞춰 확장할 수 있는 활용처

날짜와 서버 상태 예제를 이해했다면, 정보를 가져오는 명령만 바꿔 다른 플러그인을 만들 수 있습니다. Git 브랜치를 표시하려면 대상 저장소를 명확히 지정하고 디스크 용량은 어떤 볼륨을 확인할지 먼저 정하면 됩니다.

활용처메뉴바에 표시할 내용드롭다운에 둘 내용
Git 브랜치지정한 저장소의 현재 브랜치저장소 경로와 관련 링크
디스크 용량확인 대상 볼륨의 남은 공간 또는 사용률전체 용량과 측정 대상
API 상태마지막 요청의 정상·오류 여부응답 코드와 확인 시각
배포 링크 모음짧은 프로젝트 이름운영·테스트 환경과 CI 대시보드 링크

특히 링크 모음은 상태를 수집할 필요가 없어 간단히 만들 수 있습니다. links.1d.sh라는 파일에 아래 내용을 저장하면 됩니다. example.com 주소는 설명을 위한 예시이므로 실제 사용하는 주소로 바꿉니다.

#!/bin/bash

echo '프로젝트 링크'
echo '---'
echo '운영 환경 | href=https://example.com'
echo '테스트 환경 | href=https://staging.example.com'
echo 'CI 대시보드 | href=https://ci.example.com'

각 항목은 클릭하면 해당 주소를 엽니다. 이 스크립트에는 배포 상태를 조회하는 로직이 없으므로 메뉴바에 프로젝트 이름이 보인다고 배포 성공이나 서비스 정상을 확인한 것은 아닙니다.

갱신 주기도 정보의 성격에 맞춥니다. 링크처럼 자주 바뀌지 않는 내용은 하루 단위로 길게 잡아도 되지만 로컬 개발 서버 상태는 작업 중 변화가 잦으므로 더 짧게 확인할 수 있습니다. 외부 API를 호출한다면 호출 제한과 배터리·네트워크 사용량을 함께 고려하고 응답이 없을 때 무한정 기다리지 않도록 요청 제한 시간을 설정하는 편이 좋습니다.

메뉴가 안 보이거나 예상과 다르게 동작할 때

문제가 생기면 SwiftBar 화면을 보기 전에 스크립트를 터미널에서 직접 실행해 봅니다. 명령 자체가 실패하는지, 출력은 나오지만 SwiftBar 형식과 맞지 않는지 나눠 보면 원인을 찾기 쉽습니다.

증상먼저 확인할 내용
메뉴바에 항목이 나타나지 않음SwiftBar 실행 여부, Plugin Folder 경로, 파일명과 실행 권한
실행해도 아무것도 출력되지 않음조건문이 모든 경우에 제목을 출력하는지, 정상 종료 시 출력이 비어 있지 않은지
명령 결과가 메뉴 항목으로 길게 섞임상태 수집용 명령의 출력과 메뉴 구성용 출력을 구분했는지
터미널에서는 되지만 SwiftBar에서 실패함필요한 명령의 절대 경로와 환경 변수, 접근 권한
상태가 바뀌었는데 이전 내용이 보임파일명의 갱신 주기와 마지막 확인 시각, 수동 새로고침 결과
메뉴바에 오류가 표시됨드롭다운의 Error 항목과 macOS 콘솔 앱의 SwiftBar 로그

기본 타입인 Standard 플러그인은 실행 후 출력을 남기고 종료합니다. 정상 종료하면서 출력이 비어 있지 않으면 SwiftBar가 메뉴를 구성하고 정상 종료해도 출력이 비어 있으면 메뉴바에 표시하지 않습니다. 디버깅 메시지는 일반 출력과 구분해 표준 오류(stderr)로 보내야 메뉴 구성을 방해하지 않습니다.

터미널과 앱에서 실행할 때는 환경이 다를 수 있습니다. 예제에서 /bin/date, /usr/sbin/lsof처럼 절대 경로를 쓴 것도 명령을 찾는 과정의 차이를 줄이기 위해서입니다. 나중에 Homebrew로 설치한 도구를 사용한다면 터미널에서 command -v 도구이름으로 경로를 확인하고 필요한 설정이 SwiftBar 실행 환경에도 전달되는지 점검합니다.

처음에는 날짜 플러그인 하나로 파일 위치와 출력 형식이 맞는지 확인하면 됩니다. 그다음 자주 확인하는 상태 하나를 추가하고 메뉴바에는 짧은 상태를, 드롭다운에는 확인 시각과 관련 링크를 두는 방식으로 확장할 수 있습니다.

참고한 글: 재아군의 SwiftBar 입문·활용 가이드 . 설치 조건과 플러그인 동작은 공식 문서에서 별도로 확인했습니다.