개요
JavaScript는 Fess 15.9 이후의 기본 스크립트 언어입니다. Fess가 DI XML 식 판정에도 사용하고 있는, CodeLibs의 Nashorn 포크인 Sai 위에서 동작하며, 스크립트는 ECMAScript 6로 실행됩니다. 식별자는 javascript이며, js 및 sai라는 별칭으로도 지정할 수 있습니다.
스크립트 평가 방식
Fess의 스크립트 엔진은 스크립트 문자열을 먼저 하나의 「식」으로 컴파일하려고 시도하고, 그것이 구문 오류가 될 경우에만 「문(스테이트먼트)」 블록으로 다시 컴파일합니다.
이 때문에 값을 반환하기만 하는 단순한 식:
과, 최상위 레벨에 return 문을 포함하는 스크립트:
는 모두 문제없이 동작합니다. 후자는 일반적인 JavaScript로는 최상위 레벨의 return이 구문 오류가 되지만, 식으로서의 컴파일에 실패하기 때문에 문 블록으로 다시 해석되어 유효한 스크립트로 실행됩니다.
데이터 스토어 스크립트처럼 한 줄이 하나의 식으로 취급되는 경우에는 여러 문으로 구성된 스크립트를 사용할 수 없습니다. 반면 스케줄 작업처럼 스크립트 전체가 평가되는 경우에는 여러 줄의 문이나 let / const의 변수 선언, 제어 구문을 자유롭게 사용할 수 있습니다.
경고
문 블록으로 컴파일된 스크립트가 값을 반환하는 것은 명시적인 return 을 포함하는 경우 뿐입니다. 스크립트 문자열을 식으로 해석할 수 없는 경우 그 문자열은 함수로 감싸져 문 블록으로 실행되는데, return 이 없는 블록의 평가 결과는 null 이 됩니다. 끝에 세미콜론을 하나 붙이는 것만으로 이 경계를 넘습니다.
| 스크립트 | 결과 | 이유 |
|---|---|---|
content.length() | 11 | 식으로 해석되며, 식의 값이 그대로 결과가 됩니다 |
content.length(); | null | 문 블록으로만 해석되며, return 이 없습니다 |
var x = 1; x + 2 | null | 문 블록으로만 해석되며, return 이 없습니다 |
Groovy에서는 마지막으로 평가된 문의 값이 스크립트의 반환값이 되기 때문에 위 세 가지 모두 값을 반환했습니다. JavaScript에는 이러한 규칙이 없습니다.
이는 이행 과정에서 오류도 로그도 남지 않고, 필드가 조용히 비는 것 외에는 아무런 증상도 나타나지 않는 유일한 차이입니다. 스크립트가 null 을 반환한 데이터 스토어 매핑은 해당 필드를 단순히 설정하지 않습니다. 데이터 스토어의 필드명=식 각 행은 끝에 세미콜론을 붙이지 않은 식으로 작성하고, 스케줄 작업 스크립트에는 반드시 명시적인 return 을 작성하십시오.
기본 구문
아래에서 끝에 세미콜론이 붙어 있지 않은 행은 식 이며, 데이터 스토어의 필드명=식 행을 포함해 어디에서든 사용할 수 있습니다. let / const 선언, if 블록, 반복문은 문 이며, 스케줄 작업처럼 스크립트 전체가 평가되는 경우에만 사용할 수 있습니다. 그 경우에도 값을 반환하려면 명시적인 return 이 필요합니다. 위의 “스크립트 평가 방식” 을 참조하세요.
변수 선언
문자열 조작
컬렉션 조작
조건 분기
반복 처리
데이터 스토어 스크립트
데이터 스토어 설정에서의 스크립트 예입니다.
참고
데이터 스토어 스크립트에서는 필드명=식 의 각 행이 각각 독립된 하나의 식으로 평가됩니다. 따라서 let / const에 의한 변수 선언문이나, 여러 필드를 한꺼번에 설정하는 복수 행의 제어 구문( if 블록 등)은 사용할 수 없습니다. Java 클래스를 이용하는 경우에는 완전 정규화 클래스명(FQCN)을 사용하여 하나의 식으로 기술하고, 조건 분기는 필드별로 삼항 연산자로 기술합니다(예: url=data.published ? data.url : null ). 또한 여기서 사용하는 변수명 data 는 설명을 위한 예시이며, 실제 변수명은 사용하는 데이터 스토어 커넥터에 따라 다릅니다. 자세한 내용은 데이터 저장소 크롤링 를 참조하세요. 식은 끝에 세미콜론을 붙이지 않고 작성하십시오. 문 블록으로만 해석할 수 있는 행의 평가 결과는 null 이 되어 해당 필드가 설정되지 않습니다. 스크립트 평가 방식 을 참조하세요.
기본 매핑
URL 생성
콘텐츠 가공
날짜 처리
사용 가능한 객체
스크립트 실행 컨텍스트에 따라 사용 가능한 객체가 다릅니다.
| 컨텍스트 | 객체 | 설명 |
|---|---|---|
| 모든 컨텍스트 | container | DI 컨테이너. container.getComponent("...") 를 통해 컴포넌트에 접근할 때 사용 |
| 스케줄 작업 | executor | 작업 실행 제어 ( JobExecutor ). 작업 정지 지원에 필요 |
| 데이터 스토어 | (커넥터별) | 각 데이터 스토어가 제공하는 데이터 레코드 변수. 변수명은 커넥터에 따라 다름 |
| 패스 매핑 | url , matcher | 변환 대상 URL 문자열과 정규표현식 매치 결과( Matcher ). 치환 문자열에 등록된 엔진명이 접두사로 붙은 경우( javascript: , 별칭 js: , sai: )에 이용 가능 |
| 문서 부스트 | (문서 필드) | 대상 문서의 각 필드를 변수로 이용 가능(조건식·부스트값 식에서 사용) |
스케줄 작업 스크립트
스케줄 작업에서 사용하는 JavaScript 스크립트 예입니다. 스케줄 작업에서는 container 와 executor 를 사용할 수 있습니다. executor 를 작업의 execute() 메서드에 전달하면 작업 정지 제어가 활성화됩니다.
참고
스케줄 작업 스크립트는 스크립트 전체가 하나의 완전한 스크립트로 평가됩니다. 스크립트 엔진은 먼저 이를 식으로 컴파일하려고 시도하며, 실패한 경우에만 문(스테이트먼트) 블록으로 다시 해석하므로, 여러 줄의 문이나 let / const 선언, 제어 구문, 최상위 레벨의 return 문을 사용할 수 있습니다(자세한 내용은 위의 「스크립트 평가 방식」을 참조). 이후의 “Java 클래스 사용”, “Fess 컴포넌트 접근”, “오류 처리”, “디버그와 로그 출력” 예시도 이 완전한 스크립트 컨텍스트를 전제로 합니다.
크롤 작업 실행
조건부 크롤링
여러 작업을 순서대로 실행
Java 클래스 사용
JavaScript 스크립트 내에서는 Sai(Nashorn)의 Java 상호운용 메커니즘을 통해 Java 표준 라이브러리나 Fess 클래스를 직접 사용할 수 있습니다. JavaScript에는 import 문이 없으므로, 클래스는 항상 완전 정규화 이름(FQCN)으로 기술합니다.
날짜/시간
파일 조작
HTTP 통신
경고
외부 리소스 접근은 성능에 영향을 미치므로 필요 최소한으로 줄이세요.
Fess 컴포넌트 접근
container를 사용하여 Fess 컴포넌트에 접근할 수 있습니다.
시스템 헬퍼
설정값 가져오기
검색 실행
오류 처리
JavaScript에는 import 문이 없으므로 Groovy와 같은 배치 제약이 없습니다. try-catch로 예외를 포착하여 작업의 오류를 제어할 수 있습니다.
디버그와 로그 출력
로그 출력
디버그용 출력
변수의 내용을 빠르게 확인하고 싶을 때는 JSON.stringify로 문자열화하여 로그에 출력하면 편리합니다.
Groovy에서 마이그레이션
기존 Groovy 스크립트를 JavaScript로 이식할 때는 다음 차이점에 주의하세요.
산술 연산의 정밀도
JavaScript의 숫자 연산은 항상 배정밀도 부동소수점으로 처리됩니다. 예를 들어 다음 식은 Groovy에서는 정수 34를 반환하지만, JavaScript에서는 부동소수점수 34.0을 반환합니다.
반면 Java 상호운용으로 호출하는 메서드의 반환값은 Java 쪽 타입이 그대로 유지되므로, content.length()는 계속해서 정수를 반환합니다.
Groovy 전용 구문 재작성
다음의 Groovy 전용 구문은 JavaScript에서는 재작성이 필요합니다.
| Groovy | JavaScript | 설명 |
|---|---|---|
1000L | 1000 | long 타입 리터럴의 L 접미사는 필요 없음(숫자 리터럴을 그대로 기술) |
["a", "b"] as String[] | ["a", "b"] | JavaScript 배열은 |
Java 상호운용
Java 상호운용 표기법 자체는 Nashorn과 동일하며, Groovy와 거의 다르지 않습니다. new java.io.File(...), java.lang.System.getProperty(...), new org.codelibs.fess.job.IndexExportJob()과 같은 완전 정규화 생성자 호출은 그대로 해석됩니다.
ES6 구문
Fess의 JavaScript 엔진은 ECMAScript 6로 동작하므로, let / const, 화살표 함수, 템플릿 리터럴, 구조 분해 할당, for...of, class 등의 ES6 구문을 사용할 수 있습니다. 다만 옵셔널 체이닝( ?. )과 null 병합 연산자 ( ?? )는 ES2020 이후의 구문이므로 사용할 수 없습니다.
모범 사례
단순하게 유지: 복잡한 로직은 피하고 읽기 쉬운 코드 작성
기본값: Elvis 연산자 대신 논리 OR 연산자(
||)를 활용예외 처리: 적절한 try-catch로 예상치 못한 오류 대응
로그 출력: 디버깅하기 쉽도록 로그 출력
성능: 외부 리소스 접근 최소화
숫자 연산: 정수가 필요한 곳에서는 Java 상호운용 메서드 호출 결과를 그대로 사용하거나, 필요에 따라 명시적으로 변환
참고 정보
스크립팅 개요 - 스크립팅 개요
Groovy 스크립트 가이드 - Groovy 스크립트 가이드(플러그인)
데이터 저장소 크롤링 - 데이터 스토어 설정 가이드
스케줄러 - 스케줄러 설정 가이드