NVDA 추가 기능 개발 가이드라인 2부
Webacc NV
2018-08-27 15:16:58
안녕하세요. 엔비전스입니다.
이번 글에서는 NVDA 추가 기능의 기본 구성 요소 및 글로벌 플러그인, 앱 모듈의 간단한 예제를 살펴보겠습니다.
들어가기 전에
- 1부에서 언급한 바와 같이 아티클 전반에서는 NVDA의 추가 기능 패키지(*.nvda-addon)를 사용하지 않으며, NVDA 사용자 환경 폴더 내 appModule, globalPlugins 폴더에 작업물을 저장합니다. 추가 기능 패키지(*.nvda-addon)를 제작하는 방법은 추후 다룰 예정입니다. NVDA 사용자 환경 폴더를 여는 방법은 NVDA 추가 기능 개발 가이드라인 1부 <추가 기능이 저장된 폴더 열기> 섹션을 참고합니다.
- NVDA는 Python 언어로 추가 기능을 제작할 수 있습니다. 2부에서 사용한 NVDA에 내장된 클래스, 메소드 왜 Python 언어의 문법, 튜토리얼 등의 자세한 내용은 Python 공식 문서 웹사이트 https://docs.python.org/ko/2.7/를 참고하세요.
- NVDA는 Python 언어로 추가 기능을 제작할 수 있습니다. 2부에서 사용한 NVDA에 내장된 클래스, 메소드 왜 Python 언어의 문법, 튜토리얼 등의 자세한 내용은 Python 공식 문서 웹사이트 https://docs.python.org/ko/2.7/를 참고하세요.
- NVDA에 기본으로 포함된 추가 기능을 위한 모듈에 대해서는 NVDA 추가 기능 모듈 문서를 통해 내장 모듈, 클래스 및 메소드에 대한 설명을 확인할 수 있습니다.
추가 기능 코드의 구성
추가 기능 코드는 하나 이상의 Python 파일 (.py 파일)에 저장됩니다. 이는, 앱 모듈, 글로벌 플러그인 등 NVDA의 모든 추가 기능에 공통으로 적용됩니다. 추가 기능 코드는 다음과 같이 구성됩니다:
- 추가 기능 작성 시 먼저 추가 기능에 대한 선택적인 머리글 (예 : 추가 기능의 이름 및 추가 기능의 간단한 설명 등)을 작성하는 것으로 시작합니다. 이 부분은 선택 사항이지만, 추가 기능의 역할, 용도를 아는 데 도움이 되므로 작성하는 것이 좋습니다.
- 다음으로, 추가 기능 파일에 필요한 모듈을 NVDA에 알려줍니다. 이 작업은 <import module>을 작성하여 수행됩니다. 여기서 module은 코드에서 사용할 모듈의 이름입니다. 예를 들어, 추가 기능을 사용하는 동안 비프음을 재생하기 위해서는 import tones 구문을 작성합니다. 일반적으로 특정 추가 기능에 대해 두 개 이상의 모듈을 사용해야 할 수도 있습니다. 추가 기능에서 사용할 수 있는 여러 모듈에 대해서는 다음 글에서 자세히 설명합니다.
- 필요한 모듈을 선언한 후, 추가 기능 코드 (클래스, 변수, 메소드) 등을 작성합니다. 가장 중요한 섹션은 코드를 할당할 추가 기능 모듈 유형을 결정하는 추가 기능 클래스 코드입니다. 세 예제를 통해 추가 기능 클래스에 대해 간단히 살펴보겠습니다.
- 클래스를 선언한 다음 추가 기능에 필요한 코드를 작성합니다. 추가 기능 작성 시 Python 공식 문서, 외부 모듈을 사용한다면 모듈 문서를 참고합니다.
- 추가 기능을 실행하려면, NVDA 추가 기능 개발 가이드라인 1부 내 <추가 기능 폴더 열기> 섹션을 참고하여 추가 기능 폴더를 연 다음 .py 파일을 appModules 또는 globalPlugins 폴더에 붙여 넣습니다.
추가 기능 첫 번째 예제: 단축키를 눌러 음성 메시지 출력하기
세 섹션에 걸쳐 NVDA 추가 기능의 간단한 예제를 살펴보겠습니다. 첫 번째 예제는 NVDA +Shift+A를 누르면 모든 프로그램에서 <안녕하세요. NVDA 추가 기능 개발 가이드라인의 첫 번째 예제입니다.>가 음성 출력되는 예제입니다. 프로그램과 관계없이 어디에서나 실행되어야 하므로, 글로벌 플러그인으로 작성해야 합니다.
아래 코드는 첫 번째 예제 코드입니다. 파일을 내려받아 테스트하거나, 아래 코드를 복사하여 붙여 넣은 후 <example1GlobalPlugin.py> 로 저장합니다. 추가 기능 파일 이름은 추가 기능의 역할을 유추할 수 있는 이름으로 지정하는 것이 좋습니다. 첫 번째 예제 다운로드
<code start>
# -*- coding: utf-8 -*-
# NVDA 추가 기능 개발: 첫 번째 예제
# 이 예제는 NVDA+a 키를 누를 때마다 1초 동안 비프음을 울립니다. 이 예제는 특정 프로그램에 국한되지 않고, NVDA가 실행된 상태에서 어디에서나 사용할 수 있습니다.
# 제작자: a11yTester(a11yTester@example.com)
import globalPluginHandler # 글로벌 플러그인을 제작하기 위한 필수 모듈
import ui # 음성 또는 점자로 메시지 출력을 위한 모듈
class GlobalPlugin(globalPluginHandler.GlobalPlugin): # 글로벌 플러그인 제작을 위해 GlobalPlugin class 정의
def script_outputMessage(self, gesture): # NVDA+Shift+A 키를 누르면 음성 메시지가 출력되는 함수
ui.message(u'안녕하세요. NVDA 추가 기능 개발 가이드라인의 첫 번째 예제입니다.') # ui.message 메소드로 음성 및 점자로 메시지 출력
__gestures = { # 추가 기능에 대한 단축키를 할당하기 위해 Python의 사전형으로 정의
"kb:NVDA+shift+A":"outputMessage" # NVDA+Shift+A 키에 기능을 할당합니다
}
</code end>
첫 번째 예제에 대한 코드 설명
첫 번째 예제를 자세히 살펴보겠습니다.
- 파일의 첫 번째, 두 번째 줄에는 추가 기능의 명칭 및 제작자 정보로 추가 기능 예제임을 명확히 알려 NVDA 추가 기능 관련 파일임을 명시했습니다. 추가 기능의 라이선스 등과 같은 중요 정보를 추가할 수도 있습니다.
- 이 예제는 글로벌 플러그인이므로 import globalPluginHandler 구문을 통해 글로벌 플러그인 작성을 위한 모듈을 불러왔습니다.
- import ui 구문을 작성하여 NVDA의 내장된 음성이나 점자로 메시지를 출력하기 위한 모듈을 불러왔습니다. 주어진 모듈의 메소드를 사용하고자 할 때 필요한 모듈을 import 구문을 통해 불러올 수 있습니다.
- 글로벌 플러그인을 작성하기 위한 <GlobalPlugin이>라는 클래스를 정의했습니다. 괄호 안의 텍스트는 이 클래스가 어디에서 왔는지 알려줍니다.
- 클래스 내 script_outputMessage 메소드는 단축키를 누를 때 실행되는 메소드입니다. 이 스크립트에서 메시지가 음성으로 출력되도록 NVDA에 알리기 위해 ui.message(u'안녕하세요. NVDA 추가 기능 개발 가이드라인의 첫 번째 예제입니다.')를 작성했습니다.
- 마지막으로 outputMessage 스크립트에 단축키를 NVDA+Shift+A에 할당하기 위해 __gestures 블록에 "kb:NVDA+A":"outputMessage"를 작성했습니다. __gestures 블록에는 스크립트에 대한 단축키 또는 터치 명령을 할당하며, Python의 사전형으로 정의합니다.
파일을 저장하고 NVDA를 다시 시작하거나, NVDA+Control+F3 키를 눌러 플러그인을 새로 고칩니다. 이제 NVDA +Shift+A를 누를 때마다 <안녕하세요. NVDA 추가 기능 개발 가이드라인의 첫 번째 예제입니다.>가 음성으로 출력됩니다.
참고
Python에서는 해시 기호(#)를 라인의 첫 번째 칸에 삽입하여 해당 라인을 주석으로 처리되도록 할 수 있습니다. 주석은 코드에 대한 부가적인 설명 등에 사용되어 코드를 작성하지 않은 제3자가 코드를 이해할 수 있도록 하는 등 여러 면에서 유용합니다.
추가 기능을 처음 작성하는 사용자를 위한 팁
처음 NVDA 추가 기능을 개발하거나 추가 기능 개발이 익숙하지 않다면, 다음의 추가 기능 작성을 위한 일반적인 팁을 참고합니다:
- 추가 기능을 개발할 때, 한 번에 한 가지 기능을 작성하고 테스트합니다. 예를 들어, 특정 단축키를 누를 때마다 각기 다른 기능(음성 메시지 출력 또는 브라우저 주소 열기 등)과 같이 여러 기능을 개발하려 한다면, 한 가지 기능을 먼저 개발한 후 테스트하는 것이 좋습니다.
- 응용 프로그램을 위한 앱 모듈을 작성하려면, 응용 프로그램의 설명서 및 사용법을 충분히 익혀야 합니다.
- 추가 기능에서 사용될 단축키를 정의할 때 NVDA의 기본 단축키와 충돌하지 않도록 NVDA의 설명서를 참조하여 확인합니다.
두 번째 예제: 이벤트가 발생할 때 비프음 재생하기
두 번째 예제는 특정 컨트롤에 초점을 이동하거나, 체크 상자를 선택 또는 해제하는 것과 같은 상황에서 이벤트가 발생할 때 비프음이 재생되는 예제입니다. 이벤트와 같은 중요 개념에 대해서는 3부에서 자세히 다룹니다. 다음 예제를 복사하여 <exampleGlobalPlugin.py> 과 같은 파일 이름으로 저장하거나, 파일을 내려받아 테스트합니다. 두 번째 예제 다운로드
<code start>
# -*- coding: utf-8 -*-
# NVDA 추가 기능 개발: 두 번째 예제
# 이 예제는 <네이버> 링크에 초점이 위치하거나 벗어날 때 다른 비프음을 출력합니다. 이 예제는 응용 프로그램에 관계없이 어디에서나 실행할 수 있습니다
import api # 플러그인 작성에 필요한 기본 API 모듈
import controlTypes # 체크 상자, 링크와 같은 컨트롤을 처리하기 위한 모듈
import globalPluginHandler # 글로벌 플러그인을 제작하기 위한 필수 모듈
import tones # 비프음을 재생하기 위한 모듈
class GlobalPlugin(globalPluginHandler.GlobalPlugin): # 글로벌 플러그인 제작을 위해 GlobalPlugin class 정의
def event_gainFocus (self, obj, nextHandler): # 특정 컨트롤에 초점을 이동하면 발생하는 gainFocus 이벤트를 처리하기 위한 함수
obj = api.getFocusObject() # api 모듈의 초점을 받은 객체를 얻기 위한 함수
if (obj.name == u'네이버' and obj.role == controlTypes.ROLE_LINK): # 콘트롤의 이름이 네이버이고, 역할이 링크인 요소일 때 기능 실행
tones.beep(440,100) # 440Hz의 비프음 재생
nextHandler() # 비프음 재생 후 NVDA가 음성 출력 등과 같은 다음 기능이 처리될 수 있도록 함
def event_loseFocus(self, obj, nextHandler): # 특정 컨트롤에서 초점을 잃었을 때 발생하는 loseFocus 이벤트를 처리하기 위한 함수
obj = api.getFocusObject() # API 모듈에서 현재 초점을 받은 객체를 얻기 위한 함수
if (obj.name == u'네이버' and obj.role == controlTypes.ROLE_LINK): # 컨트롤의 이름이 네이버이고, 역할이 링크인 요소일 때 기능 실행
tones.beep(880, 100) # 880Hz의 비프음 재생
nextHandler() # 비프음 재생 후 NVDA가 음성 출력 등과 같은 다음 기능이 처리될 수 있도록 함
</code end>
두 번째 예제에 대한 코드 설명
- 파일의 첫 번째, 두 번째 줄에는 추가 기능에 대한 헤더를 작성하여 추가 기능이 어떤 역할 및 기능을 하는지 작성했습니다.
- 두 번째 예제도 글로벌 플러그인이므로 import globalPluginHandler 구문을 통해 글로벌 플러그인 작성을 위한 모듈을 불러왔습니다.
- import 구문을 통해 현재 초점이 있는 객체, 클립보드 복사와 같은 일반적인 함수가 정의된 api, 체크 상자, 라디오 버튼과 같은 컨트롤과 상호 작용을 위한 controlTypes, 비프음을 재생하기 위한 tones 모듈을 불러왔습니다.
- 글로벌 플러그인을 작성하기 위해 GlobalPlugin 클래스를 정의했습니다.
- 클래스 내 event_gainFocus, event_loseFocus 메소드를 통해 <네이버> 링크에 초점을 이동하거나 초점을 벗어났을 때 비프음이 재생되도록 처리합니다.
세 번째 예제: 특정 응용 프로그램에서 NVDA를 일시 중지하기
마지막으로 살펴볼 예제는, Firefox 웹 브라우저에서 NVDA가 일시 중지되도록 하는 예제입니다. Firefox 웹 브라우저에 초점을 위치하면, NVDA가 일시 중지되며, Firefox 웹 브라우저에서 초점을 벗어나기 전까지 NVDA는 음성 또는 점자 지원을 처리하지 않습니다. 키보드 명령 또한 NVDA에서 처리하지 않으며 응용 프로그램에 직접 전달됩니다. 다음 코드를 <firefox.py> 로 저장하여 NVDA 사용자 환경 폴더 내appModules 폴더에 저장합니다. 세 번째 예제 다운로드
<code start>
# NVDA 추가 기능 개발: 세 번째 예제
# 이 예제는 Firefox 웹 브라우저에서 NVDA가 일시 중지되도록 합니다. 이 예제는 Firefox 웹 브라우저에서만 작동합니다
# 제작자: a11yTester(a11yTester@example.com)
import appModuleHandler # APPModule을 작성하기 위한 필수 모듈
class AppModule(appModuleHandler.AppModule): # APPModule을 작성하기 위한 class 정의
sleepMode = True # sleepMode 변수를 true로 설정하여 NVDA가 일시 중지되도록 처리
</code end>
세 번째 예제에 대한 코드 설명
세 번째 예제는 두 예제와 달리 Firefox 웹 브라우저만을 대상으로 작동하는 앱 모듈입니다. Firefox 웹 브라우저로 초점을 이동하면 NVDA가 일시 중지됩니다. 세 번째 예제의 자세한 코드 설명은 다음과 같습니다:
- 파일의 첫 번째, 두 번째 줄은 두 예제와 같이 추가 기능의 기본적인 정보 및 제작자 정보를 명시하였습니다.
- 세 번째 예제는 Firefox 웹 브라우저 응용 프로그램만을 대상으로 하여 작동하므로, 앱 모듈 제작 시 필수적으로 요구되는 appModuleHandler 모듈을 불러왔습니다.
- 앱 모듈 작성을 위해 AppModule class를 정의했습니다.
- appModuleHandler.AppModule에 정의된 sleepMode 변수를 true로 설정하여 Firefox 웹 브라우저에서 NVDA가 작동하지 않도록 처리했습니다.
참고
앱 모듈은 해당 응용 프로그램의 이름과 정확히 일치하는 파일 이름으로 저장해야 합니다. 예를 들어, Chrome 웹 브라우저를 위한 추가 기능을 작성했다면 <chrome.py> 과 같이 저장해야 해당 프로그램에서 앱 모듈이 작동합니다.
2부에서 사용된 NVDA 내장 모듈 목록
다음은 이번 글에서 사용된 NVDA 내장 모듈 목록입니다. 해당 모듈에 대한 자세한 클래스 및 메소드 사용법에 대해서는 모듈별로 제공된 링크를 통해 확인할 수 있습니다.
- api: 현재 초점을 받은 객체 및 클립보드 복사 기능과 같은 일반적인 함수가 정의된 모듈
- appModuleHandler: 앱 모듈 제작 시 필수적으로 필요한 모듈
- controlTypes: 체크 상자, 라디오 버튼과 같은 컨트롤과의 상호 작용을 처리하기 위한 모듈
- globalPluginHandler: 글로벌 플러그인을 제작하기 위한 필수 모듈
- tones: 비프음 재생을 위한 모듈
- ui: 음성 및 점자로 사용자에게 메시지를 출력하기 위한 용도로 사용되며, 예제 1에서 음성 출력을 위해 사용
3부에서는 NVDA에 기본으로 내장된 유용한 모듈 및 메소드를 살펴보고, 추가 기능 제작 시 알아야 할 이벤트, 스크립트와 같은 주요 개념에 대해 살펴보겠습니다.
조회수4423