개발 가이드

언어 분석 API 란?

자연어 문장의 의미를 이해하기 위한 기술로, 단어의 형태와 의미 및 문장의 구조와 의미를 분석하여 지식처리를 위한 기반 기술로 활용됩니다. 언어 분석 API는 HTTP 기반의 REST API 인터페이스로 JSON 포맷 기반의 입력 및 출력을 지원하며 ETRI에서 제공하는 Access Key 인증을 통해 사용할 수 있는 Open API 입니다.

언어 분석 API는 요청되는 분석 코드에 따라 형태소 분석, 어휘의미 분석(동음이의어 분석, 다의어 분석), 개체명 인식, 의존 구문분석, 의미역 인식 결과를 제공합니다.

형태소 분석

형태소 분석은 자연어 문장에서 의미를 가진 최소 단위인 형태소(명사, 동사, 형용사, 부사, 조사, 어미 등)를 분석하는 기술로, 태그셋은 세종 태그셋을 기반으로 한 TTA 표준 형태소 태그셋 (TTAK.KO-11.0010/R1)에 기반합니다.

어휘의미 분석 (동음이의어 분석, 다의어 분석)

어휘의미 분석 (동음이의어 분석, 다의어 분석)은 어휘의 형태는 동일하지만 의미가 다른 어휘에 대해서 의미를 분석해 주는 기술로, 주변 문맥을 고려해서 가장 적합한 의미를 찾아 표준국어대사전을 기반으로 한 단어의 의미 분석 결과를 제공합니다.

개체명 인식 기술

개체명 인식 기술은 인명, 지명, 기관명 등과 같은 개체명을 인식하는 기술로, 특정 개체를 표현하는 단어에 대한 의미 정보를 제공합니다. 개체명 태그셋은 15개 대분류 및 146개 세분류로 구성된 TTA 표준 개체명 태그셋 (TTAK.KO-10.0852)을 사용합니다.

의존 구문분석 기술

의존 구문분석 기술은 자연어 문장의 구조를 분석하는 기술로, 문장 내 각 어절에 대해서 지배소 어절을 인식하고, 주격, 목적격과 같은 세부 의존관계 유형을 인식하는 기술입니다. 의존관계 설정 가이드라인은 세종 구문분석 가이드라인을 기반으로 한 TTA 표준 의존 구문분석 가이드라인 (TTAK.KO-10.0853)과 제27회 한글 및 한국어 정보처리 학술대회 논문집의 “의존 구문분석을 위한 한국어 의존관계 가이드라인 및 엑소브레인 언어분석 말뭉치”[1]를 따르고 있습니다.

의미역 인식 기술

의미역 인식 기술은 서술어(predicate)와 논항(argument)의 관계를 기반으로 문장의 의미를 분석하는 기술로, 문장 내에서 표현된 각 서술어에 대해서 필수 논항(core argument)와 부가 논항(adverbal argument)를 인식합니다. 의미역 체계는 Proposition Bank(Propbank)[2] 체계를 따르고 있으며, 한국어 의미역 태깅 가이드라인은 제27회 한글 및 한국어 정보처리 학술대회 논문집의 “ExoBrain을 위한 의미역 가이드라인 및 말뭉치 구축”[3]를 따르고 있습니다.

사전 준비 사항

언어 분석 API를 사용하려면 ETRI 인공지능 Open API 서비스에서 개발자 계정 등록 해야 합니다. 개발자 계정 등록 이후 API 사용 신청을 통해 API 사용시 필요한 인증 정보를 획득해야 합니다.

  1. “ETRI AI” 홈페이지의 [Open API 사용신청] 페이지로 이동합니다.
  2. [Open API 사용신청] 페이지의 키 발급 신청하기 버튼을 클릭합니다.
  3. Open API의 Access Key 발급에 필요한 사용 신청 정보를 입력 후 등록하기 버튼을 클릭합니다.
    (등록된 사용 신청은 “ETRI AI” 관리자에 의해서 승인이 필요합니다.)
  4. [Open API 사용신청] 페이지의 키 발급 신청확인 버튼을 클릭합니다.
  5. 키 발급 신청에 입력한 “이메일”와 “패스워드”를 입력 후 API KEY 확인하기 버튼을 클릭합니다.
  6. 발급된 Open API의 Access Key를 확인합니다.
언어 분석 API 사용하기

언어 분석 API는 REST API이며, 언어 분석을 수행할 텍스트 데이터를 HTTP 통신으로 ETRI 인공지능 Open API 서버에 전달하면 됩니다. 서버가 제공하는 REST API의 URI는 다음과 같으며 POST 방식으로 호출해야 합니다.

http://aiopen.etri.re.kr:8000/WiseNLU

HTTP 요청으로 언어 분석을 요청할 때 사전 준비 사항에서 발급받은 Access key 정보를 요청하는 본문에 포함시켜야 합니다. 다음은 HTTP 요청 메시지 예입니다.

                                
[HTTP Request Body]
{
    "request_id": "reserved field",
    "access_key": “YOUR_ACCESS_KEY”,
    "argument": {
        “analysis_code”: “ANALYSIS_CODE”
        "text": “YOUR_SENTENCE”
    }
}
                                
                            

위와 같은 HTTP 요청을 ETRI 인공지능 Open API 서버로 전달하면 서버는 JSON 형태의 Text 데이터를 HTTP 응답 메시지로 반환합니다. 다음은 HTTP 응답 예제 입니다.

                                
[HTTP Response Header]
Access-Control-Allow-Origin:*
Connection:close
Content-Length:0
Content-Type:application/json; charset=UTF-8

[HTTP Response Body]
{
    "request_id": "reserved field",
    "result": 0,
    "return_type": "kr.re.etri.aiopen.restapi.client.dto.OpenApiLmInterfaceResult",
    "return_object": {언어 분석 결과 JSON}
}

                                
                            
구현 예제
Java

JSON parsing을 위해 Gson 라이브러리를 사용하여 제공하고 있습니다. Gson 라이브러리에 대한 자세한 설명은 https://github.com/google/gson 에서 확인 하실 수 있습니다.

import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.Gson;

public class Example {

    static public void main ( String[] args ) {
        String openApiURL = "http://aiopen.etri.re.kr:8000/WiseNLU";
        String accessKey = "YOUR_ACCESS_KEY";    // 발급받은 Access Key
        String analysisCode = "ANALYSIS_CODE";   // 언어 분석 코드
        String text = "YOUR_SENTENCE";           // 분석할 텍스트 데이터
        Gson gson = new Gson();

        Map<String, Object> request = new HashMap<>();
        Map<String, String> argument = new HashMap<>();

        argument.put("analysis_code", analysisCode);
        argument.put("text", text);

        request.put("access_key", accessKey);
        request.put("argument", argument);


        URL url;
        Integer responseCode = null;
        String responBody = null;
        try {
            url = new URL(openApiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setRequestMethod("POST");
            con.setDoOutput(true);

            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            wr.write(gson.toJson(request).getBytes("UTF-8"));
            wr.flush();
            wr.close();

            responseCode = con.getResponseCode();
            InputStream is = con.getInputStream();
            byte[] buffer = new byte[is.available()];
            int byteRead = is.read(buffer);
            responBody = new String(buffer);

            System.out.println("[responseCode] " + responseCode);
            System.out.println("[responBody]");
            System.out.println(responBody);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
                                        
PHP
<?php
$openApiURL = "http://aiopen.etri.re.kr:8000/WiseNLU";
$accessKey = "YOUR_ACCESS_KEY";
$analysisCode = "ANALYSIS_CODE";
$text = "YOUR_SENTENCE";

$request = array(
    "access_key" => $accessKey,
    "argument" => array (
        "analysis_code" => $analysisCode,
        "text" => $text
    )
);

try {
    $server_output = "";
    $ch = curl_init();
    $header = array(
        "Content-Type:application/json; charset=UTF-8",
    );
    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
    curl_setopt($ch, CURLOPT_URL, $openApiURL);
    curl_setopt($ch, CURLOPT_VERBOSE, true);
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode ( $request) );

    $server_output = curl_exec ($ch);
    if($server_output === false) {
        echo "Error Number:".curl_errno($ch)."\n";
        echo "Error String:".curl_error($ch)."\n";
    }

    curl_close ($ch);
} catch ( Exception $e ) {
    echo $e->getMessage ();
}

echo "result = " . var_dump($server_output);
?>                                            
C++

JSON parsing을 위해 jsoncpp 라이브러리를 사용하여 제공하고 있습니다. jsoncpp 라이브러리에 대한 자세한 설명은 https://github.com/open-source-parsers/jsoncpp 에서 확인 하실 수 있습니다.

HTTP 통신을 위해 curl 라이브러리를 사용하여 제공하고 있습니다. curl 라이브러리에 대한 자세한 설명은 https://curl.haxx.se/libcurl 에서 확인 하실 수 있습니다.

컴파일을 위해서는 아래와 같이 추가된 LIB에 대한 옵션을 추가해야 합니다.
g++ (c++파일명) (JOSNCPP)/json/json.h (JOSNCPP)/json/json-forwards.h (JOSNCPP)/jsoncpp.cpp ?I(CURL)/include -lcurl

#include <curl/curl.h>
#include <json/json.h>
#include <iostream>
#include <string>

using namespace std;

size_t writeDataFunc(void *ptr, size_t size, size_t nmemb, std::string stream);

int main() {
    char* openApiURL = (char*)"http://aiopen.etri.re.kr:8000/WiseNLU";
    string accessKey = "YOUR_ACCESS_KEY";
    string analysisCode = "ANALYSIS_CODE";
    string text = "YOUR_SENTENCE";

    Json::Value request;
    Json::Value argument;

    argument["text"] = text;
    argument["analysis_code"] = analysisCode;

    request["access_key"] = accessKey;
    request["argument"] = argument;

    CURL *curl;
    curl_slist* responseHeaders = NULL;
    curl = curl_easy_init();

    if( curl == NULL ) {
        cout << "Unable to initialize cURL interface" << endl ;
    } else {
        responseHeaders = curl_slist_append( responseHeaders , "Content-Type: application/json; charset=UTF-8" ) ;
        string requestJson = request.toStyledString();
        long statusCode;
        string response;

        curl_easy_setopt(curl, CURLOPT_URL, openApiURL);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, responseHeaders ) ;
        curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5);
        curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, requestJson.c_str());
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writeDataFunc);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response);

        curl_easy_perform(curl);

        curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &statusCode);
        curl_easy_cleanup(curl);

        cout << "[responseCode] " << statusCode << endl;
        cout << "[responBody]" << endl;
        cout << response << endl;
    }

    return 0;
}

size_t writeDataFunc(void *ptr, size_t size, size_t nmemb, std::string stream) {
    size_t realsize = size * nmemb;
    std::string temp(static_cast<const char*>(ptr), realsize);
    stream.append(temp);
    return realsize;
}                                            
Python

python 3.0을 기준으로 작성되었습니다.

HTTP 통신을 위해 urllib3 라이브러리를 사용하여 제공하고 있습니다. Python 3.0 이하의 버전에서 예제를 실행하기 위해서는 별도로 urllib3의 설치가 필요합니다. 설치에 대한 설명은 https://pypi.python.org/pypi/urllib3 를 참고하시기 바랍니다. urllib3 라이브러리에 대한 자세한 설명은 https://urllib3.readthedocs.io/en/latest/ 에서 확인 하실 수 있습니다.

#-*- coding:utf-8 -*-
import urllib3
import json

openApiURL = "http://aiopen.etri.re.kr:8000/WiseNLU"
accessKey = "YOUR_ACCESS_KEY"
analysisCode = "ANALYSIS_CODE"
text = "YOUR_SENTENCE"

requestJson = {
    "access_key": accessKey,
    "argument": {
        "text": text,
        "analysis_code": analysisCode
    }
}

http = urllib3.PoolManager()
response = http.request(
    "POST",
    openApiURL,
    headers={"Content-Type": "application/json; charset=UTF-8"},
    body=json.dumps(requestJson)
)

print("[responseCode] " + str(response.status))
print("[responBody]")
print(str(response.data,"utf-8"))
                                       
Node.js
var openApiURL = 'http://aiopen.etri.re.kr:8000/WiseNLU';
var access_key = 'YOUR_ACCESS_KEY';
var analysisCode = 'ANALYSIS_CODE';
var text = 'YOUR_SENTENCE';

var requestJson = {
    'access_key': access_key,
    'argument': {
        'text': text,
        'analysis_code': analysisCode
    }
};

var request = require('request');
var options = {
    url: openApiURL,
    body: JSON.stringify(requestJson),
    headers: {'Content-Type':'application/json; charset=UTF-8'}
};
request.post(options, function (error, response, body) {
    console.log('responseCode = ' + response.statusCode);
    console.log('responseBody = ' + body);
});
                                        
활용 예제

형태소 분석 결과에 대해서 문장에 쓰여진 명사와 동사를 분석하여 많이 사용된 순으로 최대 5개를 출력하는 예제 입니다.

해당 예제는 Java 1.8 기준으로 작성되었습니다.
Java에 대한 자세한 설명은 http://www.oracle.com/technetwork/java/index.html 에서 확인 하실 수 있습니다.

JSON parsing을 위해 Gson 라이브러리를 사용하여 제공하고 있습니다.
Gson 라이브러리에 대한 자세한 설명은 https://github.com/google/gson 에서 확인 하실 수 있습니다.

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;

public class WiseNLUExample {
	static public class Morpheme {
		final String text;
		final String type;
		Integer count;
		public Morpheme (String text, String type, Integer count) {
			this.text = text;
			this.type = type;
			this.count = count;
		}
	}
	static public class NameEntity {
		final String text;
		final String type;
		Integer count;
		public NameEntity (String text, String type, Integer count) {
			this.text = text;
			this.type = type;
			this.count = count;
		}
	}

	static public void main(String[] args) {
		String openApiURL = "http://aiopen.etri.re.kr:8000/WiseNLU";
		String accessKey = "YOUR_ACCESS_KEY";	// 발급받은 Access Key
		String analysisCode = "ner";		// 언어 분석 코드
		String text = "";			// 분석할 텍스트 데이터
		Gson gson = new Gson();

		text += "윤동주(尹東柱, 1917년 12월 30일 ~ 1945년 2월 16일)는 한국의 독립운동가, 시인, 작가이다." +
				"중국 만저우 지방 지린 성 연변 용정에서 출생하여 명동학교에서 수학하였고, 숭실중학교와 연희전문학교를 졸업하였다. 숭실중학교 때 처음 시를 발표하였고, 1939년 연희전문 2학년 재학 중 소년(少年) 지에 시를 발표하며 정식으로 문단에 데뷔했다." +
				"일본 유학 후 도시샤 대학 재학 중 , 1943년 항일운동을 했다는 혐의로 일본 경찰에 체포되어 후쿠오카 형무소(福岡刑務所)에 투옥, 100여 편의 시를 남기고 27세의 나이에 옥중에서 요절하였다. 사인이 일본의 생체실험이라는 견해가 있고 그의 사후 일본군에 의한 마루타, 생체실험설이 제기되었으나 불확실하다. 사후에 그의 시집 《하늘과 바람과 별과 시》가 출간되었다." +
				"일제 강점기 후반의 양심적 지식인으로 인정받았으며, 그의 시는 일제와 조선총독부에 대한 비판과 자아성찰 등을 소재로 하였다. 그의 친구이자 사촌인 송몽규 역시 독립운동에 가담하려다가 체포되어 일제의 생체 실험으로 의문의 죽음을 맞는다. 1990년대 후반 이후 그의 창씨개명 '히라누마'가 알려져 논란이 일기도 했다. 본명 외에 윤동주(尹童柱), 윤주(尹柱)라는 필명도 사용하였다.";

		Map<String, Object> request = new HashMap<>();
		Map<String, String> argument = new HashMap<>();

		argument.put("analysis_code", analysisCode);
		argument.put("text", text);

		request.put("access_key", accessKey);
		request.put("argument", argument);

		URL url;
		Integer responseCode = null;
		String responBodyJson = null;
		Map<String, Object> responeBody = null;

		try {
			url = new URL(openApiURL);
			HttpURLConnection con = (HttpURLConnection) url.openConnection();
			con.setRequestMethod("POST");
			con.setDoOutput(true);

			DataOutputStream wr = new DataOutputStream(con.getOutputStream());
			wr.write(gson.toJson(request).getBytes("UTF-8"));
			wr.flush();
			wr.close();

			responseCode = con.getResponseCode();
			InputStream is = con.getInputStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(is));
			StringBuffer sb = new StringBuffer();

	        String inputLine = "";
	        while ((inputLine = br.readLine()) != null) {
	            sb.append(inputLine);
	        }
	        responBodyJson = sb.toString();

	        // http 요청 오류 시 처리
 			if ( responseCode != 200 ) {
 				// 오류 내용 출력
 				System.out.println("[error] " + responBodyJson);
 				return ;
 			}

			responeBody = gson.fromJson(responBodyJson, Map.class);
			Integer result = ((Double) responeBody.get("result")).intValue();
			Map<String, Object> returnObject;
			List<Map> sentences;

			// 분석 요청 오류 시 처리
			if ( result != 0 ) {

				// 오류 내용 출력
				System.out.println("[error] " + responeBody.get("result"));
				return ;
			}

			// 분석 결과 활용
			returnObject = (Map<String, Object>) responeBody.get("return_object");
			sentences = (List<Map>) returnObject.get("sentence");

			Map<String, Morpheme> morphemesMap = new HashMap<String, Morpheme>();
			Map<String, NameEntity> nameEntitiesMap = new HashMap<String, NameEntity>();
			List<Morpheme> morphemes = null;
			List<NameEntity> nameEntities = null;

			for( Map<String, Object> sentence : sentences ) {
				// 형태소 분석기 결과 수집 및 정렬
				List<Map<String, Object>> morphologicalAnalysisResult = (List<Map<String, Object>>) sentence.get("morp");
				for( Map<String, Object> morphemeInfo : morphologicalAnalysisResult ) {
					String lemma = (String) morphemeInfo.get("lemma");
					Morpheme morpheme = morphemesMap.get(lemma);
					if ( morpheme == null ) {
						morpheme = new Morpheme(lemma, (String) morphemeInfo.get("type"), 1);
						morphemesMap.put(lemma, morpheme);
					} else {
						morpheme.count = morpheme.count + 1;
					}
				}

				// 개체명 분석 결과 수집 및 정렬
				List<Map<String, Object>> nameEntityRecognitionResult = (List<Map<String, Object>>) sentence.get("NE");
				for( Map<String, Object> nameEntityInfo : nameEntityRecognitionResult ) {
					String name = (String) nameEntityInfo.get("text");
					NameEntity nameEntity = nameEntitiesMap.get(name);
					if ( nameEntity == null ) {
						nameEntity = new NameEntity(name, (String) nameEntityInfo.get("type"), 1);
						nameEntitiesMap.put(name, nameEntity);
					} else {
						nameEntity.count = nameEntity.count + 1;
					}
				}
			}

			if ( 0 < morphemesMap.size() ) {
				morphemes = new ArrayList<Morpheme>(morphemesMap.values());
				morphemes.sort( (morpheme1, morpheme2) -> {
					return morpheme2.count - morpheme1.count;
				});
			}

			if ( 0 < nameEntitiesMap.size() ) {
				nameEntities = new ArrayList<NameEntity>(nameEntitiesMap.values());
				nameEntities.sort( (nameEntity1, nameEntity2) -> {
					return nameEntity2.count - nameEntity1.count;
				});
			}

			// 형태소들 중 명사들에 대해서 많이 노출된 순으로 출력 ( 최대 5개 )
			morphemes
				.stream()
				.filter(morpheme -> {
					return morpheme.type.equals("NNG") ||
							morpheme.type.equals("NNP") ||
							morpheme.type.equals("NNB");
				})
				.limit(5)
				.forEach(morpheme -> {
					System.out.println("[명사] " + morpheme.text + " ("+morpheme.count+")" );
				});

			// 형태소들 중 동사들에 대해서 많이 노출된 순으로 출력 ( 최대 5개 )
			System.out.println("");
			morphemes
				.stream()
				.filter(morpheme -> {
					return morpheme.type.equals("VV");
				})
				.limit(5)
				.forEach(morpheme -> {
					System.out.println("[동사] " + morpheme.text + " ("+morpheme.count+")" );
				});

			// 인식된 개채명들 많이 노출된 순으로 출력 ( 최대 5개 )
			System.out.println("");
			nameEntities
				.stream()
				.limit(5)
				.forEach(nameEntity -> {
					System.out.println("[개체명] " + nameEntity.text + " ("+nameEntity.count+")" );
				});
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
                            
분석된 결과
[명사] 시 (5)
[명사] 학교 (4)
[명사] 중 (4)
[명사] 년 (4)
[명사] 일본 (4)

[동사] 의하 (1)
[동사] 알려지 (1)
[동사] 남기 (1)
[동사] 맞 (1)

[개체명] 일본 (3)
[개체명] 시 (2)
[개체명] 숭실중학교 (2)
[개체명] 윤동주 (2)
[개체명] 일제 (2)

                            
언어 분석 API 레퍼런스
요청 파라미터

언어 분석 API에 필요한 요청 본문에 다음과 같은 파라미터를 작성해야 합니다.

                                            
[HTTP Request Body]
{
    “access_key”: “YOUR_ACCESS_KEY”,
    “argument”: {
        “analysis_code”: “ANALYSIS_CODE”
        “text”: “YOUR_SENTENCE”
    }
}
                                            
                                        

다음은 파라미터에 대한 설명입니다.

Field 명 타입 필수 여부 설명
access_key String API 사용을 위해 ETRI에서 발급한 사용자 Access Key
argument Object API 사용 요청 시 분석을 위해 전달할 내용
analysis_code String 요청할 분석 코드로서 요청할 수 있는 분석 요청은 아래와 같음
형태소 분석 : “morp”,
어휘의미 분석 (동음이의어 분석) : “wsd”
어휘의미 분석 (다의어 분석) : “wsd_poly”
개체명 인식 : “ner”
의존 구문 분석 : “dparse”
의미역 인식 : “srl”
text String 분석할 자연어 문장으로서 UTF-8 인코딩된 텍스트만 지원
응답

언어 분석 API는 요청된 자연어 문장의 분석된 결과를 JSON 형태의 Text 데이터로 반환합니다. 분선된 결과는 입력된 analysis_code에 따라 의존성이 있는 분석 처리 결과를 포함하며, 포함되는 내용은 아래와 같습니다.

분석 명 분석 코드 포함되는 내용
형태소 분속 morp 형태소 분석 결과
어휘의미 분석
(동음이의어)
wsd 형태소 분석 결과, 어휘의미 분석 결과 (동음이의어 분석)
(동음이의어에 대한 상세정보 조회는 동음이의어 정보 API 사용)
어휘의미 분석
(다의어)
wsd_poly 형태소 분석 결과, 어휘의미 분석 결과 (다의어 분석)
(다의어에 대한 상세정보 조회는 다의어 정보 API 사용)
개체명 인식 ner 형태소 분석 결과, 어휘의미 분석 결과 (동음이의어 분석), 개체명 인식 결과
의존 구문 분석 dparse 형태소 분석 결과, 어휘의미 분석 결과 (동음이의어 분석), 개체명 인식 결과, 의존 구문 분석 결과
의미역 인식 srl 형태소 분석 결과, 어휘의미 분석 결과 (동음이의어 분석), 개체명 인식 결과, 의존 구문 분석 결과, 의미역 인식 결과

다음은 정상적인 요청 처리에 대한 HTTP 응답 예입니다.

                                            
[HTTP Response Header]
Access-Control-Allow-Origin:*
Connection:close
Content-Length:0
Content-Type:application/json; charset=UTF-8

[HTTP Response Body]
{
"request_id": "reserved field",
"result": 0,
"return_type": "com.google.gson.internal.LinkedTreeMap
"return_object": {언어 분석 결과 JSON}
}
                                            
                                        

다음은 오류가 발생한 요청 처리에 대한 HTTP 응답 예입니다.

                                            
[HTTP Response Header]
Access-Control-Allow-Origin:*
Connection:close
Content-Length:0
Content-Type:application/json; charset=UTF-8

[HTTP Response Body]
{
"request_id": "reserved field",
"result": -1,
"reason": {오류 메시지}
}
                                            
                                        

분석된 결과는 다음과 같은 내용이 포함되어 있습니다.

구분 세부 구분 JSON Key 이름 설명
sentence   id 분석한 문장 번호
reserve_str 예비 공간으로 현재는 사용 안함.
text 분석한 원 문장
morp 형태소 분석 결과
id 형태소 ID (출현 순서)
lemma 형태소
type 형태소 태그
position 문장에서의 byte position
weight 형태소 분석 결과 신뢰도
WSD 어휘의미 분석 결과
id WSD 대상 ID (출현 순서)
text WSD 대상 어휘 텍스트
type 어휘 형태소 태그
scode 어휘의 표준국어대사전 어깨번호
(동형이의어 분석 시 2자리, 다의어 분석 시 6자리)
weight 어휘의 어휘의미 분석 결과 신뢰도
position 문장에서의 byte position
begin 어휘의 첫 형태소의 ID
end 어휘의 끝 형태소의 ID
word 어절 정보 분석 결과
id 어절의 ID (출현 순서)
text 어절의 대상 텍스트
type 어절 타입
begin 어절을 구형하는 첫 형태소 ID
end 어절을 구형하는 끝 형태소 ID
NE 개체명 정보 인식 결과
id 개체명 ID (출현 순서)
text 개체명 어휘
type 개체명 타입
begin 개체명을 구성하는 첫 형태소의 ID
end 개체명을 구성하는 끝 형태소의 ID
weight 개체명 인식 결과 신뢰도
end 고유명사인 경우 0
일반명사인 경우 1
dependency 의존구문 분석 결과
id 어절의 ID (출현 순서)
text 의존구문 텍스트
head 부모 어절의 ID
label 의존관계
mod 자식 어절들의 ID
weight 의존구문 분석 결과 신뢰도
SRL 의미역 분석 결과
verb 대상 용언(predicate)
sense 용언에 대한 의미 번호
word_id 용언 어절 ID
weight 결과에 대한 신뢰도
argument 논항 정보
 type 논항 타입 정보
 word_id 논항 어절 ID
 text 논항 대상 어절의 텍스트
 weight 논항 분석에 대한 신뢰도
형태소 태그셋

언어 분석 API의 형태소 분석은 TTA 표준 형태소 태그셋(TTAK.KO-11.0010/R1)에 기본하며, 구체적인 정보는 다음과 같습니다.

대분류 소분류 세분류 세종태그
(1) 체언 명사 일반명사 NNG
고유명사 NNP
의존명사 NNB
대명사   NP
수사   NR
(2) 용언 동사   VV
형용사   VA
보조용언   VX
지정사 긍정지정사 VCP
부정지정사 VCN
(3) 수식언 관형사   MM
부사 일반부사 MAG
접속부사 MAJ
(4) 독립언 감탄사   IC
(5) 관계언 격조사 주격조사 JKS
보격조사 JKC
관형격조사 JKG
목적격조사 JKO
부사격조사 JKB
호격조사 JKV
인용격조사 JKQ
보격조사   JX
접속조사   JC
(6) 의존형태 어미 선어말어미 EP
종결어미 EF
연결어미 EC
명사형전성어미 ETN
관형형전성어미 ETM
접두사 체언접두사 XPN
접미사 명사파생접미사 XSN
동사파생접미사 XSV
형용사파생접미사 XSA
어근   XR
(7) 기호 마침표, 물음표, 느낌표   SF
쉼표, 가운뎃점, 콜론, 빗금   SP
따옴표, 괄호표, 줄표   SS
줄임표   SE
붙임표 (물결, 숨김, 빠짐)   SO
외국어   SL
한자   SH
기타 기호 (논리 수학기호, 기호 등)   SW
명사추정범주   NF
용언추정범주   NV
숫자   SN
분석불능범주   NA
개체명 태그셋

언어 분석 API의 개체명 인식 모듈에서 사용하는 태그셋은 TTA 표준 태그셋(TTAK.KO-10.0852)을 사용하며, 146개 세부 개체명 태그에 대한 정보는 다음과 같습니다.

대분류 세분류 정의
PERSON (PS) PS_NAME 사람 이름
LOCATION (LC) LC_OTHERS LC계열의 세부 유형이 아닌 기타 장소
LCP_COUNTRY 국가명
LCP_PROVINCE 도, 주 지역명
LCP_COUNTY 군, 면, 읍, 리, 동 등과 같은 세부 행정구역명
LCP_CITY 도시명
LCP_CAPITALCITY 수도명
LCG_RIVER 강, 호수, 연못
LCG_OCEAN 해양, 바다
LCG_BAY 반도, 만
LCG_MOUNTAIN 산, 산맥, 능선, 고개/재, 봉
LCG_ISLAND 섬, 제도
LCG_CONTINENT 대륙
LC_TOUR 관광명소
LC_SPACE 천체 명칭
ORGANIZATION (OG) OG_OTHERS 기타 기관/단체
OGG_ECONOMY 경제 관련 기관/단체, 기업
OGG_EDUCATION 교육 기관/단체, 교육관련 기관
OGG_MILITARY 군사 기관/단체 및 유형, 국방기관
OGG_MEDIA 미디어 기관/단체, 방송관련 기관/기업
OGG_SPORTS 스포츠 기관/단체
OGG_ART 예술 기관/단체
OGG_MEDICINE 의학/의료 기관/단체
OGG_RELIGION 종교 기관/단체, 종파 포함
OGG_SCIENCE 과학 기관/단체
OGG_LIBRARY 도서관 및 도서관 관련 기관/단체
OGG_LAW 법률 기관/단체
OGG_POLITICS 정부/행정 기관, 공공기관, 정치기관
OGG_FOOD 음식 관련 업체/회사
OGG_HOTEL 숙박 관련 업체
ARTIFACTS (AF) AF_CULTURAL_ASSET 건물/서적/작품 등 문화재
AF_BUILDING 건축물/토목건설물, 운동장이름, 아파트, 다리, 등대, 분수
AF_MUSICAL_INSTRUMENT 악기 명칭
AF_ROAD 도로/철로 명칭
AF_WEAPON 무기 명칭
AF_TRANSPORT 교통수단/자동차/선박 모델 및 유형, 운송 수단, 놀이기구
AF_WORKS AFW의 세부 작품명에 해당하지 않는 기타 작품명
AFW_DOCUMENT 도서/서적 작품명
지리서, 지도
의학 관련 서적
종교 서적, 각 종교의 경전
철학 관련 서적
시/소설/희곡 등의 문학 작품명
역사 서적
기타 서적
AFW_PERFORMANCE 춤/무용 작품명 및 춤 종류
연극/공연명/가극
AFW_VIDEO 영화 작품명
TV 프로그램 이름
AFW_ART_CRAFT 미술 작품명(그림/미술품)
AFW_MUSIC 음악 작품명
AF_WARES 상품/제품 이름
DATE (DT) DT_OTHERS DT 계열의 세부 유형이 아닌 기타 날짜
DT_DURATION 기간
DT_DAY 날짜/절기
DT_MONTH
DT_YEAR
DT_SEASON 계절
DT_GEOAGE 지질시대
DT_DYNASTY 왕조시대
TIME (TI) TI_OTHERS 기타 시간
TI_DURATION 기간
TI_HOUR 시각
TI_MINUTE
TI_SECOND
CIVILIZATION (CV) CV_NAME 문명/문화 명칭
CV_TRIBE 민족/종족 명칭, 국가를 구성하는 국민
CV_SPORTS 스포츠/레포츠/레져 명칭
CV_SPORTS_INST 스포츠 용품/도구
CV_POLICY 제도/정책 명칭
CV_TAX 조세 명칭
CV_FUNDS 연금, 기금, 자금, 펀드 명칭
CV_LANGUAGE 언어 명칭
CV_BUILDING_TYPE 건축양식 명칭
CV_FOOD 음식 명칭, 음식재료
CV_DRINK 음료수, 술 명칭
CV_CLOTHING 의복/섬유 명칭
CV_POSITION 직위/직책 명칭, 스포츠 포지션
CV_RELATION 인간 관계 명칭
CV_OCCUPATION 직업 명칭
CV_CURRENCY 통화 명칭
CV_PRIZE 상과 훈장
CV_LAW 법/법률 명칭
CV_FOOD_STYLE 음식 종류
ANIMAL (AM) AM_OTHERS 기타 동물 명칭
AM_INSECT 곤충
AM_BIRD 조류
AM_FISH 어류
AM_MAMMALIA 포유류
AM_AMPHIBIA 양서류
AM_REPTILIA 파충류
AM_TYPE 동물 분류 명칭
AM_PART 동물 몸의 한 부분(신체 부위) 명칭
PLANT (PT) PT_OTHERS 기타 식물 명칭
PT_FRUIT 과일 이름 (식용 가능한 식물의 열매)
PT_FLOWER 꽃 이름
PT_TREE 나무 이름
PT_GRASS 풀 이름
PT_TYPE 식물 유형 명칭
PT_PART 식물의 한 부분에 대한 명칭
QUANTITY (QT) QT_OTHERS 기타 수량 표현
QT_AGE 나이
QT_SIZE 크기/넓이
QT_LENGTH 길이/거리/높이
QT_COUNT 개수/빈도
QT_MAN_COUNT 인원수
QT_WEIGHT 무게
QT_PERCENTAGE 백분율, 비율, 농도
QT_SPEED 속도
QT_TEMPERATURE 온도
QT_VOLUME 부피
QT_ORDER 순서, 순차적 표현
QT_PRICE 금액
QT_PHONE 전화번호
QT_SPORTS 스포츠 관련 수량 표현
QT_CHANNEL TV/라디오 채널 번호
QT_ALBUM 앨범 관련 수량 표현
QT_ZIPCODE 우편번호
STUDY_FIELD (FD) FD_OTHERS 학문 분야 및 학파
FD_SCIENCE 과학 학문 분야
FD_SOCIAL_SCIENCE 사회과학 학문 분야 및 학파
정치/경제/사회와 관련된 분야
FD_MEDICINE 의학 관련 학문 분야 및 분과
FD_ART 예술관련 학문 분야 및 학파
FD_PHILOSOPHY 철학 관련 학문 분야 및 학파
THEORY (TR) TR_OTHERS 기타 이론/법칙/원리
TR_SCIENCE 과학 관련 이론/법칙/방식/양식/체계/학설
TR_SOCIAL_SCIENCE 사회과학 이론/법칙/방법/원리/사상, 정치사상
TR_ART 예술관련 이론/법칙/방식/양식, 예술사조
TR_PHILOSOPHY 철학 이론/사상
TR_MEDICINE 의학 요법/처방, 의학 진단법
EVENT (EV) EV_OTHERS 기타 사건/사고 명칭, ~사태
EV_ACTIVITY 사회운동 및 선언
EV_WAR_REVOLUTION 전쟁/혁명
EV_SPORTS 스포츠/레저 관련 행사
EV_FESTIVAL 축제 명칭
MATERIAL (MT) MT_ELEMENT 원소명
MT_METAL 금속물
MT_ROCK 암석 명칭
MT_CHEMICAL 모든 화학물질을 나타냄
TERM (TM) TM_COLOR
TM_DIRECTION 방향
TM_CLIMATE 기후지역 명칭
TM_SHAPE 모양/형태 명칭
TM_CELL_TISSUE 세포/조직/기관 명칭 (외부에서 안 보이는 조직/기관)
TMM_DISEASE 증상/증세/질병
TMM_DRUG 약/약품명
TMI_HW IT 하드웨어 용어
TMI_SW IT 소프트웨어 용어
TMI_SITE URL 주소
TMI_EMAIL 이메일주소
TMI_MODEL 각종 제품의 세부 모델명, 부품류
TMI_SERVICE IT 서비스 용어
TMI_PROJECT 프로젝트 명칭
TMIG_GENRE 게임 장르
TM_SPORTS 스포츠/레저 용어 (기술/규칙 명칭)
의존 구문분석 태그셋
구문 레이블 설명 기능 레이블 설명
S 문장 SBJ 주격
NP 명사구 OBJ 목적격
VP 동사구 MOD 관형격 수식어
AP 부사구 AJT 부사격 수식어
VNP 명사+이다 (지정사) CNJ 연결 (~와)
DP 관용사구 CMP 보격
IP 감탄사 INT 독립어
기타 표지 설명
PRN 삽입어구
X pseudo phrase
L, R 부호
Q 인용절
의미역 인식 태그셋

의미역 인식에서 사용하는 의미역은 필수역(core role)과 부가역(adverbal role)으로 구분되며, Proposition Bank[2]에서 정의된 세부적인 목록은 다음과 같습니다.

타입 의미역 설명
필수격 ARG0 (A0) 행동주(Agent), 경험주(experiencer)
ARG1 (A1) 피동주(Patient), 대상(theme)
ARG2 (A2) 수혜자(Benefactive), instrument, attribute,
결과(end state)
ARG3 (A3) 기점(Start point), benefactive, instrument, attribute
ARG4 (A4) 착점(End point)
부가격 ARGM-TMP 시간(When)
ARGM-LOC 장소(Where)
ARGM-DIR 방향(where to/from)
ARGM-MNR 방법(How, manner)
ARGM-PRP 목적
ARGM-CAU 원인
ARGM-EXT 범위, 정도
ARGM-CND 조건
ARGM-PRD 보조서술
ARGM-DIS 담화
ARGM-ADV 부사구
ARGM-NEG 부정
오류 코드

언어 분석 API의 오류 코드 목록은 다음과 같습니다.

http status code result reason 설명
400 -1 Required arguments is empty 필수 파라미터의 값이 없는 경우
400 -1 One or more arguments are not valid 파라미터의 값이 유효하지 않는 경우
413 -1 Request Entity Too Large 요청 문장 또는 어휘의 크기가 서버가 처리 할 수 있는 것보다 큰 경우
429 -1 Too Many Requests 사용자가 주어진 시간 내에 서버에 너무 많은 요청을 하는 경우
404 -1 Unknown Handler 등록되지 않는 서비스를 요청한 경우
408 -1 Handler Timeout 서버의 요청 대기가 시간을 초과한 경우
500 -1 ETRI service server connection refused ETRI 분석 서버에서 요청을 받지 못하는 경우
500 -1 ETRI service server is not exists 수행 가능한 ETRI 분석 서버가 없는 경우
500 -1 Recipient Failure ETRI 분석 서버에서 요청을 처리하지 못하는 경우
500 -1 Unknown ReplyFailure API 요청에 알 수 없는 내부 오류가 발생한 경우
500 -1 Unknown Exception 알 수 없는 내부 오류가 발생한 경우
참고문헌
  1. 임준호, 배용진, 김현기, 김윤정, 이규철, 의존 구문분석을 위한 한국어 의존관계 가이드라인 및 엑소브레인 언어분석 말뭉치, 제27회 한글 및 한국어 정보처리 학술대회 논문집, 2015.10.
    download
  2. Martha Palmer, Dan Gildea, Paul Kingsbury, The Proposition Bank: A Corpus Annotated with Semantic Roles Computational Linguistics Journal, 31:1, 2005
    download
  3. 임수종, 권민정, 김준수, 김현기, ExoBrain을 위한 의미역 가이드라인 및 말뭉치 구축, 제27회 한글 및 한국어 정보처리 학술대회 논문집, 2015.10.
    download