바쁜 분은 이것만
- 크롬 창은
make new window로 만들고, 돌려받은 창 변수로만 조작하기 - 탭 전환은
set active tab index of w to 1, 최소화는set minimized of w to true - 크롬 창 id는 9자리라
window id 875878509처럼 숫자로 직접 쓰면 실패 — 글자로 비교해서 찾기
맥의 크롬은 AppleScript를 지원해서, 터미널의 osascript로 창을 열고 탭을 바꾸고 닫을 수 있어요. 파이썬에서 부르면 정해진 페이지를 띄워 두는 자동화도 쉽게 만들 수 있습니다. 실제로 돌려 보면서 막혔던 곳 두 군데까지 같이 정리했어요. 테스트는 모두 example.com을 띄운 새 창에서만 했습니다.
1. 창 개수, 탭 개수 세기
$ osascript -e 'tell application "Google Chrome" to count windows'
1
탭은 창마다 따로라서 반복으로 더해요.
tell application "Google Chrome"
set n to 0
repeat with w in windows
set n to n + (count tabs of w)
end repeat
return n
end tell
7
크롬이 꺼져 있으면 tell application이 크롬을 켜 버리니, 개수만 볼 때는 pgrep -x "Google Chrome"으로 먼저 확인하는 게 좋아요.
2. 새 창 열고 URL 넣기, 탭 추가, 활성 탭 바꾸기, 최소화
한 스크립트 안에서 다 해 본 코드예요. 핵심은 make new window가 돌려준 창을 w에 받아 두는 것입니다. "1번 창"처럼 순서로 부르면 사용 중인 다른 창을 건드릴 수 있어요.
tell application "Google Chrome"
set w to make new window
set URL of active tab of w to "https://example.com"
make new tab at end of tabs of w with properties {URL:"https://example.org"}
delay 3
set wid to id of w
set out to "창 id: " & wid & linefeed
set out to out & "창 개수: " & (count windows) & linefeed
set out to out & "탭 URL: " & (URL of tabs of window id wid as text) & linefeed
set out to out & "활성 탭: " & (active tab index of window id wid) & linefeed
set active tab index of window id wid to 1
set out to out & "바꾼 뒤 활성 탭: " & (active tab index of window id wid) & " " & (URL of active tab of window id wid) & linefeed
set out to out & "탭 제목: " & (title of active tab of window id wid) & linefeed
set minimized of window id wid to true
delay 1
set out to out & "최소화: " & (minimized of window id wid) & linefeed
set minimized of window id wid to false
delay 1
set out to out & "복원: " & (minimized of window id wid) & linefeed
return out
end tell
$ osascript c3_all.applescript
창 id: 875878509
창 개수: 2
탭 URL: https://example.com/https://example.org/
활성 탭: 2
바꾼 뒤 활성 탭: 1 https://example.com/
탭 제목: Example Domain
최소화: true
복원: false
- 새 탭을 만들면 그 탭이 활성 탭(2)이 돼요.
active tab index는 1부터 셉니다. minimized는 바꾸자마자 읽으면 이전 값이 나올 수 있어delay 1을 두었어요.URL of tabs ... as text는 구분자 없이 붙어서 나와요. 따로 보려면 반복으로 꺼내면 됩니다.
3. 막힌 곳 ①: window id를 숫자로 직접 쓰면 실패
위에서 받은 id로 터미널에서 다시 부르면 이렇게 됩니다.
$ osascript -e 'tell application "Google Chrome" to get URL of active tab of window id 875878509'
40:43: execution error: Google Chrome에 오류 발생: window id 8.75878509E+8을(를) 가져올 수 없습니다. (-1728)
id가 8.75878509E+8로 바뀌어 있어요. AppleScript의 정수는 범위가 작아서, 큰 숫자를 코드에 직접 쓰면 실수(real)가 됩니다.
$ osascript -e 'return class of 536870911'
integer
$ osascript -e 'return class of 536870912'
real
"875878509" as integer로 바꿔도, whose id is로 걸러도 같은 오류였어요. 스크립트 안에서 크롬이 돌려준 id를 변수에 담아 쓸 때(2번)는 문제가 없었습니다. 그래서 바깥에서 받은 id는 글자로 비교해서 창을 찾게 했어요.
4. 막힌 곳 ②: repeat 변수는 "몇 번째 창"이다
처음엔 이렇게 찾은 창을 그대로 돌려줬어요.
repeat with w in windows
if (id of w as text) is wid then return w
end repeat
그런데 파이썬에서 최소화하고 읽으면 계속 false가 나왔습니다.
최소화: false
복원: false
repeat with w in windows의 w는 창 자체가 아니라 "item 2 of every window" 같은 순서 참조예요. 최소화하면 창 순서가 바뀌어서, 다시 읽을 때는 다른 창을 보고 있었던 거죠(기존 창은 상태를 확인해 보니 그대로였어요). 창 id를 꺼내 window id i로 돌려주게 고쳤습니다.
repeat with w in windows
set i to id of w
if (i as text) is wid then return window id i
end repeat
같은 이유로 반복 안에서 창을 닫고 그대로 계속 돌면, 없어진 순서를 찾다가 오류가 나요.
execution error: Google Chrome에 오류 발생: item 2 of every window을(를) 가져올 수 없습니다. 유효하지 않은 인덱스. (-1719)
닫은 다음에는 바로 return이나 exit repeat로 빠져나오면 됩니다.
5. 파이썬에서 부르기: 열고, 바꾸고, 닫기
스크립트를 osascript -의 표준 입력으로 넘기고, URL·창 id는 argv로 넘겨요. 문자열을 스크립트에 끼워 넣지 않아도 돼서 따옴표 문제가 없습니다.
import subprocess, time
def osa(script, *args):
r = subprocess.run(["osascript", "-", *args], input=script,
capture_output=True, text=True)
if r.returncode != 0:
raise RuntimeError(r.stderr.strip())
return r.stdout.strip()
FIND = '''
on findWin(wid)
tell application "Google Chrome"
repeat with w in windows
set i to id of w
if (i as text) is wid then return window id i
end repeat
end tell
error "창 없음: " & wid
end findWin
'''
def counts():
out = osa('''tell application "Google Chrome"
set n to 0
repeat with w in windows
set n to n + (count tabs of w)
end repeat
return (count windows) & "," & n
end tell''')
w, t = out.split(", ")[0], out.split(", ")[-1]
return int(w), int(t)
def open_window(url):
return osa('''on run argv
tell application "Google Chrome"
set w to make new window
set URL of active tab of w to item 1 of argv
return id of w as text
end tell
end run''', url)
def win_do(wid, body):
return osa(FIND + '''on run argv
set w to findWin(item 1 of argv)
tell application "Google Chrome"
''' + body + '''
end tell
end run''', wid)
print("시작:", counts())
wid = open_window("https://example.com")
win_do(wid, 'make new tab at end of tabs of w with properties {URL:"https://example.org"}')
time.sleep(2)
print("열고 나서:", counts(), "새 창 id:", wid)
print("활성 탭:", win_do(wid, 'return active tab index of w'))
win_do(wid, 'set active tab index of w to 1')
print("바꾼 뒤:", win_do(wid, 'return URL of active tab of w'))
print("최소화:", win_do(wid, 'set minimized of w to true\ndelay 1\nreturn minimized of w'))
print("복원:", win_do(wid, 'set minimized of w to false\ndelay 1\nreturn minimized of w'))
win_do(wid, 'close w')
time.sleep(1)
print("닫은 뒤:", counts())
$ .venv/bin/python p1.py
시작: (1, 8)
열고 나서: (2, 10) 새 창 id: 875878548
활성 탭: 2
바꾼 뒤: https://example.com/
최소화: true
복원: false
닫은 뒤: (1, 8)
(창 개수, 탭 개수)가 처음과 끝이 같아서, 만든 창만 깔끔히 닫힌 걸 확인할 수 있어요.- 숫자로 시작하는
(count windows) & "," & n은 글자가 아니라 리스트가 돼서1, ,, 8처럼 나와요. 그래서", "로 나눠 앞뒤만 썼습니다. - osascript로 맥 캘린더에 일정을 넣는 예는 파이썬으로 맥 캘린더에 일정 자동 등록하기에 있어요.
6. 처음 실행할 때: 자동화 권한
macOS는 한 앱이 다른 앱을 AppleScript로 조종할 때 자동화 권한을 물어봐요. 터미널에서 처음 돌리면 "터미널이 Google Chrome을 제어하려고 합니다" 같은 창이 뜨고, 허용해야 동작합니다. 거부했다면 시스템 설정 → 개인정보 보호 및 보안 → 자동화에서 터미널 아래 Google Chrome을 켜면 돼요. 거부 상태에서는 osascript가 오류(-1743)로 끝납니다. 이 맥은 이미 허용돼 있어서 창이 뜨지 않았고, 이 부분은 Apple 안내 기준이에요.
정리
| 하고 싶은 것 | AppleScript |
|---|---|
| 창·탭 개수 | count windows, count tabs of w |
| 새 창 + URL | set w to make new window → set URL of active tab of w to ... |
| 탭 추가 | make new tab at end of tabs of w with properties {URL:...} |
| 활성 탭 바꾸기 | set active tab index of w to 1 (1부터) |
| 최소화/복원 | set minimized of w to true/false + delay 1 |
| 창 닫기 | close w (반복 안이면 바로 빠져나오기) |
| 바깥에서 받은 id | 숫자로 쓰지 말고 (id of w as text) is wid로 찾아 window id i |
참고: Google Chrome AppleScript 사전(스크립트 편집기 → 파일 → 용어 사전 열기) / Apple AppleScript Language Guide — repeat with loopVariable in list, integer 클래스 / Python 공식 문서 — subprocess.run
