워커 간 통신

데스크톱 플랫폼용 Flash Player 11.4 이상, Adobe AIR 13.4 이상

각 워커는 별개의 실행 스레드에서 자체의 코드를 실행하지만 서로 완전히 격리된 경우에는 아무런 이점도 제공하지 않습니다. 워커 간 통신은 결국 워커 간 데이터 전달을 의미합니다. 다음과 같이 세 가지 기본 메커니즘으로 한 워커에서 다른 워커로 데이터를 가져올 수 있습니다.

특정 데이터 전달 요구 사항에 이러한 데이터 공유 기법 중 어떤 것이 적합한지 결정할 때는 서로 다른 두 가지 주요 방식을 고려합니다. 이 둘 간의 한 가지 차이점은 새 데이터를 사용할 수 있음을 수신자에게 알리는 이벤트가 있는지 여부 또는 수신 워커가 업데이트를 확인해야 하는지 여부와 관련이 있습니다. 이러한 데이터 공유 기법 간의 또 다른 차이점은 데이터를 실제로 전달하는 방식과 관련이 있습니다. 경우에 따라 수신 워커는 공유 데이터의 복제본을 받으며, 이렇게 되면 더 많은 객체가 생성되어 메모리 및 CPU 주기가 늘어납니다. 또 어떤 경우 워커는 동일한 기본 시스템 메모리를 참조하는 객체에 액세스하므로 더 적은 객체가 생성되어 전반적으로 사용되는 메모리가 줄어듭니다. 이러한 차이점은 아래에 요약되어 있습니다.

통신 기법

데이터 수신 시 이벤트 전달

워커 간에 메모리 공유

워커 공유 속성

아니요

아니요. 객체가 참조가 아닌 복제본임

MessageChannel

아니요. 객체가 참조가 아닌 복제본임

공유 가능한 ByteArray

아니요

예. 메모리가 공유됨

공유 속성을 사용한 데이터 전달

워커 간에 데이터를 공유하는 가장 기본적인 방법은 공유 속성을 사용하는 것입니다. 각 워커에서는 공유 속성 값의 내부 사전을 유지 관리합니다. 각 속성은 String 키 이름과 함께 저장되어 다른 속성과 구분됩니다. 워커에 공유 속성으로 객체를 저장하려면 두 인수, 즉 저장할 키 이름 및 값과 함께 Worker 객체의 setSharedProperty() 메서드를 호출하십시오.

// code running in the parent worker 
bgWorker.setSharedProperty("sharedPropertyName", someObject);

공유 속성이 설정된 후에 해당 값은 Worker 객체의 getSharedProperty() 메서드를 호출하여 키 이름을 전달하면 읽을 수 있습니다.

// code running in the background worker 
receivedProperty = Worker.current.getSharedProperty("sharedPropertyName");

어떤 워커에서 속성 값을 읽거나 설정하는지에 대한 제한은 없습니다. 예를 들어 백그라운드 워커의 코드에서 setSharedProperty() 메서드를 호출하여 값을 저장할 수 있습니다. 그런 다음, 부모 워커에서 실행 중인 코드는 getSharedProperty() 를 사용하여 데이터를 수신할 수 있습니다.

setSharedProperty() 메서드로 전달되는 값은 거의 모든 유형의 객체가 될 수 있습니다. getSharedProperty() 메서드를 호출하면 반환되는 객체는 몇몇 특수한 경우를 제외하고는 setSharedProperty() 에 전달된 객체의 사본이며 동일한 객체에 대한 참조가 아닙니다. 데이터가 공유되는 방식에 대한 자세한 내용은 공유 참조 및 복제 값 에 설명되어 있습니다.

공유 속성을 사용하여 워커 간에 데이터를 전달하는 방식의 가장 큰 이점은 워커가 실행되기 전에도 해당 방식을 활용할 수 있다는 것입니다. 백그라운드 Worker 객체의 setSharedProperty() 메서드를 호출하면 워커가 실행되기 전에도 공유 속성을 설정할 수 있습니다. 부모 워커에서 Worker의 start() 메서드를 호출하면 런타임에서는 자식 워커의 기본 클래스의 생성자를 호출합니다. start() 가 호출되기 전에 설정된 모든 공유 속성은 자식 워커에서 코드를 통해 읽는 것이 가능합니다.

MessageChannel을 사용한 데이터 전달

메시지 채널은 두 워커 간에 단방향 데이터 전달 링크를 제공합니다. 워커 간 데이터 전달을 위해 MessageChannel 객체를 사용하는 방식에는 핵심적인 이점 하나가 있습니다. 메시지 채널을 사용하여 메시지(객체)를 전송할 경우, MessageChannel 객체에서는 channelMessage 이벤트를 전달합니다. 수신 워커의 코드에서는 해당 이벤트를 수신하여 데이터의 사용 가능 시기를 파악할 수 있습니다. 따라서 수신 워커에서는 데이터의 업데이트 여부를 상시적으로 확인할 필요가 없습니다.

메시지 채널 하나는 두 개의 워커, 즉 전송자 및 수신자와만 연결되어 있습니다. MessageChannel 객체를 만들려면 전송자 Worker 객체의 createMessageChannel() 메서드를 호출하고 수신 워커를 인수로 전달하십시오.

// In the sending worker swf 
var sendChannel:MessageChannel; 
sendChannel = Worker.current.createMessageChannel(receivingWorker);

두 워커 모두 MessageChannel 객체에 액세스할 수 있어야 합니다. 이를 위한 가장 간단한 방법은 setSharedProperty() 메서드를 사용하여 MessageChannel 객체를 전달하는 것입니다.

receivingWorker.setSharedProperty("incomingChannel", sendChannel);

수신 워커에서 MessageChannel 객체의 channelMessage 이벤트에 대해 리스너를 등록합니다. 이 이벤트는 전송 워커에서 메시지 채널을 통해 데이터를 전송할 때 전달됩니다.

// In the receiving worker swf 
var incomingChannel:MessageChannel; 
incomingChannel = Worker.current.getSharedProperty("incomingChannel"); 
incomingChannel.addEventListener(Event.CHANNEL_MESSAGE, handleIncomingMessage);

실제로 데이터를 전송하려면 전송 워커에서 MessageChannel 객체의 send() 메서드를 호출하십시오.

// In the sending worker swf 
sendChannel.send("This is a message");

수신 워커에서 MessageChannel은 channelMessage 이벤트 핸들러를 호출합니다. 그런 다음 수신 워커에서는 MessageChannel 객체의 receive() 메서드를 호출하여 데이터를 가져올 수 있습니다.

private function handleIncomingMessage(event:Event):void 
{ 
    var message:String = incomingChannel.receive() as String; 
}

receive 메서드에 의해 반환된 객체는 send() 메서드에 전달된 객체와 동일한 데이터 유형을 갖습니다. 수신된 객체는 전송자에 의해 전달된 객체의 사본이며 전송 워커에 있는 객체의 참조가 아닙니다. 단, 해당 객체가 공유 참조 및 복제 값 에 설명되어 있는 몇몇 데이터 유형 중 하나에 속하는 경우는 예외입니다.

공유 가능한 ByteArray를 사용하여 데이터 공유

두 워커 간에 객체가 전달되면 수신 워커는 원본의 복제본에 해당하는 새 객체를 받습니다. 두 객체는 시스템 메모리에서 서로 다른 위치에 저장됩니다. 따라서 객체의 복제본이 수신될 때마다 런타이멩서 사용되는 총 메모리가 증가합니다. 또한 한 워커의 객체에서 변경하는 사항이 다른 워커의 복제본에 영향을 주지 않습니다. 객체가 복제되는 방식에 대한 자세한 내용은 공유 참조 및 복제 값 을 참조하십시오.

기본적으로 ByteArray 객체는 동일한 비헤이비어를 사용합니다. ByteArray 인스턴스를 Worker 객체의 setSharedProperty() 메서드 또는 MessageChannel 객체의 send() 메서드에 전달하는 경우 런타임에서는 컴퓨터의 메모리에 새 ByteArray를 생성하며 수신 워커는 새 ByteArray에 대한 참조에 해당하는 ByteArray 인스턴스를 가져옵니다. 하지만 해당 shareable 속성을 true 로 설정하여 ByteArray 객체에 대한 이 비헤이비어를 변경할 수 있습니다.

워커 간에 공유 가능한 ByteArray 객체를 전달하는 경우 수신 워커의 ByteArray 인스턴스는 송신 워커의 ByteArray 인스턴스에서 사용하는 것과 동일한 기본 운영 체제 메모리에 대한 참조입니다. 한 워커의 코드로 인해 바이트 배열의 내용이 변경되는 경우 이러한 변경 사항은 공유되는 바이트 배열에 액세스할 수 있는 다른 워커에서 바로 사용할 수 있습니다.

두 워커는 각자의 코드를 동시에 실행하기 때문에 바이트 배열에 있는 동일한 바이트에 동시에 액세스하려고 할 수 있습니다. 이렇게 되면 데이터가 손실되거나 손상될 수 있습니다. 공유 리소스에 대한 액세스를 관리하고 이러한 문제를 방지하기 위해 여러 가지 API를 사용할 수 있습니다.

ByteArray 클래스에는 다음과 같이 단일 작업에서 바이트 배열의 내용을 검증하고 변경하는 데 사용할 수 있는 메서드가 있습니다.

또한 flash.concurrent 패키지에는 공유 리소스 작업에 필요한 액세스 제어 기능을 제공하는 다음과 같은 클래스가 포함되어 있습니다.

공유 참조 및 복제 값

정상적인 상황에서 Worker.setSharedProperty() 또는 MessageChannel.send() 를 호출할 경우 수신 워커에 전달되는 객체는 AMF 형식으로 직렬화되어 전달됩니다. 그 결과는 다음과 같습니다.

  • getSharedProperty() 메서드가 호출될 때 수신 워커에 만들어지는 객체는 AMF 바이트로부터 비직렬화됩니다. 이 객체는 원본 객체의 참조가 아니라 사본입니다. 양쪽 워커의 객체에서 변경된 내용은 다른 워커에 있는 사본에는 적용되지 않습니다.

  • 표시 객체와 같이 AMF 형식으로 직렬화될 수 없는 객체는 Worker.setSharedProperty() 또는 MessageChannel.send() 를 사용하여 워커에 전달할 수 없습니다.

  • 사용자 정의 클래스를 올바르게 비직렬화하려면 flash.net.registerClassAlias() 함수 또는 [RemoteClass] 메타데이터를 사용하여 클래스 정의를 등록해야 합니다. 해당 클래스의 두 워커 버전 모두에 같은 별칭을 사용해야 합니다.

다음 객체는 워커 간에 복제되는 대신 실제로 공유되는 다섯 가지 특수한 객체입니다.

  • Worker 객체

  • MessageChannel 객체

  • 공유 가능한 바이트 배열(해당 shareable 속성이 true 인 ByteArray 객체)

  • Mutex 객체

  • Condition 객체

Worker.setSharedProperty() 메서드 또는 MessageChannel.send() 메서드를 사용하여 두 객체 중 하나의 인스턴스를 전달하면 각 워커는 동일한 기본 객체에 대한 참조를 갖게 됩니다. 한 워커에 있는 인스턴스에서 변경된 내용은 다른 워커에서 즉시 사용 가능합니다. 또한 이 객체 중 하나의 동일한 인스턴스를 한 워커에 두 번 이상 전달할 경우 런타임에서는 수신 워커에 해당 객체의 새로운 사본을 만들지 않습니다. 그 대신 같은 참조가 다시 사용됩니다.

그 밖의 데이터 공유 기술

데이터 전달을 위한 워커별 메커니즘 외에도, 다음과 같은 두 swf 응용 프로그램 간 데이터 공유를 지원하는 기존 API를 사용하면 데이터를 교환할 수 있습니다.

  • 로컬 공유 객체

  • 데이터를 한 워커의 파일에 쓴 후 다른 워커의 파일에서 읽기

  • SQLite 데이터베이스를 통해 데이터를 저장하고 읽기

둘 이상의 워커 간에 리소스를 공유할 경우에는 일반적으로 여러 워커가 동시에 해당 리소스에 액세스하지 않도록 방지해야 합니다. 예를 들어 여러 워커가 로컬 파일 시스템에 있는 하나의 파일에 액세스하면 데이터가 손실되거나 손상될 수 있으므로 이러한 액세스는 운영 체제에서 지원되지 않을 수도 있습니다.

동시 액세스 문제를 방지하려면 flash.concurrent 패키지의 Mutex 및 Condition 클래스를 사용하여 공유 리소스 작업에 필요한 액세스 제어 기능을 제공합니다.

다른 데이터 공유 메커니즘과 달리, SQLite 데이터베이스 엔진은 동시 액세스용으로 설계되었으며 자체적인 트랜잭션 지원 내장 기능을 갖추고 있습니다. 다중 워커는 데이터 손상의 위험 없이 SQLite 데이터베이스에 동시에 액세스할 수 있습니다. 각 워커는 서로 다른 SQLConnection 인스턴스를 사용하므로 개별 트랜잭션을 통해 데이터베이스에 액세스합니다. 따라서 동시적인 데이터 조작 작업은 데이터의 무결성에 영향을 주지 않습니다.

참고 사항

AIR에서 로컬 SQL 데이터베이스를 사용한 작업

flash.concurrent 패키지