반응형

바쁜 분은 이것만

  1. 크롬 창은 make new window로 만들고, 돌려받은 창 변수로만 조작하기
  2. 탭 전환은 set active tab index of w to 1, 최소화는 set minimized of w to true
  3. 크롬 창 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

반응형

+ Recent posts