Aspectran Parameters Object Notation

APON을 소개합니다.

APON은 구조화된 형식의 데이터를 교환하기 위해 새롭게 개발된 표기법이며, JSON과 비슷한 표기 형식을 가지면서도, YAML처럼 사람이 읽고 쓰기에 더 용이한 특징을 가집니다.

1. APON 이란?

APON(Aspectran Parameters Object Notation)은 구조화된 데이터를 표현하기 위한 경량 데이터 교환 형식입니다. JSON과 유사한 구조를 가지면서도, YAML처럼 사람이 쉽게 읽고 쓸 수 있도록 가독성을 높인 것이 특징입니다.

APON은 특히 Aspectran 프레임워크의 설정 파일을 간결하게 작성하고, 애플리케이션이 설정 값을 정확하게 읽어 들일 수 있도록 설계되었습니다.

주요 특징

  • 뛰어난 가독성: 콤마(,) 대신 줄바꿈으로 항목을 구분하고, 불필요한 따옴표를 생략할 수 있어 코드가 간결하고 명확합니다.
  • 명시적 타입 지원: 값(Value)에 대한 데이터 타입을 직접 명시할 수 있어, 설정 값의 정확성과 안정성을 보장합니다.
  • 계층적 데이터 구조: 중괄호({ })를 사용하여 데이터를 계층적으로 구성할 수 있어 복잡한 설정도 체계적으로 표현할 수 있습니다.
  • 긴 문자열 지원: 여러 줄로 이루어진 텍스트를 쉽게 작성할 수 있는 text 타입을 지원합니다.
  • 주석 지원: # 문자를 사용하여 코드에 대한 설명을 추가할 수 있습니다.

2. 기본 문법

단일 매개변수 (Parameter)

APON의 가장 기본적인 단위는 이름: 값 형식의 단일 매개변수입니다.

name: John Doe
age: 30
city: New York

매개변수 집합(Parameters)

매개변수의 집합은 중괄호({ })로 감싸서 표현합니다. 다른 하위 매개변수를 포함하는 계층적 구조를 가질 수 있습니다.

user: {
  name: John Doe
  age: 30
  address: {
    city: New York
    zipCode: 10001
  }
}

배열 (Array)

배열은 대괄호([ ]) 안에 여러 값을 넣어 표현합니다. 각 요소는 줄바꿈으로 구분합니다.

users: [
  "John"
  "Jane"
  "Peter"
]
numbers: [
  1
  2
  3
]

3. 데이터 타입

APON은 다양한 데이터 타입을 지원하며, 이름(타입): 값의 형태로 타입을 명시할 수 있습니다. 타입을 생략하면 값의 형태에 따라 자동으로 타입이 결정됩니다.

Value TypeJava Object Type예시
stringjava.lang.Stringname(string): Hello, World.
textjava.lang.String아래 text 타입 예제 참조
intjava.lang.Integerage(int): 30
longjava.lang.Longid(long): 12345L
floatjava.lang.Floatscore(float): 95.5f
doublejava.lang.Doublepi(double): 3.14159d
booleanjava.lang.BooleanisAdmin(boolean): true
parameterscom.aspectran.utils.apon.Parameters중첩된 매개변수 구조

text 타입 사용 예제

여러 줄로 구성된 긴 문자열은 text 타입을 사용하면 편리합니다. 괄호(( ))로 감싸고, 각 줄의 시작에 | 문자를 붙여 표현합니다.

description(text): (
    | 이것은 여러 줄로 된 텍스트입니다.
    | 각 줄은 파이프 문자로 시작합니다.
    | 이 블록 안에서는 "따옴표"나 '작은따옴표' 같은
    | 특수문자를 자유롭게 사용할 수 있습니다.
)

4. APON 활용하기

APON 형식의 텍스트를 자바 객체로 변환하거나, 자바 객체를 APON 텍스트로 변환하는 방법을 알아봅니다.

1단계: APON에 매핑될 자바 Parameters 클래스 정의

APON 데이터 구조에 맞춰 자바에서 Parameters 인터페이스를 구현하는 클래스를 정의해야 합니다. 각 클래스는 APON의 계층 구조에 대응되며, ParameterDefinition을 통해 각 파라미터의 이름, 타입, 배열 여부 등을 정의합니다.

예시 APON:

server: {
  name: MyServer
  port: 8080
  features: [
    "HTTP2"
    "SSL"
  ]
}

위 APON에 매핑될 자바 클래스:

RootConfig.java

import com.aspectran.utils.apon.AbstractParameters;
import com.aspectran.utils.apon.ParameterDefinition;
import com.aspectran.utils.apon.ParameterValueType;
import com.aspectran.utils.apon.Parameters;

public class RootConfig extends AbstractParameters implements Parameters {

    public static final ParameterDefinition server;

    private static final ParameterDefinition[] parameterDefinitions;

    static {
        // 다른 Parameter를 포함하는 계층적 구조를 가짐
        naserverme = new ParameterDefinition("server", ServerConfig.class);

        parameterDefinitions = new ParameterDefinition[] {
            server
        };
    }

    public RootConfig() {
        super(parameterDefinitions);
    }
}

ServerConfig.java

import com.aspectran.utils.apon.AbstractParameters;
import com.aspectran.utils.apon.ParameterDefinition;
import com.aspectran.utils.apon.ParameterValueType;
import com.aspectran.utils.apon.Parameters;

public class ServerConfig extends AbstractParameters implements Parameters {

    public static final ParameterDefinition name;
    public static final ParameterDefinition port;
    public static final ParameterDefinition features;

    private static final ParameterDefinition[] parameterDefinitions;

    static {
        name = new ParameterDefinition("name", ParameterValueType.STRING);
        port = new ParameterDefinition("port", ParameterValueType.INT);
        // features 파라미터는 string 타입이며, 여러 값을 가질 수 있는 배열임 (세 번째 인자 true)
        features = new ParameterDefinition("features", ParameterValueType.STRING, true);

        parameterDefinitions = new ParameterDefinition[] {
            name,
            port,
            features
        };
    }

    public ServerConfig() {
        super(parameterDefinitions);
    }
}

2단계: APON 파일 읽기 (AponReader)

AponReader 클래스를 사용하면 APON 형식의 텍스트 파일을 읽어 정의된 Parameters 자바 객체로 변환할 수 있습니다.

import com.aspectran.utils.apon.AponReader;
import com.aspectran.utils.apon.Parameters;
import java.io.FileReader;
import java.io.Reader;

public class AponTest {
    public static void main(String[] args) {
        try {
            // 1. APON 파일을 읽기 위한 Reader 생성
            Reader fileReader = new FileReader("root-config.apon");

            // 2. APON 구조에 맞게 정의된 최상위 Parameters 객체 생성
            Parameters rootParams = new RootConfig(); // RootConfig는 server 파라미터를 포함

            // 3. AponReader를 사용하여 파일 내용을 Parameters 객체로 읽어들임
            AponReader.read(fileReader, rootParams);

            // 4. 변환된 객체 사용
            Parameters serverConfig = rootParams.getParameters("server");
            String serverName = serverConfig.getString("name");
            int port = serverConfig.getInt("port");

            System.out.println("Server Name: " + serverName);
            System.out.println("Port: " + port);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3단계: APON 파일 생성하기 (AponWriter)

AponWriter 클래스를 사용하면 Parameters 자바 객체를 APON 형식의 문자열로 쉽게 변환할 수 있습니다.

import com.aspectran.utils.apon.AponWriter;
import com.aspectran.utils.apon.Parameters;
import java.io.StringWriter;
import java.io.Writer;

public class AponWriteTest {
    public static void main(String[] args) {
        try {
            // 1. APON으로 변환할 Parameters 객체 생성 및 값 설정
            Parameters serverConfig = new ServerConfig();
            serverConfig.putValue("name", "NewServer");
            serverConfig.putValue("port", 9090);
            serverConfig.putValue("features", new String[] {"WebService", "Security"});

            Parameters rootParams = new RootConfig(); // RootConfig는 server 파라미터를 포함
            rootParams.putValue("server", serverConfig);

            // 2. APON 텍스트를 저장할 Writer 생성
            Writer writer = new StringWriter();

            // 3. AponWriter를 사용하여 Parameters 객체를 APON 형식으로 씀
            try (AponWriterCloseable aponWriter = new AponWriterCloseable(writer)) {
                aponWriter.write(rootParams);
            }

            // 4. 변환된 APON 문자열 출력
            System.out.println(writer.toString());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

출력 결과:

server: {
  name: NewServer
  port: 9090
  features: [
    WebService
    Security
  ]
}

5. 라이브러리 정보

APON 관련 클래스들은 Aspectran 프레임워크의 공통 유틸리티 패키지에 포함되어 있습니다.

Source