반응형

Cloudant에서 제공하는 쿼리를 사용하기 위해서는 Cloudant가 제공하는 세 가지 방식의 Index 즉, 
Primary, Secondary, Search Index에 대해 이해를 해야 합니다. 각각에 대한 설명은 다음 슬라이드를 참고하시기 바랍니다.


먼저 Primary Index(Key)는 기본적인 Document CRUD(Create/Read/Update/Delete)에 사용하는 ID를 의미합니다.
다음과 같은 코드를 통해 "uniqueId" 라는 ID에 해당하는 문서를 가져올 수 있습니다.

JsonNode queriedNode = conn.get(JsonNode.class, "uniqueId");

Primary Key는 Document 생성 시, 자동으로 만들어지거나 지정한 값으로 지정되며 그에 대한 Index는 항상 만들어집니다.
그러나 DB를 사용하다 보면 Primary Key가 아닌 다른 속성을 이용한 조회가 필요한 경우가 있습니다.
예를 들어 다음과 같은 JSON 문서가 있다고 가정합니다. (haproxy log를 Cloudant DB로 읽어 들임)
_id 필드가 바로 Primary Key에 해당되며, 이 경우는 자동 생성된 UUID입니다.
만약, statusCode를 기준으로 2xx에 해당하는 데이터를 조회하려면 어떻게 해야 할까요?

{
  "_id": "3301271f19a1de5a25f1f71a36a5a901",
  "_rev": "1-567a8600361cc4bcf5ce0b3d0407559e",
  "dateTime": "Mar 10 00:00:00",
  "serverIp": "10.245.101.62",
  "procName": "haproxy[29983]:",
  "clientIpPort": "127.0.0.1:44368",
  "acceptDate": "10/Mar/2014:00:00:00.579",
  "frontendName": "http_proxy~",
  "backendName": "wilson.lb1.wildcard.cloudant.net",
  "serverName": "localhost",
  "time": {
    "Tq": "7",
    "Tw": "0",
    "Tc": "0",
    "Tr": "2",
    "Tt": "9"
  },
  "statusCode": "200",
  "bytesRead": "192",
  "requestCookie": "",
  "responseCookie": "",
  "terminationState": "----",
  "conns": {
    "a": "7",
    "f": "0",
    "b": "0",
    "s": "2",
    "r": "9"
  },
  "queue": {
    "s": "0",
    "c": "0"
  },
  "requestHeaders": "python-requests/2.0.1 CPython/2.6.5 Linux/2.6.32-342-ec2|",
  "responseHeaders": "|",
  "httpRequest": "GET /_api/v2/ HTTP/1.1"
}

이 경우 사용할 수 있는 것이 바로 나머지 두 가지 Index인, Secondary Index와 Search Index입니다.


Secondary Index

일반적인 RDB에서는 대략 다음과 같이 Index를 생성합니다.

CREATE INDEX statusIdx ON httplog (statusCode)

그러면 아래와 같이 SQL 쿼리를 실행할 수 있습니다.

SELECT * FROM httplog WHERE statusCode >= ‘400’ AND statusCode <= ‘499’;
SELECT * FROM httplog GROUP BY statusCode;

Cloudant DB에서 Secondary Index를 이용하여 위와 같은 과정을 처리하려면 다음과 같은 과정을 거칩니다.

1. Secondary Index 생성

Cloudant DB 관리 콘솔에 들어가서 해당 DB(여기서는 httplog)의 Secondary Indexes 메뉴에서 +New를 눌러 새로운 Design Document를 생성합니다.



여기서 Design Document는 일반적인 데이터를 저장하는 것이 아니라 Secondary Index나 Search Index에 대항 정의를 담는 특수한 Document라고 생각하시면 됩니다.
그것은 문서의 ID가 _design 이라는 prefix로 시작함으로 식별되게 됩니다. 아래에서 _design은 Design Doc을 식별하고 sql은 그것의 이름입니다.
그 문서 안에는 여러 개의 Index들을 정의할 수 있습니다. 여기서는 statuscode라는 이름의 Index를 생성합니다.
Map function 부분에는 Secondary Index에 해당하는 Map 함수를 정의합니다. 이 Map 함수는 Hadoop에서 사용하는 Map/Reduce와 거의 유사하며
대신 JavaScript로 작성됩니다. emit() 함수를 통해 Index를 만들고자 하는 속성을 첫 번째 파라미터(key에 해당)로 실행합니다.
두 번째 파라미터의 1은 Map/Reduce의 문법에 따른 것으로 의미 상으로는 해당 statusCode에 해당하는 문서가 1개 라는 의미로 생각하면 됩니다.

emit(doc.statusCode, 1);

if 문으로 statusCode 속성이 존재하는지 여부를 체크하는 이유는 Cloudant DB가 JSON 기반의 자유로운 형식의 문서를 저장하다 보니
해당 속성이 없는 문서도 있을 수 있기 때문입니다. 물론 그런 경우에도 emit()을 하게 되면 null이 key로 지정되기 때문에 쿼리에 큰 지장은 없습니다.
즉, 지정하지 않아도 무방합니다.

두 번째 Reduce(optional)라고 되어 있는 부분에는 _count가 선택되어 있습니다.
여기에도 Map 함수의 경우처럼 JavaScript 코드를 Map/Reduce 형식에 따라 작성할 수 있지만 _count 라고 하는 내장된 함수를 그냥 사용하도록 하였습니다.
_count 함수의 역할은 statusCode 별로 존재하는 Document의 전체 개수를 Counting 하는 역할을 합니다.

2. 생성된 Secondary Index 테스트

이렇게 생성한 Index는 Java 코드로 호출하기 전에 웹 콘솔에서 바로 테스트해 볼 수 있습니다.
아래는 statusCode가 400인 것들을 조회하되, 결과에 전체 문서를 포함하고 개수는 20개로 제한하도록 한 것입니다.



만약 statusCode가 4xx인 문서들을 조회하고 싶다면 다음과 같이 조건을 지정하면 됩니다. 
“400” ~ “500” 사이인데 마지막의 “500”에 해당하는 문서는 결과에 포함시키지 말라는 의미입니다.



이번에는 Reduce 기능을 통해서 statusCode별 문서의 개수가 몇 개나 되는지 확인해 보겠습니다.
Reduce 함수에 _count가 지정되었기 때문에 문서의 개수를 세는 것이 가능합니다.
다음과 같이 지정하면 statusCode가 “200” ~ “500” 사이인 문서들을 statusCode 별로 분류(RDB SQL의 group by에 해당)한 결과를 구할 수 있습니다.



결과는 다음과 같습니다. key에 Map의 emit() 함수에서 첫 번째 파라미터로 지정한 statusCode가 오고 value에는 Reduce의 _count 함수에 의해 계산된 결과가 나오게 됩니다.

{
  "value": 2344,
  "key": "200"
}

{
  "value": 2,
  "key": "201"
}

{
  "value": 1,
  "key": "302"
}

{
  "value": 1,
  "key": "304"
}

{
  "value": 46,
  "key": "400"
}

{
  "value": 4,
  "key": "404"
}

{
  "value": 3,
  "key": "408"
}

사용 가능한 REST 문법은 다음을 참고하시기 바랍니다.



3. Ektorp 라이브러리를 통해서 Java 프로그램에서 호출하기

CRUD 예제를 참고해서 CouchDbConnector까지는 구합니다.
그리고 나서 다음과 같이 ViewQuery를 작성해야 합니다. 내용은 위에서 보았던 Query 조건들이고 그것을 다음과 같은 형식으로 지정합니다.

// “400” ~ “500” 사이의 문서 리스트
ViewQuery q = new ViewQuery().designDocId("_design/sql").viewName("statuscode").includeDocs(true).reduce(false).startKey("400").endKey("500").inclusiveEnd(false);

// “200” ~ “500” 사이 문서들의 개수
ViewQuery q = new ViewQuery().designDocId("_design/sql").viewName("statuscode").includeDocs(false).reduce(true).groupLevel(1).startKey("400").endKey(“500").inclusiveEnd(false);

이렇게 만들어진 ViewQuery 객체(조건)를 이용해서 다음과 같이 쿼리를 실행합니다.

ViewResult result = conn.queryView(q);

그것에 대한 전체 코드는 다음과 같습니다.

               ObjectMapper om = new ObjectMapper();
               try {
                    // “400” ~ “500” 사이의 문서 리스트
                    //ViewQuery q = new ViewQuery().designDocId("_design/sql").viewName("statuscode").includeDocs(true).reduce(false).startKey("400").endKey(“500").inclusiveEnd(false);

                    // “200” ~ “500” 사이 문서들의 개수
                    ViewQuery q = new ViewQuery().designDocId("_design/sql").viewName("statuscode").includeDocs(false).reduce(true).groupLevel(1).startKey("400").endKey("500").inclusiveEnd(false); 
                    ViewResult result = conn.queryView(q);
                    Iterator<Row> it = result.iterator();
                    System.out.println("\n*** statusCode Result ***");
                    while(it.hasNext()) {
                         Row aRow = it.next();
                         String key = aRow.getKey();
                         JsonNode valueNode = aRow.getValueAsNode();
                         System.out.println(key + ": " + om.writerWithDefaultPrettyPrinter().writeValueAsString(valueNode));
                    }
               } catch (JsonParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (JsonMappingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }

실행한 결과는 다음과 같습니다.

*** statusCode Result ***
200: 2344
201: 2
302: 1
304: 1
400: 46
404: 4
408: 3


Search Index

이번에는 Search Index를 이용하는 방법을 알아 보도록 하겠습니다.
Ektorp에서 Search Index를 이용하기 위해서는 우선 아래 글과 같이 클래스 두 개를 추가해야 합니다.
Ektorp는 순수 CouchDB를 대상으로 만들어진 라이브러리이기 때문에 Cloudant의 고유 기능인 Search Index를 호출할 수 있는 기능이 아직은 없습니다.
하지만 아래 글에도 언급했지만 Pull Request를 통해 정식으로 라이브러리에 포함하도록 요청할 계획입니다.


1. Search Index 생성

Search Index 기반의 Full Text Search 기능을 사용하려면 Secondary Index와 마찬가지로 먼저 Design Document에 Index를 추가해야 합니다.
아래와 같이 Search Index 부분에서 +New 를 선택해서 새로운 Design Document를 역시 _design prefix를 가진 이름으로 생성합니다.
그리고 Index name을 지정하고 Search Index Function 부분에 Index를 생성하기 위한 JavaScript 함수를 정의합니다.
아래의 예제는 JSON으로 저장된 haproxy log의 모든 속성을 인덱싱하기 위한 코드이므로 다소 복잡합니다만, 원하는 필드들만 지정하는 것도 물론 가능합니다.
위의 Secondary Index에서 사용된 statusCode만 사용하고 싶다면 아래 빨간줄의 코드만 사용해도 됩니다.



이 과정에 아래와 같이 Lucene(Cloudant가 기반으로 사용하는 검색 엔진)에서 사용할 Analyzer 즉, 언어별 단어를 추출해 내기 위한 방법을 선택할 수 있습니다.
참고로 한글의 경우에는 현재 CJK Analyzer를 사용할 수 있습니다. 필요한 Analyzer는 요청에 의해 추가할 수 있습니다.




2. Search Index 테스트

Secondary Index와 마찬가지로 콘솔에서 인덱싱 결과를 바로 테스트할 수 있습니다.
다음은 haproxy log 중에서 http method가 ‘PUT’ 이고 statusCode가 500~503인 경우만 조회한 것입니다.



위에서 입력한 조건을 아래와 같습니다.

httpMethod:PUT AND statusCode:[500 TO 503]

자세한 문법(lucene query)은 다음 문서들을 참고하면 됩니다.


사용 가능한 REST 문법은 다음을 참고하시기 바랍니다.


3. Ektorp 라이브러리를 통해서 Java 프로그램에서 호출하기

역시 CRUD 예제를 참고해서 CouchDbConnector까지는 구합니다.
그리고 나서 다음과 같이 CloudantSearchQuery를 작성해야 합니다. 아래에서는 조건에 응답 시간(Tt)이 50ms 미만인 것들만 조회를 하도록 했습니다.

//     Search를 이용한 조회 (Full Text Search)
CloudantSearchQuery search = new CloudantSearchQuery().designDocId("_design/fts").searchName("all").includeDocs(true).limit(10)
    .queryParam("q", "httpMethod:PUT AND statusCode:[500 TO 503] AND Tt:[-Infinity TO 50]");

이렇게 만들어진 ViewQuery 객체(조건)를 이용해서 다음과 같이 쿼리를 실행합니다.

ViewResult result = conn.queryView(search);

그것에 대한 전체 코드는 다음과 같습니다.

               ObjectMapper om = new ObjectMapper();
               try {
                    //     Search를 이용한 조회 (Full Text Search)
                    CloudantSearchQuery search = new CloudantSearchQuery().designDocId("_design/fts").searchName("all").includeDocs(true).limit(10)
                              .queryParam("q", "httpMethod:PUT AND statusCode:[500 TO 503] AND Tt:[-Infinity TO 50]");
                    ViewResult result = conn.queryView(search);
                    Iterator<Row> it = result.iterator();
                    System.out.println("*** Search Query Result ***");
                    while(it.hasNext()) {
                         Row aRow = it.next();
                         JsonNode aNode = aRow.getDocAsNode();
                         System.out.println(om.writerWithDefaultPrettyPrinter().writeValueAsString(aNode));
                    }
               } catch (JsonParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (JsonMappingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }

실행한 결과는 다음과 같습니다.

*** Search Query Result ***
{
  "_id" : "d554a598fcaa48b53708d7c3bdfbea6d",
  "_rev" : "1-cf0fd065215d2cee4993f114b52671de",
  "dateTime" : "Mar 10 00:02:56",
  "serverIp" : "10.245.101.62",
  "procName" : "haproxy[29983]:",
  "clientIpPort" : "68.32.134.130:52400",
  "acceptDate" : "10/Mar/2014:00:02:56.191",
  "frontendName" : "http_proxy~",
  "backendName" : "http_proxy",
  "serverName" : "<NOSRV>",
  "time" : {
    "Tq" : "-1",
    "Tw" : "-1",
    "Tc" : "-1",
    "Tr" : "-1",
    "Tt" : "44"
  },
  "statusCode" : "503",
  "bytesRead" : "212",
  "requestCookie" : "",
  "responseCookie" : "",
  "terminationState" : "SC--",
  "conns" : {
    "a" : "-1",
    "f" : "-1",
    "b" : "-1",
    "s" : "-1",
    "r" : "44"
  },
  "queue" : {
    "s" : "0",
    "c" : "0"
  },
  "requestHeaders" : "Android|",
  "responseHeaders" : "|",
  "httpRequest" : "PUT /acra-storage/_design/acra-storage/_update/report/9553fe11-355a-478b-83c3-0561c5b4783f HTTP/1.1"
}
{
  "_id" : "d554a598fcaa48b53708d7c3bdfbf793",
  "_rev" : "1-dc8154b1a4ca2ea6297b0128b34603f7",
  "dateTime" : "Mar 10 00:02:56",
  "serverIp" : "10.245.101.62",
  "procName" : "haproxy[29983]:",
  "clientIpPort" : "68.32.134.130:53919",
  "acceptDate" : "10/Mar/2014:00:02:56.508",
  "frontendName" : "http_proxy~",
  "backendName" : "http_proxy",
  "serverName" : "<NOSRV>",
  "time" : {
    "Tq" : "-1",
    "Tw" : "-1",
    "Tc" : "-1",
    "Tr" : "-1",
    "Tt" : "41"
  },
  "statusCode" : "503",
  "bytesRead" : "212",
  "requestCookie" : "",
  "responseCookie" : "",
  "terminationState" : "SC--",
  "conns" : {
    "a" : "-1",
    "f" : "-1",
    "b" : "-1",
    "s" : "-1",
    "r" : "41"
  },
  "queue" : {
    "s" : "0",
    "c" : "0"
  },
  "requestHeaders" : "Android|",
  "responseHeaders" : "|",
  "httpRequest" : "PUT /acra-storage/_design/acra-storage/_update/report/44639569-c95f-43f9-a08e-b6fb03933c6c HTTP/1.1"
}
… 생략 …






Posted by Hey Jerry
,
반응형

Cloudant DB에 Java를 통해 접근하려면 주로 Ektorp라는 라이브러리를 사용합니다.

Ektorp의 웹사이트와 매뉴얼 페이지는 아래와 같습니다


아래는 REST 프로토콜을 사용하는 경우 Cloudant DB가 제공하는 API 입니다. 
하지만 Ektorp는 사용하기 편리한 형태로 추상화가 되어 있기 때문에 이러한 세부적인 내용들을 모두 알아야 할 필요가 없는 장점이 있습니다. 



1. Eclipse에서 Ektorp 라이브러리 레퍼런스

Ektorp 라이브러리는 하나의 jar 파일로 되어 있지만 내부적으로 참조하는 라이브러리들이 많아 일일이 설정하는 것 보다는
Maven을 통해 Dependency를 해결하길 권장합니다.

Eclipse에서 Maven 프로젝트를 만들고(이 부분에 대한 자세한 내용은 생략) pom.xml에 다음과 같이 추가합니다.

     <dependencies>
          <dependency>
               <groupId>org.ektorp</groupId>
               <artifactId>org.ektorp</artifactId>
               <version>1.4.1</version>
          </dependency>
          ...
     </dependencies>

최종 버전은 아래 Maven Repository에서 확인 후 지정하면 됩니다.


2. DB 연결 방법

기본적으로 Cloudant 계정이 있고 사용할 DB를 이미 만들었다는 전제 하에 다음과 같이 접속하는 코드를 작성할 수 있습니다.

               HttpClient httpClient = new StdHttpClient.Builder().url(url)
                         .username(uid)
                         .password(pwd)
                         .connectionTimeout(5000)
                         .socketTimeout(30000).build();

               StdCouchDbInstance dbInst = new StdCouchDbInstance(httpClient);
              
               System.out.println("*** Database connection is established");
              
               CouchDbConnector conn = dbInst.createConnector(“dbname", true);    // DB가 존재하지 않을 때 생성하려면 두 번째 파라미터에 true

위와 같이 CouchDbConnector 객체를 얻고 나면 Document에 대한 조회, 생성, 변경, 삭제가 가능해집니다.

3. 기본적인 CRUD

Cloudant DB는 기본적으로 JSON 객체를 저장할 수 있고, Ektorp는 그것을 ObjectMapper를 통해 JsonNode, Map, 또는 JavaBeans 객체로 
매핑할 수 있습니다. 다음은 Jackson 라이브러리의 JsonNode 객체를 이용하여 INSERT를 하는 예제입니다.

               ObjectMapper om = new ObjectMapper();
               try {
                    //     Document 생성 (insert 와 동일)
                    //     doc id를 지정하지 않았으므로 자동으로 생성 됨
                    JsonNode node = om.readValue("{\"name\": \"유관순\"}", JsonNode.class);
                    //     doc id를 지정하려면 다음 remark 해제
//                    ObjectNode editableNode = (ObjectNode)node;
//                    editableNode.put(“_id", "유관순”);
                    conn.create(node);
               } catch (JsonParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (JsonMappingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
               }

다음은 각각 UPDATE, DELETE, QUERY를 하는 예제입니다.

                    // 조회. _id가 지정된 경우
                    ObjectNode queriedNode = (ObjectNode)conn.get(JsonNode.class, “유관순");

                    // 내용 변경. JsonNode가 아닌 ObjectNode로 type casting 해야 JSON 데이터 변경 가능
                    queriedNode.put("name", "끼어들기");
                    try {
                         conn.update(queriedNode);
                         conn.delete(queriedNode);
                    } catch (UpdateConflictException e) {
                         System.out.println(om.writerWithDefaultPrettyPrinter().writeValueAsString(queriedNode));
                         e.printStackTrace();
                    }









Posted by Hey Jerry
,

CouchDB 소개

기술 2014. 3. 19. 16:31
반응형



Posted by Hey Jerry
,
반응형

정보통신산업진흥원(NIPA)에서 운영하고 있는 각종 자료 포탈 사이트...


http://www.itfind.or.kr


정부 관련 자료가 약간 현실과 동떨어진 감은 있지만


(1) 거시적인 insight를 얻기에 좋고

(2) 각종 수치, 통계, 그래프 등과 같은 디테일 내용


으로 도움이 됨







Posted by Hey Jerry
,
반응형
전세계 클라우드


Amazon 전체 연매출 610억 달러에서 AWS로 추정할 수 있는 기타 매출(의도적으로 AWS 매출 별도 집계 안 함... 10% 미만은 부문별 집계 의무 없음)
AWS 추정 매출은 38억 달러... 성장률은 쇼핑몰 상회... 성장 동력임은 분명
Rackspace(전문 업체는 의무적으로 해야 함)는 전체 13억 중에서 3억 달러가 퍼블릭 클라우드 매출... 따라서 아직 AWS의 1/10 수준 (다른 업체들의 수준도 짐작 가능)

IBM이 클라우드 매출이 AWS를 넘는다고 하지만... 무리수



역시 위와 동일한 내용... 연 38억 달러... 성장률 가파르고... 대기업(화이자) 사용하려고 함

국내 클라우드


국내 클라우드 환경을 보았을 때, 삼성전자가 AWS의 주요 또는 대부분을 차지하는 고객으로 추정 (비율은 50% 훨씬 상회 예상)


사용하는 규모와 AWS 가격 정책으로 볼 때, 연 1500~3000억 수준 예상이 됨

따라서 AWS 전세계 매출의 5~10%로 추정 가능


대체로 한국의 SW 시장 규모가 전 세계 1% 정도로 볼 때, 이 정도 수준은 높은 것이라 할 수 있음. 단!! 오직 삼성전자 하나만의 힘이라는 것 !!



그런 면에서 초기 현재의 클라우드 시장에서 한국 시장은 중요도가 꽤 있음... (외국 업체가 국내에 데이터 센터 하나 정도는 지어도 되지 않을까? 전기값도 싼데)

다만, 다른 SW 시장과 마찬가지로 저변(대기업을 제외한 Long/Medium Tail)이 부족한 우리나라 상황 상(startup 들이 많이 나와야 함) 이 비중은 점점 떨어질 것으로 예상


정말 분발과 선제적인 대응과 노력이 필요할 듯!!


하지만 안타깝게도 국내 현실은 


(1) 삼성전자라는 아주 좋은 고객도 외산에 놓치고 있고

(2) 외국 클라우드 업체를 따라잡을 원천 기술이 부족 (HW, SW, Best Practice 등을 클라우드 운영 노하우라 총칭하겠음)

(3) 그럼에도 불구하고 보안(우리나라만의 특수한 내 것을 밖에 내 놓지 않겠다는 생각)이라는 장벽이 높고

(4) 누구도 그러한 결정을 먼저하지 않으려는 수동적인 자세


로 인해 안방을 내 주고 있는 상황


가능성은 있음... 그것은 바로 관심 !!!!!













Posted by Hey Jerry
,
반응형

다음 위치에서

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\taskmgr.exe (regjump로 가면 편리)

다음과 같이 변경하면 됨

이 때 첫 번째 파라미터로 원래 taskmgr.exe 실행 경로가 오므로 주의

"C:\Windows\system32\taskmgr.exe"

procexp.exe는 파라미터가 있으면 에러가 나므로 batch 파일을 만들어 피해가게 했음






Posted by Hey Jerry
,
반응형

안녕하세요. TISTORY입니다.


Evernote 글 불러오기 플러그인을 소개합니다.


 

PC와 스마트폰에서 사용할 수 있는 메모 애플리케이션 Evernote를 이용해 언제 어디서나 블로그에 글을 등록할 수 있습니다. 일상생활에서 일어나는 크고 작은 일들을 쉽게 기록하고 정리하여 블로그에 발행해 보세요.

Evernote에 노트를 작성하시고 '티스토리' 태그만 넣으면 내 블로그에 언제든 불러올 수 있습니다.


Evernote 플러그인 적용하기



Evernote 플러그인은 해당 플러그인은 새 에디터에서만 지원하며, 관리센터의 플러그인 설정 > 글쓰기 카테고리에서 찾으실 수 있습니다. 



 

플러그인 설정 화면에서 ☞ 내 Evernote 계정 연결하기를 선택하면 로그인 화면이 나타납니다. 본인의 계정으로 로그인하시거나 새로운 계정을 만드신 후, 로그인해 주세요. 

로그인이 완료되면 플러그인을 사용하기 위한 인증 단계를 거칩니다. 인증은 기본 1년 동안 유지됩니다.


 


 

Evernote 계정 연결이 완료되면, 위와 같이 "연결되었습니다. 설정을 저장해 주세요" 라는 메세지가 나타납니다. 여기에서 반드시 "저장" 버튼을 눌러 설정 내용을 저장해주셔야만 플러그인을 사용할 수 있습니다.


Evernote의 글을 블로그로 불러오기



 

플러그인 설정이 완료되면 글쓰기 제목 영역에 Evernote 버튼을 확인하실 수 있습니다. 또는 우측 사이드바에서 플러그인 > Evernote로도 사용가능합니다. Evernote를 클릭하시면 노트를 불러오는 팝업이 뜹니다.



팝업에서는 Evernote에서 티스토리, tistory 태그가 붙은 모든 글을 확인하실 수 있습니다. 불러올 내용이 많거나 Evernote의 서비스 속도가 지연되는 경우, 로딩이 오래 걸릴 수 있으니 참고해 주세요. 블로그에 발행하고자 하는 글을 선택하시면 에디터에 내용을 가져옵니다. 한 포스팅에 여러개의 노트를 불러올 수도 있습니다.

에디터에서 글 내용을 마음대로 편집하시고 완성된 글을 발행해 보세요!


Q. 팝업에서 글 목록은 어떤 순서인가요?

A. 노트를 최초 작성한 시간 기준으로 최근에 작성한 글이 목록 상단에 보이게 됩니다.


Q. Evernote에 등록된 이미지 및 첨부파일은 어떻게 불러오나요?

A. 이미지는 노트에 직접 첨부하시거나 외부에서 html로 붙인 경우에도 티스토리 블로그에 업로드 되어 보여집니다. 그러나 녹음파일, PPT, Word 등 첨부파일 등은 블로그로 가져올 때, 파일첨부 형태로 제공되어 다운로드가 가능합니다.


Q. Evernote에서 폰트에 스타일을 적용했거나 표를 삽입한 경우는 블로그에서 어떻게 보여지나요?

A. 폰트 색상, 강조색, 정렬을 포함한 모든 스타일과(글머리 기호 제외) 표 등, 노트에서 확인 가능한 스타일 그대로 블로그에 적용됩니다. 


Q. 블로그로 이미 가져온 글을 Evernote에서 수정하면 수정 내용이 반영되나요?

A. Evernote 플러그인은 팝업을 띄울 때마다 티스토리 태그가 삽입된 글을 불러오도록 단방향 기능으로 제공되고 있습니다. 이미 블로그에서 포스팅한 노트가 수정되면 다음번에 팝업을 띄웠을 때, 편집된 노트를 다시 가져오며, 자동으로 싱크를 맞추지는 않습니다.


Q. 에버노트에 연결할 수 없다는 메시지가 떠요.

A. Evernote 플러그인은 유저별로 사용량에 따라 일시적으로 제한될 수 있습니다. 제한은 최대 1시간까지 적용될 수 있으므로 1시간 후에 다시 시도해 보시기 바랍니다.


항상 여러분에게 더 편리한 서비스를 제공하기 위해 노력하는 티스토리가 되겠습니다.

감사합니다.

 

'공지' 카테고리의 다른 글

네이버에서 이사를 옮  (0) 2014.03.06
Posted by Hey Jerry
,
반응형

http://blog.naver.com/javalove93에서 새로 이사 옴~~



'공지' 카테고리의 다른 글

Tistory에서 Evernote 글을 이용해서 글 쓰는 방법  (0) 2014.03.15
Posted by Hey Jerry
,