After Effects 스크립팅 기초 (ExtendScript) 완전정복! 🚀

콘텐츠 대표 이미지 - After Effects 스크립팅 기초 (ExtendScript) 완전정복! 🚀

 

 

애프터 이펙트의 숨겨진 슈퍼파워를 깨우는 방법 ✨

After Effects 스크립팅의 세계 ExtendScript로 작업 흐름을 혁신하자! Ae {code} script()

안녕! 오늘은 애프터 이펙트(After Effects)를 더 효율적으로 다룰 수 있게 해주는 마법 같은 기술, 바로 ExtendScript에 대해 함께 알아볼 거야. 🧙‍♂️

혹시 반복적인 작업에 지쳐있니? 특정 효과를 여러 레이어에 적용하느라 손목이 아프진 않아? 아니면 복잡한 애니메이션을 매번 수동으로 만드느라 시간을 낭비하고 있진 않아? 그렇다면 이 글이 너에게 게임 체인저가 될 거야!

2025년 현재, 영상 편집과 모션 그래픽 분야에서 자동화와 효율성은 선택이 아닌 필수가 되었어. 재능넷에서도 After Effects 스크립팅 능력을 갖춘 크리에이터들의 수요가 꾸준히 증가하고 있지. 이제 ExtendScript를 배워서 너의 창의적 작업 흐름을 한 단계 업그레이드할 시간이야! 🚀

📋 목차

  1. ExtendScript란 무엇인가?
  2. 개발 환경 설정하기
  3. After Effects 객체 모델 이해하기
  4. 기본 스크립트 작성법
  5. 실전 예제: 유용한 스크립트 만들기
  6. 디버깅과 문제 해결
  7. 스크립트 배포 및 공유하기
  8. 고급 기법과 팁
  9. 자주 묻는 질문들
  10. 결론 및 다음 단계

1. ExtendScript란 무엇인가? 🤔

ExtendScript는 Adobe 애플리케이션을 자동화하기 위한 JavaScript의 확장 버전이야. 특히 After Effects에서는 이 스크립팅 언어를 통해 거의 모든 작업을 자동화할 수 있어. 간단한 버튼 클릭부터 복잡한 애니메이션 생성까지, 상상하는 거의 모든 것을 코드로 구현할 수 있지!

ExtendScript의 주요 특징

🔹 JavaScript 기반: 이미 JavaScript를 알고 있다면, 학습 곡선이 훨씬 완만할 거야.

🔹 Adobe 전용 객체 모델: After Effects의 내부 구조에 접근할 수 있는 특별한 객체와 메서드를 제공해.

🔹 크로스 플랫폼: Windows와 macOS 모두에서 동일하게 작동해.

🔹 UI 생성 가능: 사용자 인터페이스를 만들어 더 직관적인 스크립트를 개발할 수 있어.

🔹 파일 시스템 접근: 컴퓨터의 파일 시스템에 접근하여 파일을 읽고 쓸 수 있어.

왜 ExtendScript를 배워야 할까?

⏱️ 시간 절약 반복 작업 자동화로 작업 시간 90%까지 단축 🔄 작업 일관성 인간의 실수 없이 항상 동일한 품질 유지 💡 창의성 향상 지루한 작업은 스크립트에게 창의적인 일에 집중 💰 수익성 더 많은 프로젝트 처리 스크립트 자체를 판매 가능 🏆 경쟁력 강화 차별화된 기술력으로 시장에서 우위 확보

재능넷 같은 플랫폼에서 활동하는 모션 디자이너나 영상 편집자라면, ExtendScript 능력은 엄청난 경쟁력이 될 수 있어. 클라이언트의 특별한 요구사항을 빠르게 처리하거나, 반복적인 작업을 자동화해서 더 많은 프로젝트를 수주할 수 있으니까! 😉

2. 개발 환경 설정하기 🛠️

ExtendScript로 작업을 시작하기 전에, 먼저 적절한 개발 환경을 설정해야 해. 걱정 마! 생각보다 훨씬 간단하니까.

필요한 도구들

1. ExtendScript Toolkit (ESTK) - Adobe의 공식 ExtendScript 개발 환경이야. 하지만 2019년 이후로는 더 이상 새 버전이 나오지 않고 있어. 그래도 여전히 많은 개발자들이 사용하고 있지.

2. Visual Studio Code + ExtendScript 확장 프로그램 - 요즘 가장 인기 있는 방법이야. VS Code에 ExtendScript Debugger 확장 프로그램을 설치하면 현대적인 개발 환경에서 작업할 수 있어.

3. 기본 텍스트 에디터 - 심지어 메모장이나 TextEdit 같은 기본 텍스트 에디터로도 스크립트를 작성할 수 있어. 단, 코드 하이라이팅이나 디버깅 기능은 없지만!

VS Code로 개발 환경 설정하기

가장 추천하는 방법인 VS Code 설정 방법을 자세히 알아볼게:

  1. VS Code 설치 - https://code.visualstudio.com/에서 다운로드
  2. ExtendScript Debugger 확장 프로그램 설치 - VS Code의 확장 프로그램 탭에서 "ExtendScript Debugger"를 검색하고 설치
  3. Adobe 애플리케이션 디버깅 활성화 - After Effects의 환경설정에서 "스크립트 디버깅 허용" 옵션을 활성화
  4. 작업 폴더 생성 - 스크립트 프로젝트를 저장할 폴더를 만들고 VS Code에서 열기

💡 Pro Tip: VS Code에서 "Adobe ExtendScript" 확장 프로그램도 함께 설치하면 코드 자동 완성과 문법 하이라이팅 기능을 사용할 수 있어서 개발이 훨씬 편해져!

스크립트 저장 위치

After Effects에서 스크립트를 쉽게 접근할 수 있도록 특정 폴더에 저장해야 해:

Windows:
C:\Program Files\Adobe\Adobe After Effects [버전]\Support Files\Scripts

macOS:
/Applications/Adobe After Effects [버전]/Scripts

ScriptUI 패널로 개발하는 경우에는 "Scripts/ScriptUI Panels" 폴더에 저장하면 돼. 이렇게 하면 After Effects의 Window 메뉴에서 바로 접근할 수 있어!

3. After Effects 객체 모델 이해하기 🧩

ExtendScript로 After Effects를 제어하기 위해서는 After Effects의 객체 모델을 이해하는 것이 중요해. 이건 마치 After Effects의 내부 구조를 이해하는 것과 같아!

핵심 객체 계층 구조

Application Project Item (FootageItem) Item (CompItem) Item (FolderItem) Layer Property

위 다이어그램은 After Effects의 주요 객체 계층 구조를 보여줘. 이제 각 객체에 대해 자세히 알아보자:

주요 객체 설명

1. Application (app) - 모든 것의 시작점. After Effects 애플리케이션 자체를 나타내는 객체야.

var app = new Application();

2. Project - 현재 열려있는 After Effects 프로젝트를 나타내. 모든 항목(아이템)의 컨테이너야.

var project = app.project;

3. Item - 프로젝트 패널에 있는 모든 항목(폴더, 컴포지션, 푸티지)의 기본 클래스야.

  • CompItem - 컴포지션을 나타내는 객체
  • FootageItem - 이미지, 비디오, 오디오 등의 미디어 파일
  • FolderItem - 프로젝트 패널의 폴더
var firstItem = app.project.item(1); // 인덱스는 1부터 시작!

4. Layer - 컴포지션 내의 레이어를 나타내. 텍스트, 솔리드, 쉐이프, 카메라 등 다양한 유형이 있어.

var comp = app.project.activeItem; // 현재 활성화된 컴포지션 var firstLayer = comp.layer(1); // 첫 번째 레이어

5. Property - 레이어의 속성(위치, 스케일, 불투명도 등)을 나타내. 애니메이션의 핵심이야!

var position = firstLayer.transform.position; // 위치 속성

⚠️ 중요: After Effects에서는 인덱스가 0이 아닌 1부터 시작해! 이건 일반적인 JavaScript와 다른 점이니 꼭 기억해둬.

객체 접근 예제

실제로 스크립트에서 이러한 객체들에 어떻게 접근하는지 몇 가지 예제를 통해 알아보자:

// 현재 프로젝트의 첫 번째 컴포지션에 접근
var myComp = app.project.item(1);

// 컴포지션의 모든 레이어 수 확인
var layerCount = myComp.numLayers;
alert("이 컴포지션에는 " + layerCount + "개의 레이어가 있습니다.");

// 첫 번째 레이어의 위치 속성 가져오기
var positionProp = myComp.layer(1).transform.position;

// 위치 값 변경하기
positionProp.setValue([960, 540]); // x=960, y=540으로 설정

이런 식으로 객체 계층 구조를 따라 내려가면서 After Effects의 거의 모든 요소에 접근하고 조작할 수 있어! 😎

4. 기본 스크립트 작성법 ✍️

이제 실제로 ExtendScript를 작성하는 방법을 알아볼게. 기본적인 문법부터 시작해서 점점 복잡한 스크립트로 나아갈 거야.

첫 번째 스크립트: Hello World

모든 프로그래밍 언어의 전통처럼, "Hello World"로 시작해볼게:

// 첫 번째 After Effects 스크립트
alert("Hello World! After Effects 스크립팅의 세계에 오신 것을 환영합니다!");

이 간단한 코드를 저장하고 After Effects에서 실행하면(File > Scripts > Run Script File...) 알림 창이 나타날 거야.

기본 문법과 규칙

ExtendScript는 기본적으로 JavaScript를 기반으로 하지만, 몇 가지 특별한 규칙이 있어:

1. 주석 작성

// 한 줄 주석

/* 
   여러 줄 주석
   이렇게 작성할 수 있어
*/

2. 변수 선언

var myVariable = 10; // 숫자
var myString = "After Effects"; // 문자열
var myBoolean = true; // 불리언
var myArray = [1, 2, 3, 4]; // 배열
var myObject = {name: "Layer 1", type: "Text"}; // 객체

3. 조건문

if (app.project.numItems > 0) {
    alert("프로젝트에 항목이 있습니다!");
} else {
    alert("프로젝트가 비어있습니다. 먼저 컴포지션을 만들어주세요.");
}

4. 반복문

// for 반복문
for (var i = 1; i <= app.project.numItems; i++) {
    alert("항목 " + i + ": " + app.project.item(i).name);
}

// while 반복문
var j = 1;
while (j <= 5) {
    alert("카운트: " + j);
    j++;
}

5. 함수 정의

function createSolidLayer(comp, color, name) {
    var newSolid = comp.layers.addSolid(color, name, comp.width, comp.height, 1);
    return newSolid;
}

// 함수 호출
var myComp = app.project.activeItem;
var redSolid = createSolidLayer(myComp, [1, 0, 0], "빨간 솔리드");

실용적인 첫 스크립트: 레이어 이름 일괄 변경

이제 실제로 유용한 간단한 스크립트를 만들어볼게. 이 스크립트는 선택한 모든 레이어의 이름을 접두사를 붙여 일괄 변경해:

// 선택한 레이어의 이름을 일괄 변경하는 스크립트
function renameSelectedLayers() {
    var comp = app.project.activeItem;
    
    // 활성화된 컴포지션이 없는 경우 체크
    if (!comp || !(comp instanceof CompItem)) {
        alert("컴포지션을 선택해주세요!");
        return;
    }
    
    // 선택된 레이어가 없는 경우 체크
    if (comp.selectedLayers.length === 0) {
        alert("레이어를 하나 이상 선택해주세요!");
        return;
    }
    
    // 사용자에게 접두사 입력 받기
    var prefix = prompt("추가할 접두사를 입력하세요:", "Layer_");
    if (prefix === null) return; // 취소 버튼 누른 경우
    
    // 실행 취소 기능을 위한 그룹화
    app.beginUndoGroup("레이어 이름 일괄 변경");
    
    // 선택된 모든 레이어에 접두사 추가
    for (var i = 0; i < comp.selectedLayers.length; i++) {
        var layer = comp.selectedLayers[i];
        layer.name = prefix + layer.name;
    }
    
    app.endUndoGroup();
    
    alert(comp.selectedLayers.length + "개의 레이어 이름이 변경되었습니다.");
}

// 스크립트 실행
renameSelectedLayers();

이 스크립트는 다음과 같은 중요한 개념들을 보여줘:

  1. 오류 처리 - 컴포지션이나 레이어가 선택되지 않은 경우 확인
  2. 사용자 입력 - prompt() 함수를 사용해 사용자로부터 입력 받기
  3. Undo 그룹화 - beginUndoGroup()과 endUndoGroup()으로 작업을 그룹화해 한 번에 실행 취소 가능
  4. 레이어 조작 - 레이어 속성(이 경우 이름) 변경하기

💡 팁: 항상 app.beginUndoGroup()app.endUndoGroup()을 사용해 스크립트 작업을 그룹화하는 습관을 들이면 좋아. 이렇게 하면 사용자가 Ctrl+Z(Cmd+Z)로 스크립트 작업을 쉽게 취소할 수 있어!

5. 실전 예제: 유용한 스크립트 만들기 🛠️

이제 실제 작업 흐름에서 유용하게 사용할 수 있는 몇 가지 스크립트 예제를 살펴볼게. 이 예제들을 통해 ExtendScript의 실제 활용법을 배울 수 있을 거야!

예제 1: 선택한 레이어에 페이드 인/아웃 효과 적용하기

이 스크립트는 선택한 레이어에 자동으로 페이드 인과 페이드 아웃 효과를 적용해. 매번 키프레임을 수동으로 설정할 필요 없이 한 번의 클릭으로 처리할 수 있지!

function applyFadeInOut() {
    var comp = app.project.activeItem;
    
    if (!comp || !(comp instanceof CompItem)) {
        alert("컴포지션을 선택해주세요!");
        return;
    }
    
    if (comp.selectedLayers.length === 0) {
        alert("레이어를 하나 이상 선택해주세요!");
        return;
    }
    
    // 페이드 지속 시간 설정 (초 단위)
    var fadeDuration = parseFloat(prompt("페이드 지속 시간(초):", "0.5"));
    if (isNaN(fadeDuration) || fadeDuration <= 0) return;
    
    app.beginUndoGroup("페이드 인/아웃 적용");
    
    for (var i = 0; i < comp.selectedLayers.length; i++) {
        var layer = comp.selectedLayers[i];
        var opacity = layer.transform.opacity;
        
        // 레이어의 시작 및 종료 시간
        var startTime = layer.inPoint;
        var endTime = layer.outPoint;
        
        // 페이드 인 키프레임 설정
        opacity.setValueAtTime(startTime, 0); // 시작 시간에 0% 불투명도
        opacity.setValueAtTime(startTime + fadeDuration, 100); // 페이드 인 후 100% 불투명도
        
        // 페이드 아웃 키프레임 설정
        opacity.setValueAtTime(endTime - fadeDuration, 100); // 페이드 아웃 전 100% 불투명도
        opacity.setValueAtTime(endTime, 0); // 종료 시간에 0% 불투명도
        
        // 이징(부드러운 움직임) 설정
        for (var j = 1; j <= opacity.numKeys; j++) {
            opacity.setInterpolationTypeAtKey(j, KeyframeInterpolationType.BEZIER);
        }
    }
    
    app.endUndoGroup();
    alert("페이드 인/아웃이 " + comp.selectedLayers.length + "개의 레이어에 적용되었습니다.");
}

applyFadeInOut();

이 스크립트는 레이어의 불투명도 속성에 키프레임을 자동으로 추가해서 페이드 효과를 만들어내. setValueAtTime() 메서드를 사용해 특정 시간에 특정 값을 설정하고, 베지어 보간법을 적용해 부드러운 페이드 효과를 만들어내지.

예제 2: 텍스트 레이어 일괄 생성기

여러 개의 텍스트 레이어를 한 번에 생성하는 스크립트야. 예를 들어, 목록이나 크레딧을 빠르게 만들 때 유용해!

function createMultipleTextLayers() {
    var comp = app.project.activeItem;
    
    if (!comp || !(comp instanceof CompItem)) {
        alert("컴포지션을 선택해주세요!");
        return;
    }
    
    // 여러 줄의 텍스트 입력 받기
    var inputText = prompt("각 줄을 하나의 텍스트 레이어로 생성합니다.\n여러 줄을 입력하세요:", "텍스트 1\n텍스트 2\n텍스트 3");
    if (!inputText) return;
    
    // 줄바꿈으로 텍스트 분할
    var textLines = inputText.split("\n");
    
    // 텍스트 레이어 간의 수직 간격 (픽셀)
    var verticalSpacing = parseInt(prompt("텍스트 레이어 간 간격(픽셀):", "50"));
    if (isNaN(verticalSpacing)) verticalSpacing = 50;
    
    app.beginUndoGroup("텍스트 레이어 일괄 생성");
    
    var centerX = comp.width / 2;
    var startY = comp.height / 2 - ((textLines.length - 1) * verticalSpacing) / 2;
    
    for (var i = 0; i < textLines.length; i++) {
        if (textLines[i].trim() === "") continue; // 빈 줄 건너뛰기
        
        // 텍스트 레이어 생성
        var textLayer = comp.layers.addText(textLines[i]);
        
        // 텍스트 가운데 정렬
        var textProp = textLayer.property("Source Text");
        var textDocument = textProp.value;
        textDocument.justification = ParagraphJustification.CENTER_JUSTIFY;
        textProp.setValue(textDocument);
        
        // 위치 설정
        var position = textLayer.transform.position;
        position.setValue([centerX, startY + i * verticalSpacing]);
    }
    
    app.endUndoGroup();
    alert(textLines.length + "개의 텍스트 레이어가 생성되었습니다.");
}

createMultipleTextLayers();

이 스크립트는 사용자가 입력한 여러 줄의 텍스트를 각각 별도의 텍스트 레이어로 생성하고, 지정된 간격으로 배치해. 텍스트 속성을 조작하는 방법과 레이어 위치를 설정하는 방법을 보여주는 좋은 예제지!

예제 3: 프로젝트 정리 도우미

이 스크립트는 프로젝트 패널을 정리하는 데 도움을 줘. 미디어 유형별로 폴더를 생성하고 해당 항목들을 분류해:

function organizeProject() {
    var project = app.project;
    
    if (project.numItems === 0) {
        alert("프로젝트에 항목이 없습니다!");
        return;
    }
    
    // 사용자 확인
    if (!confirm("프로젝트 항목을 유형별로 정리하시겠습니까?")) {
        return;
    }
    
    app.beginUndoGroup("프로젝트 정리");
    
    // 폴더 생성 함수
    function createFolder(name) {
        for (var i = 1; i <= project.numItems; i++) {
            if (project.item(i) instanceof FolderItem && project.item(i).name === name) {
                return project.item(i); // 이미 존재하는 폴더 반환
            }
        }
        return project.items.addFolder(name); // 새 폴더 생성
    }
    
    // 유형별 폴더 생성
    var compFolder = createFolder("Compositions");
    var imageFolder = createFolder("Images");
    var videoFolder = createFolder("Videos");
    var audioFolder = createFolder("Audio");
    var otherFolder = createFolder("Other");
    
    // 모든 항목 분류
    for (var i = project.numItems; i >= 1; i--) {
        var item = project.item(i);
        
        // 방금 생성한 폴더는 건너뛰기
        if (item === compFolder || item === imageFolder || 
            item === videoFolder || item === audioFolder || 
            item === otherFolder) {
            continue;
        }
        
        if (item instanceof CompItem) {
            // 컴포지션
            item.parentFolder = compFolder;
        } else if (item instanceof FootageItem) {
            if (item.mainSource instanceof FileSource) {
                var fileType = item.mainSource.file.toString().toLowerCase();
                
                if (/\.(jpg|jpeg|png|gif|tif|tiff|psd|ai|eps)$/i.test(fileType)) {
                    // 이미지 파일
                    item.parentFolder = imageFolder;
                } else if (/\.(mp4|mov|avi|mxf|r3d|braw|wmv)$/i.test(fileType)) {
                    // 비디오 파일
                    item.parentFolder = videoFolder;
                } else if (/\.(mp3|wav|aac|m4a|aif|aiff)$/i.test(fileType)) {
                    // 오디오 파일
                    item.parentFolder = audioFolder;
                } else {
                    // 기타 파일
                    item.parentFolder = otherFolder;
                }
            } else {
                // 솔리드 등의 생성된 푸티지
                item.parentFolder = otherFolder;
            }
        } else if (!(item instanceof FolderItem)) {
            // 폴더가 아닌 기타 항목
            item.parentFolder = otherFolder;
        }
    }
    
    app.endUndoGroup();
    alert("프로젝트가 성공적으로 정리되었습니다!");
}

organizeProject();

이 스크립트는 프로젝트 항목을 분석하고 파일 유형에 따라 적절한 폴더로 분류해. 정규 표현식을 사용해 파일 확장자를 확인하고, parentFolder 속성을 설정해 항목을 이동시키는 방법을 보여줘.

💡 실무 팁: 이런 스크립트들을 버튼 패널로 만들어두면 작업 효율이 크게 향상돼! 재능넷에서 활동하는 영상 편집자라면, 자주 사용하는 스크립트들을 모아 나만의 툴킷을 만들어두는 것도 좋은 방법이야.

6. 디버깅과 문제 해결 🔍

스크립트를 작성하다 보면 오류가 발생하는 건 당연해. 효과적인 디버깅 방법을 알아두면 문제를 빠르게 해결할 수 있어!

기본 디버깅 방법

1. alert() 사용하기 - 가장 간단한 디버깅 방법이야. 변수 값이나 실행 흐름을 확인할 수 있어.

var myValue = 42;
alert("현재 값: " + myValue);

// 객체 내용 확인하기
var layer = app.project.activeItem.layer(1);
alert("레이어 정보: " + JSON.stringify(layer, null, 2));

2. 콘솔 로깅 - ExtendScript Toolkit이나 VS Code의 콘솔에 로그를 출력할 수 있어.

$.writeln("디버그 메시지: 함수 실행 시작");
$.writeln("레이어 수: " + app.project.activeItem.numLayers);

3. try-catch 블록 사용 - 오류를 잡아내고 처리할 수 있어.

try {
    var comp = app.project.activeItem;
    var layer = comp.layer(1000); // 존재하지 않는 레이어 접근 시도
} catch (error) {
    alert("오류 발생: " + error.toString());
}

ExtendScript Toolkit(ESTK) 디버거 사용하기

ESTK를 사용한다면, 강력한 디버깅 도구를 활용할 수 있어:

  1. 중단점(Breakpoints) 설정 - 코드 라인 번호를 클릭해 중단점을 설정할 수 있어.
  2. 변수 조사(Watch) - 특정 변수의 값을 실시간으로 모니터링할 수 있어.
  3. 단계별 실행 - Step Into, Step Over, Step Out 버튼을 사용해 코드를 한 줄씩 실행할 수 있어.
  4. 호출 스택(Call Stack) 확인 - 함수 호출 순서를 추적할 수 있어.

VS Code에서 디버깅하기

VS Code와 ExtendScript Debugger 확장 프로그램을 사용한다면:

  1. launch.json 설정 - After Effects 디버깅을 위한 설정 파일을 만들어야 해.
  2. 중단점 설정 - 코드 라인 왼쪽을 클릭해 중단점을 설정할 수 있어.
  3. 디버그 시작 - F5 키나 디버그 패널의 시작 버튼을 눌러 디버깅을 시작할 수 있어.
  4. 변수 및 호출 스택 확인 - 디버그 패널에서 실시간으로 확인 가능해.

일반적인 오류와 해결 방법

1. "Object is invalid" 오류

이 오류는 존재하지 않는 객체에 접근하려 할 때 발생해. 항상 객체가 유효한지 확인해:

// 잘못된 방법
var comp = app.project.activeItem;
var layer = comp.layer(1); // comp가 null일 수 있음!

// 올바른 방법
var comp = app.project.activeItem;
if (comp && comp instanceof CompItem) {
    var layer = comp.layer(1);
}

2. 인덱스 관련 오류

After Effects에서는 인덱스가 1부터 시작한다는 점을 기억해:

// 잘못된 방법
for (var i = 0; i < comp.numLayers; i++) {
    var layer = comp.layer(i); // 오류! 첫 번째 레이어는 인덱스 1
}

// 올바른 방법
for (var i = 1; i <= comp.numLayers; i++) {
    var layer = comp.layer(i);
}

3. 속성 경로 오류

속성에 접근할 때 정확한 경로를 사용해야 해:

// 잘못된 방법
var position = layer.position; // 직접 접근 불가

// 올바른 방법
var position = layer.transform.position;

⚠️ 주의: 항상 스크립트를 실행하기 전에 작업을 저장하는 습관을 들이자! 특히 개발 중인 스크립트는 After Effects를 충돌시킬 수 있어.

디버깅 체크리스트

스크립트가 작동하지 않을 때 확인할 사항들:

  1. 컴포지션이 선택되어 있는가?
  2. 레이어가 선택되어 있는가?
  3. 인덱스가 범위를 벗어나지 않는가? (1부터 시작함을 기억)
  4. 속성 경로가 정확한가?
  5. 객체가 예상한 유형인가? (instanceof로 확인)
  6. 오타는 없는가?
  7. 괄호나 중괄호가 올바르게 닫혔는가?

7. 스크립트 배포 및 공유하기 🌐

멋진 스크립트를 만들었다면, 다른 사람들과 공유하거나 심지어 판매할 수도 있어! 스크립트를 배포하는 방법과 고려해야 할 사항들을 알아보자.

스크립트 패키징 방법

1. 단일 JSX 파일 - 가장 간단한 형태로, 하나의 .jsx 파일로 스크립트를 배포할 수 있어.

2. 폴더 구조 - 이미지, 아이콘, 추가 라이브러리 등이 필요한 경우 폴더 구조로 배포할 수 있어.

MyScript/
  ├── MyScript.jsx        # 메인 스크립트 파일
  ├── lib/                # 라이브러리 폴더
  │   └── helpers.jsxbin  # 컴파일된 헬퍼 함수들
  └── icons/              # 아이콘 폴더
      └── icon.png        # 스크립트 아이콘

3. ZXP 패키지 - Adobe의 확장 프로그램 형식으로, 설치 프로세스를 간소화할 수 있어.

스크립트 보호하기

상업용 스크립트를 배포할 때는 코드를 보호하는 것이 중요해:

1. JSXBIN으로 컴파일 - ExtendScript Toolkit에서 JSX 파일을 JSXBIN으로 컴파일하면 코드를 읽기 어렵게 만들 수 있어.

// ESTK에서 컴파일하는 코드
var inputFile = File("/path/to/myScript.jsx");
var outputFile = File("/path/to/myScript.jsxbin");
app.compile(inputFile, outputFile);

2. 라이선스 시스템 구현 - 사용자별 라이선스 키를 생성하고 확인하는 시스템을 구현할 수 있어.

3. 온라인 인증 - 스크립트가 인터넷에 접속해 라이선스를 확인하도록 할 수 있어.

사용자 친화적인 문서 작성

스크립트를 공유할 때는 좋은 문서를 함께 제공하는 것이 중요해:

  1. 설치 방법 - 스크립트를 어디에 복사해야 하는지 명확히 설명
  2. 사용 방법 - 스크립트의 기능과 사용법을 단계별로 설명
  3. 예제 영상 - 가능하다면 스크립트 사용법을 보여주는 짧은 영상 제공
  4. FAQ - 자주 묻는 질문과 답변 목록
  5. 연락처 - 사용자가 문제를 보고하거나 질문할 수 있는 방법 제공

스크립트 공유 및 판매 플랫폼

재능넷 한국 최대 재능 공유 플랫폼 스크립트 판매 및 맞춤 개발 의뢰 가능 AEScripts 전문 AE 스크립트 마켓플레이스 국제적인 고객층 높은 인지도 GitHub 오픈소스 공유 무료 배포에 적합 협업 가능 버전 관리 용이

스크립트를 공유하거나 판매할 수 있는 다양한 플랫폼이 있어:

1. 재능넷 - 한국의 대표적인 재능 공유 플랫폼으로, 스크립트를 판매하거나 맞춤형 스크립트 개발 서비스를 제공할 수 있어. 국내 사용자들과 직접 소통하며 작업할 수 있는 장점이 있지!

2. AEScripts & Plugins - After Effects 스크립트와 플러그인 전문 마켓플레이스로, 전 세계 사용자에게 스크립트를 판매할 수 있어.

3. GitHub - 오픈 소스 스크립트를 공유하기에 좋은 플랫폼이야. 다른 개발자들과 협업할 수도 있고, 포트폴리오로 활용할 수도 있어.

4. 개인 웹사이트 - 자신만의 웹사이트를 통해 스크립트를 직접 판매하거나 구독 모델을 운영할 수 있어.

💡 팁: 재능넷에서 After Effects 스크립트 개발 서비스를 제공하면 차별화된 경쟁력을 가질 수 있어! 클라이언트의 특정 요구사항에 맞는 맞춤형 스크립트를 개발해주는 서비스는 높은 부가가치를 창출할 수 있지.

8. 고급 기법과 팁 🔥

이제 ExtendScript의 더 고급 기능들을 살펴보고, 전문가 수준의 스크립트를 작성하는 데 도움이 될 팁들을 알아볼게!

ScriptUI로 사용자 인터페이스 만들기

ExtendScript의 가장 강력한 기능 중 하나는 ScriptUI를 사용해 사용자 정의 인터페이스를 만들 수 있다는 거야. 간단한 대화 상자부터 복잡한 패널까지 다양한 UI를 구현할 수 있어!

// 간단한 ScriptUI 대화 상자 예제
function createUI() {
    var dialog = new Window("dialog", "색상 선택기", undefined);
    dialog.orientation = "column";
    dialog.alignChildren = ["center", "top"];
    dialog.spacing = 10;
    dialog.margins = 16;
    
    // 설명 텍스트
    var staticText = dialog.add("statictext", undefined, "새 솔리드 레이어의 색상을 선택하세요:");
    staticText.alignment = ["center", "top"];
    
    // 색상 그룹
    var colorGroup = dialog.add("group", undefined);
    colorGroup.orientation = "row";
    colorGroup.alignChildren = ["left", "center"];
    colorGroup.spacing = 10;
    
    var redSlider = colorGroup.add("slider", undefined, 50, 0, 100);
    redSlider.minwidth = 100;
    var redValue = colorGroup.add("edittext", undefined, "50");
    redValue.characters = 3;
    
    var greenSlider = colorGroup.add("slider", undefined, 50, 0, 100);
    greenSlider.minwidth = 100;
    var greenValue = colorGroup.add("edittext", undefined, "50");
    greenValue.characters = 3;
    
    var blueSlider = colorGroup.add("slider", undefined, 50, 0, 100);
    blueSlider.minwidth = 100;
    var blueValue = colorGroup.add("edittext", undefined, "50");
    blueValue.characters = 3;
    
    // 미리보기 영역
    var previewGroup = dialog.add("group", undefined);
    previewGroup.preferredSize.width = 200;
    previewGroup.preferredSize.height = 50;
    previewGroup.alignment = ["center", "top"];
    
    // 버튼 그룹
    var buttonGroup = dialog.add("group", undefined);
    buttonGroup.orientation = "row";
    buttonGroup.alignChildren = ["center", "center"];
    buttonGroup.spacing = 10;
    
    var okButton = buttonGroup.add("button", undefined, "확인", {name: "ok"});
    var cancelButton = buttonGroup.add("button", undefined, "취소", {name: "cancel"});
    
    // 이벤트 핸들러
    redSlider.onChanging = function() {
        redValue.text = Math.round(this.value);
        updatePreview();
    };
    greenSlider.onChanging = function() {
        greenValue.text = Math.round(this.value);
        updatePreview();
    };
    blueSlider.onChanging = function() {
        blueValue.text = Math.round(this.value);
        updatePreview();
    };
    
    function updatePreview() {
        var r = redSlider.value / 100;
        var g = greenSlider.value / 100;
        var b = blueSlider.value / 100;
        previewGroup.graphics.backgroundColor = previewGroup.graphics.newBrush(previewGroup.graphics.BrushType.SOLID_COLOR, [r, g, b, 1]);
    }
    
    // 초기 미리보기 업데이트
    updatePreview();
    
    // 대화 상자 표시
    if (dialog.show() == 1) {
        // 확인 버튼을 누른 경우
        return {
            red: redSlider.value / 100,
            green: greenSlider.value / 100,
            blue: blueSlider.value / 100
        };
    } else {
        // 취소 버튼을 누른 경우
        return null;
    }
}

// UI 실행 및 결과 처리
function main() {
    var result = createUI();
    if (result) {
        var comp = app.project.activeItem;
        if (comp && comp instanceof CompItem) {
            app.beginUndoGroup("솔리드 레이어 생성");
            var solid = comp.layers.addSolid(
                [result.red, result.green, result.blue],
                "색상 솔리드",
                comp.width,
                comp.height,
                1
            );
            app.endUndoGroup();
        } else {
            alert("활성화된 컴포지션이 없습니다!");
        }
    }
}

main();

위 코드는 색상 선택기 UI를 만들고, 사용자가 선택한 색상으로 솔리드 레이어를 생성하는 스크립트야. ScriptUI의 다양한 컴포넌트(슬라이더, 텍스트 필드, 버튼 등)와 이벤트 처리 방법을 보여주고 있어.

외부 파일 및 데이터 처리

스크립트에서 외부 파일을 읽고 쓰는 방법을 알면 훨씬 더 강력한 기능을 구현할 수 있어:

// JSON 파일 읽기
function readJSONFile(filePath) {
    var file = new File(filePath);
    if (!file.exists) {
        alert("파일이 존재하지 않습니다: " + filePath);
        return null;
    }
    
    file.open("r");
    var content = file.read();
    file.close();
    
    try {
        return JSON.parse(content);
    } catch (e) {
        alert("JSON 파싱 오류: " + e);
        return null;
    }
}

// JSON 파일 쓰기
function writeJSONFile(data, filePath) {
    var file = new File(filePath);
    
    file.open("w");
    file.write(JSON.stringify(data, null, 2)); // 들여쓰기 포함
    file.close();
    
    return file.exists;
}

// CSV 파일에서 데이터 읽기
function readCSV(filePath, delimiter) {
    delimiter = delimiter || ",";
    var file = new File(filePath);
    var data = [];
    
    if (!file.exists) {
        alert("파일이 존재하지 않습니다: " + filePath);
        return data;
    }
    
    file.open("r");
    while (!file.eof) {
        var line = file.readln();
        var columns = line.split(delimiter);
        data.push(columns);
    }
    file.close();
    
    return data;
}

// 예제: CSV 파일에서 키프레임 데이터 가져오기
function importKeyframesFromCSV() {
    // 파일 선택 대화 상자
    var file = File.openDialog("키프레임 CSV 파일 선택", "CSV:*.csv");
    if (!file) return;
    
    var data = readCSV(file.fsName);
    if (data.length < 2) {
        alert("CSV 파일에 충분한 데이터가 없습니다.");
        return;
    }
    
    var comp = app.project.activeItem;
    if (!comp || !(comp instanceof CompItem)) {
        alert("활성화된 컴포지션이 없습니다!");
        return;
    }
    
    var selectedLayer = comp.selectedLayers[0];
    if (!selectedLayer) {
        alert("레이어를 선택해주세요!");
        return;
    }
    
    app.beginUndoGroup("CSV에서 키프레임 가져오기");
    
    var positionProp = selectedLayer.transform.position;
    positionProp.setValueAtTime(0, [comp.width/2, comp.height/2]); // 초기 위치 설정
    
    // 첫 번째 행은 헤더로 간주하고 건너뜀
    for (var i = 1; i < data.length; i++) {
        var time = parseFloat(data[i][0]); // 첫 번째 열: 시간(초)
        var x = parseFloat(data[i][1]);    // 두 번째 열: X 좌표
        var y = parseFloat(data[i][2]);    // 세 번째 열: Y 좌표
        
        if (!isNaN(time) && !isNaN(x) && !isNaN(y)) {
            positionProp.setValueAtTime(time, [x, y]);
        }
    }
    
    app.endUndoGroup();
    alert("키프레임을 성공적으로 가져왔습니다!");
}

이 예제는 JSON 파일과 CSV 파일을 읽고 쓰는 방법, 그리고 CSV 파일에서 키프레임 데이터를 가져와 레이어에 적용하는 방법을 보여줘. 이런 기능을 활용하면 외부 데이터 소스와 연동하는 강력한 워크플로우를 구축할 수 있어!

표현식(Expressions) 자동화

After Effects의 표현식을 스크립트로 자동 생성하고 적용하는 방법도 알아두면 유용해: