소개

웹 크롤러는 웹페이지의 link를 방문해 HTML 데이터와 link를 저장하는 작업을 반복해가며 웹 전반을 탐색하는 애플리케이션입니다.

Apache Nutch는 Open Source Web Crawler 중 하나입니다. Apache Nutch는 Apache Hadoop Cluster에서 동작하는 Deploy Mode와 간단 수집 및 테스트를 위한 Single Mode가 있습니다. 이 글에선 Ntuch Process를 간단히 설명하고 Single Mode로 크롤링을 하는 방법을 공유합니다.

 

실행 환경은 아래와 같습니다

  • Apache Nutch 1.18
  • Ubuntu 20.04

Nutch Process

  • Apache Nutch는 5가지 Main Process가 반복되며 진행됩니다.
    • Inject: 크롤링을 시작할 웹 페이지가 저장된 파일을 CrawlDB에 저장합니다.
      • CrawlDB: Apache Nutch가 웹페이지를 관리하기 위해 Metadata를 저장하는 DB
    • Generate: CrawlDB에 저장된 URL 중 1 cycle에 크롤링할 N개의 URL을 추출합니다.
    • Fetch: Generated된 웹페이지를 방문하여 HTML 원문을 저장합니다.
    • Parse: Fetched된 HTML 원문에서 text, 메타데이터, 링크를 추출한 후 나누어 저장합니다.
    • DBUpdate: parsed된 metadata와 link를 CrawlDB에 추가합니다.

Crawling Process

크롤링 프로세스 간단 정리

  1. Apache Nutch Binary 파일 다운
  2. Seed 파일 생성
  3. Apache Nutch 최소 설정 적용
  4. shell script를 활용한 크롤링
  5. 사람이 보기 편한 파일로 변환

크롤링 프로세스 세부 정리

1. Apache Nutch 홈페이지를 방문하여 Apache Nutch Binary 버전을 다운로드 한 후 적당한 위치에 압축을 풉니다.

    http://nutch.apache.org/downloads.html

 

Apache Nutch™ -

Nutch Downloads Your primary resource for all official Nutch releases

nutch.apache.org

 

2. Seed URL, CrawlDB, 크롤링 결과 파일 등을 저장할 폴더를 생성합니다. 저는 data 폴더를 생성하였습니다.

 

 

3. data 폴더 내 seed 폴더를 생성한 후 seed.txt 파일 내 테스트용 URL을 저장합니다. 저는 Apache nutch 메인 페이지 url을 아래와 같이 넣었습니다.

 

 

 

 

4. 크롤링을 하기 위한 최소 설정을 위해 Nutch가 설치된 폴더 내 conf/nutch-site.xml을 아래와 같이 수정합니다. http.agent.name은 Apache Nutch를 사용하기 위해 요구되는 최소 설정입니다. 기타 설정은 conf/nutch-default.xml을 확인한 후 nutch-site.xml에 변경사항을 추가하는 방법으로 적용 가능합니다.

 

<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>

<!-- Put site-specific property overrides in this file. -->

<configuration>
	<property>
	  <name>http.agent.name</name>
	  <value>test-crawler</value>
	  <description>HTTP 'User-Agent' request header. MUST NOT be empty - 
	  please set this to a single word uniquely related to your organization.

	  NOTE: You should also check other related properties:

	    http.robots.agents
	    http.agent.description
	    http.agent.url
	    http.agent.email
	    http.agent.version

	  and set their values appropriately.

	  </description>
	</property>
</configuration>

 

5. 크롤링을 하기 위해 Nutch가 제공하는 shell script를 확인합니다. Nutch 설치 폴더에서 bin/crawl을 아래와 같이 실행하여 명령어를 확인합니다.

 

6. bin/crawl -s <seed_dir> <crawl_dir> <num_rounds>를 아래와 같이 알맞게 입력하여 크롤링을 3회 실행합니다. 실행 시 아래 이미지와 같이 크롤링 실행 현황을 볼 수 있습니다. (3회만으로도 상당한 시간이 소요되니 테스트로 2~3회만 진행하세요)

bin/crawl -s data/seed data/crawl 3

 

7. 크롤링 결과가 저장된 data/crawl 폴더를 확인하면 사람이 알아 보기 어려운 형태로 저장되어 있습니다. 사람이 보기 편한 파일로 변경하는 기능으로 데이터를 변환합니다.

 

우선 nutch가 제공하는 다양한 기능을 확인하기 위해 nutch 설치 폴더에서 bin/nutch 명령어를 실행합니다.

 

이 중 dump가 data를 보기 편한 형태로 변환시켜줍니다. 아래와 같이 bin/nutch dump를 통해 명령어를 확인한 후 outputDir와 segmentDir를 알맞게 넣고 실행합니다.

bin/nutch dump -outputDir data/output -segment data/crawl/segments/

 

 

8. 결과가 저장된 data/ouput 폴더를 확인 합니다. json 파일은 URL과 HTML 저장 위치를 key value 값으로 가지고 있습니다. 특정 폴더에 들어가 HTML 파일을 확인할 수 있습니다.

 

{
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/f7/8d/f2fa63bd7a3aca63841eed4cd10fb519_SolrCloud.html":"https://cwiki.apache.org/confluence/display/solr/SolrCloud",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/de/94/ddf78b1fe5c268d59fd62bc745815b92_.html":"https://issues.apache.org/jira/browse/NUTCH/",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/59/89/5268b9b09193b68d8b7bada89c63c8e3_Becoming+A+Nutch+Developer.html":"https://cwiki.apache.org/confluence/display/NUTCH/Becoming+A+Nutch+Developer",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/e5/c1/e689627f55219bf2c6b7736c191aa55b_.html":"https://lucene.apache.org/",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/66/99/6b7bde9266afcb22980910d290d779db_solr.html":"https://lucene.apache.org/solr",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/ee/6f/e223c3dceeb6a4bd69de0cd4fa1ad080_.html":"https://accumulo.apache.org/",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/e6/24/e3fb513f6f0e50ea23896d884f9b59a9_nutch11.html":"https://s.apache.org/nutch11",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/02/57/0c1e6f9e2bcec9145de0653c778f0499_nutch_2.3":"https://s.apache.org/nutch_2.3",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/79/33/7b8095a69891f4ae363a13dd3e1d9944_.html":"https://gora.apache.org/",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/3f/bc/36f533cefea9e156bb7c181ec203d151_TheASF.html":"https://twitter.com/TheASF",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/50/26/5b987dde0da79d7f2e3f22b46437f514_bot.html":"http://nutch.apache.org/bot.html",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/5e/96/5e0ec8a1e0ccd04c9bcd902762d1de6d_FAQ.html":"https://cwiki.apache.org/confluence/display/NUTCH/FAQ",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/1f/2e/18017381fc3a1a5326279380ead7b16a_lqara.html":"https://s.apache.org/lqara",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/b4/eb/bc624e1b49e29870ef095819bb0e977a_mailing_lists.html":"http://nutch.apache.org/mailing_lists.html",
"/home/mech2cs/Downloads/nutch/apache-nutch-1.18/data/output/1b/e5/12ec6e48b752caf9ec09492c55daaec5_CHANGES.txt":"https://apache.org/dist/nutch/1.17/CHANGES.txt"}

 

'아파치 너치(Apache Nutch)' 카테고리의 다른 글

Web Crawler의 정의 및 Apache Nutch 구조  (0) 2021.06.29

Web Crawler의 정의

웹 크롤러는 spider, spiderbot이라고도 불리며 웹을 탐색하는 application이다. 웹 검색 엔진 구축을 위해 indexing 목적으로 사용되는게 일반적이다.

A Web crawler, sometimes called a spider or spiderbot and often shortened to crawler, is an Internet bot that systematically browses the World Wide Web, typically operated by search engines for the purpose of Web indexing (web spidering).
https://en.wikipedia.org/wiki/Web_crawler

 

  • Web Crawler는 특정 페이지에 접속해 원하는 데이터만 추출하는 기능에 집중된 Scraper와 유사하다. 하지만, 크롤링할 대상의 규모가 크기 때문에 몇가지 문제점을 추가로 가지고 있다.
    1. 가장 큰 문제는 순수히 Web의 방대한 양이다. 양을 측정하기 힘들며, 매 순간 증가하고 있다.
    2. web pages는 보통 검색 엔진이 통제하는 것이 아니다. 그래서 특정 도메인의 정보를 알 수 없는 경우가 있고 도메인 주인이 data를 공유하고 싶지 않을 수도 있는 한계가 있다.

 

  • 이런 문제점들을 해결하기 위해 고려해야할 사항들이 많다. 그 중 생각나는 일부는 아래와 같다.
    1. 웹 규모를 고려한 대용량 저장소
    2. 수많은 URL을 방문하기 위한 병렬구조 (다중 thread 등)
    3. 방문이 불필요한 URL을 판단할 수 있는 로직 (중복 제거, 재방문 주기 로직 등)
    4. 다양한 형태의 웹페이지를 수집할 수 있는 로직 (form results, javascript로 구성된 scripted pages 등)
    5. 크롤링 target 서버에게 무리를 주지 않기 위한 로직(politeness policy, robot exclusion protocol 등)
    6. 다양한 Encoding 지원

 

몇몇 논문과 도서와 오픈소스 웹 크롤러인 Apache Nutch를 보면 Web Crawler의 구조를 살펴볼 수 있다. 아주 오래 전에 설계되어 현재 상용 크롤러에선 어떤 구조를 가지고 있을지 상상하기 어렵다. 하지만, 아래 논문과 도서 등에서 확인한 구조는 명칭은 다르지만 모두 유사한 구조를 가지고 있다. 이 중 이 글에선 Apache Nutch의 구조를 간략하게 공유하고자 한다. 

https://courses.cs.washington.edu/courses/cse454/15wi/papers/mercator.pdf

https://ciir.cs.umass.edu/downloads/SEIRiP.pdf

http://nutch.apache.org/

 

 

 

Apache Nutch(Web Crawler)의 구조

Apache Nutch는 다양한 기능과 클래스를 제공하는데, 이 중 크게 5가지 Process가 반복하며 크롤링이 진행된다. (아래 그림 참조)

 

 

 

Inject

  • Seed URLs -> CrawlDB
  • Inject는 Text 파일 형태의 Seed URL을 Nutch가 URL을 관리하기 위한 메타데이터 저장소에 추가하는 작업을 한다. 크롤링의 시작 URL 역할을 하며 크롤링 중간에 새로운 URL을 강제적으로 주입시키는 역할도 한다.

Seed URL

Apache Nutch는 text 파일 형태로 해당 리스트를 가지고 있다. Seed URL을 인식하는 Process는 아래와 같다.

  1. Apache Nutch는 Seed URL을 저장하는 directory에 있는 모든 text 파일을 연다.

  2. line 단위로 불러와 URL을 읽어들인다.

  3. ## 으로 시작하는 line과 빈 line은 인식하지 않는다.

 

아래는 예시로 Seed URL 텍스트 파일을 하나 작성한 것이다.

## 이 라인은 주식으로 사용됩니다

## 너치
http://nutch.apache.org/
## 카프카
https://kafka.apache.org/
## 하둡
https://hadoop.apache.org/

 

CrawlDB

CrawlDB는 Apache Nutch가 크롤링을 위해 관리하는 URL 메타정보를 쌓기위한 DB이다. 해당 DB는 HDFS (Hadoop Distributed File System) 형태로 저장되어 있으며 압축되어 저장된다. 단순히 CrawlDB 관련 파일을 열면 아래와 같이 알아 볼 수 없는 형태로 되어 있다.

 

Apache Nutch가 제공하는 ReadDB 클래스를 사용하면 사람이 읽을 수 있는 text 파일 형태로 변형하여 볼 수 있다. 아래는 결과 파일이다.

 

 

Generate

CrawlDB에 저장된 URL 중 1 cycle (inject→generate→fetch→parse→dbupdate)에 방문할 URL n개를 추출하는 역할을 한다. 이렇게 추출된 URL은 generated URL이라고 부르며 Segment라는 단위로 저장된다.

Segment는 readSeg 클래스를 활용하면 해당 파일 내부를 볼 수 있다.

아래 그림은 generate된 상태에서 readSeg 클래스를 활용하여 내부를 본 결과이다.

 

Fetch

Generated된 URL을 방문하여 HTML Raw 파일을 다운받는 역할을 한다. 마찬가지로 segment 단위로 저장되며 readSeg를 통해 아래와 같이 파일 내부를 확인할 수 있다

 

 

Parse

Fetched된 HTML 파일을 link, text, metadata로 분리하여 나누어 저장하는 역할을 한다. 아래 그림을 참조하면 도움이 될 것이다.

 

DBUpdate

segment에 추가된 새로운 데이터를 crawlDB에 추가한다. Apache Nutch는 기존 URL들과 새로운 URL을 합쳐 score, 크롤링 시각, signature(중복 판단을 위한) 등의 정보를 저장한다. 아래는 readDB 메서드를 활용하여 내부를 확인한 결과이다.

 

 

여기까지 간단한 크롤러의 정의와 Apache Nutch의 구조에 대한 설명을 했다. 추후에 Apache Nutch를 실행하는 2가지 모드, 특정 상항에 필요한 적절한 설정방법 등을 소개하도록 하겠다.

'아파치 너치(Apache Nutch)' 카테고리의 다른 글

Apache Nutch Single Mode 크롤링  (0) 2021.06.29

소개

실행가능한 jar 파일을 만들기 위해 maven 명령어 mvn package를 사용하였는데 아래와 같은 에러가 발생하였습니다.

[ERROR] Error executing Maven.
[ERROR] java.lang.IllegalStateException: Unable to load cache item
[ERROR] Caused by: Unable to load cache item
[ERROR] Caused by: Could not initialize class com.google.inject.internal.cglib.core.$MethodWrapper

 

검색을 통해 알게된 내용은 우분투 패키지 관리 툴인 apt 에서 제공하는 maven 버전이 낮아 시스템에 설치된 자바 16버전과 호환이 안되어 발생한 에러였습니다.

위와 같은 에러 발생을 예방하기 위해 Ubuntu Maven 최신 버전을 수동으로 설치하게 되어 해당 내용을 정리하는 글입니다.

 

설치 프로세스

  1. 명령어를 통한 apache maven 최신 버전 압축 파일 다운로드
  2. /opt 폴더에 압축풀기
  3. 쉬운 maven 버전 관리를 위해 symbolic link 생성
  4. maven 환경 설정
  5. 버전 확인

참고 사이트

https://linuxize.com/post/how-to-install-apache-maven-on-ubuntu-18-04/

https://stackoverflow.com/questions/67334703/unable-to-compile-java-project-with-maven

 

 

설치 방법

1. 명령어를 통해 Apache Maven 최신 버전을 설치합니다(3.8.1 버전으로 진행하였습니다).

wget https://mirror.navercorp.com/apache/maven/maven-3/3.8.1/binaries/apache-maven-3.8.1-bin.tar.gz -P /tmp

 

2. /opt 폴더에 다운로드 받은 파일 압축을 풉니다

sudo tar xf /tmp/apache-maven-3.8.1-bin.tar.gz -C /opt

 

3. 쉬운 Maven 버전 관리를 위해 /opt/maven 에 설치된 maven의 심볼릭 링크를 생성합니다.

sudo ln -s /opt/apache-maven-3.8.1 /opt/maven

 

4. maven 경로 설정을 진행합니다. 아래 명령어를 통해 maven.sh 파일을 열고 아래 내용을 추가합니다.

sudo vi /etc/profile.d/maven.sh
export M2_HOME=/opt/maven
export MAVEN_HOME=/opt/maven
export PATH=${M2_HOME}/bin:${PATH}

 

5. maven.sh 파일에 실행 권한을 부여하고 실행합니다.

sudo chmod +x /etc/profile.d/maven.sh
source /etc/profile.d/maven.sh

 

6. 설치 확인을 위해 Maven 버전 확인을 합니다.

mvn -version

'우분투(Ubuntu)' 카테고리의 다른 글

Ubuntu 20.04 자바 JDK 설치 및 버전 관리  (0) 2021.05.24
Ubuntu 20.04 한글입력기 설치  (1) 2021.05.17

소개

  • Jackson은 자바에서 JSON(Javascript Objet Notation)을 사용하기 위해 사용하는 라이브러리 중 하나입니다.
  • 직렬화(serialization)는 데이터를 전송하거나 저장하기 위해 데이터를 적절한 포맷으로 변환하는 과정입니다. 프로그래밍 언어나 플랫폼에 독립적이고 표준화된 포맷이 직렬화에 많이 쓰이는데, JSON은 이런 포맷 중 하나입니다.
  • 프로젝트 내 Jackson Library 사용 중 LocalDateTime 포맷 직렬화 중 발생한 에러 조치 방법을 공유하고자 합니다.
  • Jackson 라이브러리 관련 내용은 아래 링크를 참조 바랍니다.
https://github.com/FasterXML/jackson

 

 

이 글의 간략한 PROCESS

  1. 자바8부터 지원하는 LocalDateTime, LocalDate를 제외한 다른 데이터 타입 필드를 가지는 객체 생성
  2. Serialize → Deserialize 작동 여부 확인
  3. LocalDateTime과 LocalDate를 객체에 추가
  4. Serialize → Deserialize 작동 여부 확인(오류 발생 확인)
  5. 해결 방법 공유

Jackson 사용방법

라이브러리는 Maven Repository를 통해 받을 수 있습니다.

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>


다양한 데이터 타입이 정상 작동하는지 여부를 확인하기 위해 다양한 타입의 필드를 가진 SampleObject 클래스와 테스트를 위한 간단한 메인 클래스를 만들었습니다.

package mech2cs;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SampleObject {

    public int int_ = 0;
    public Integer integerWrapper_ = Integer.valueOf(0);

    public String string_ = "testString";

    public double double_ = 0.0;
    public Double doubleWrapper_ = Double.valueOf(0.0);

    public float float_ = 0l;
    public Float floatWrapper_ = Float.valueOf(0l);

    public char char_ = 'a';
    public Character characterWrapper_ = Character.valueOf('a');

    public List<String> list_ = Arrays.asList("a", "b", "c");;
    public Map<String, String> map_ = Map.of("key1","value1","key2","value2");;
    public Set<String> set_ = Set.of("a","b");;

}

 

package mech2cs;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) {

        // 다양한 데이터 필드를 가진 객체 생성
        SampleObject sampleObject = new SampleObject();

        // Jackson Library를 활용한 {JAVA 객체} -> {JSON} 변환
        ObjectMapper objectMapper = new ObjectMapper();
        String serializedStr = null;
        try {
            serializedStr = objectMapper.writeValueAsString(sampleObject);
            System.out.println(serializedStr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        // Jackson Library를 활용한 {JSON} -> {JAVA 객체} 변환
        try {
            SampleObject resultObject = objectMapper.readValue(serializedStr, SampleObject.class);
        } catch (JsonProcessingException e) {
            System.out.println("Deserialize Failed");
            e.printStackTrace();
        }
    }
}


클래스 실행 결과는 아래와 같으며, 모든 데이터 타입들이 Json 형태로 잘 저장되는 것을 알 수 있습니다.

// 보기 편하게 줄바꿈
{
	"int_":0,
	"integerWrapper_":0,
	"string_":"sampleString",
	"double_":0.0,
	"doubleWrapper_":0.0,
	"float_":0.0,
	"floatWrapper_":0.0,
	"char_":"a",
	"characterWrapper_":"a",
	"list_":["a","b","c"],
	"map_":{"key2":"value2","key1":"value1"},
	"set_":["a","b"]
}


하지만 아래와 같이 SampleObject에 LocalDateTime과 LocalDate를 추가한 후 Main 메서드를 실행하게 되면 com.fasterxml.jackson.databind.exc.InvalidDefinitionException 에러가 발생하게 됩니다.

package mech2cs;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class SampleObject {

    public int int_ = 0;
    public Integer integerWrapper_ = Integer.valueOf(0);

    public String string_ = "testString";

    public double double_ = 0.0;
    public Double doubleWrapper_ = Double.valueOf(0.0);

    public float float_ = 0l;
    public Float floatWrapper_ = Float.valueOf(0l);

    public char char_ = 'a';
    public Character characterWrapper_ = Character.valueOf('a');

    public List<String> list_ = Arrays.asList("a", "b", "c");;
    public Map<String, String> map_ = Map.of("key1","value1","key2","value2");;
    public Set<String> set_ = Set.of("a","b");;

    // 새롭게 추가된 필드
    public LocalDateTime localDateTime_ = LocalDateTime.now();
    public LocalDate localDate_ = LocalDate.now();

}

해결방법

Jackson은 자바 8부터 추가된 LocalDateTime과 LocalDate 타입을 지원하기 위해 몇가지 모듈을 추가하였습니다 (아래 링크 참조). 모듈을 사용하기 위해 추가로 maven dependecies를 추가해야 합니다.

https://github.com/FasterXML/jackson-modules-java8
<dependency>
    <groupId>com.fasterxml.jackson.module</groupId>
    <artifactId>jackson-module-parameter-names</artifactId>
    <version>2.12.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jdk8</artifactId>
    <version>2.12.3</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>2.12.3</version>
</dependency>


위 링크에서 추천하는 방법을 통해 ObjectMapper에 모듈을 추가하는 코드를 넣고 실행하면 정상 결과를 출력하는 것을 볼 수 있습니다. (모듈 추가 방법1과 방법2 중 선택 가능합니다)

package mech2cs;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;

public class Main {
    public static void main(String[] args) {

        // 다양한 데이터 필드를 가진 객체 생성
        SampleObject sampleObject = new SampleObject();

        // Jackson Library를 활용한 {JAVA 객체} -> {JSON} 변환
        
        // 모듈 추가 방법 1
        ObjectMapper objectMapper = JsonMapper.builder()
                .addModule(new ParameterNamesModule())
                .addModule(new Jdk8Module())
                .addModule(new JavaTimeModule())
                .build(); // 모듈 추가
        // 모듈 추가 방법 2
        // ObjectMapper objectMapper = new ObjectMapper().findAndRegisterModules();

        String serializedStr = null;
        try {
            serializedStr = objectMapper.writeValueAsString(sampleObject);
            System.out.println(serializedStr);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        // Jackson Library를 활용한 {JSON} -> {JAVA 객체} 변환
        try {
            SampleObject resultObject = objectMapper.readValue(serializedStr, SampleObject.class);
        } catch (JsonProcessingException e) {
            System.out.println("Deserialize Failed");
            e.printStackTrace();
        }
    }
}
{
	...
	"localDateTime_":[2021,5,31,1,24,50,401107591],
	"localDate_":[2021,5,31]
}

소개

우분투에 자바를 설치하는 몇가지 방법이 있습니다.

이 글에선 설치가 비교적 간단하고 자바 버전관리도 쉽다고 판단되어 package 관리자를 통한 설치 방법JDK 버전을 쉽게 변경하는 방법을 공유합니다.

 

간단한 설치 프로세스는 아래와 같습니다.

  1. apt 패키지 정보 업데이트
  2. 자바 JDK 설치
  3. bashrc에 JAVA_HOME 추가
  4. bashrc 실행

간단한 자바 버전 변경 프로세스는 아래와 같습니다.

  1. JAVA 버전 확인
  2. update-alternatives 명령어를 통해 자바 버전 변경
  3. JAVA 버전 확인

 

설치 방법

1. apt 패키지 인덱스 정보를 아래 명령어로 업데이트하여 자바 리스트를 갱신합니다.

sudo apt update

 

2. 원하는 자바 버전을 설치합니다. 이 글에선 8버전과 16버전을 선택하였습니다.

sudo apt install openjdk-8-jdk
sudo apt install openjdk-16-jdk

 

3. bashrc에 JAVA_HOME을 추가합니다.

  • export 명령어에 대한 설명은 이 글 맨 아래에 추가하였습니다.
  • 많은 application(Apache Hadoop 등)은 자바 위치를 찾기위해 JAVA_HOME 변수를 참조합니다. 이에 다른 어플리케이션에서 쉽게 사용할 수 있도록, JAVA_HOME을 설정합니다.
sudo vi ~/.bashrc
export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")

4. bashrc 변경 사항을 적용하기 위해 아래 명령어를 통해 bashrc를 1회 실행합니다

source ~/.bashrc

 

버전 변경 방법

1. Ubuntu에서 application들의 다양한 버전 관리를 담당하는 update-alternatives 명령어를 이용하여 설치된 자바 버전을 확인합니다.

# 현재 자바 버전 확인
java -version

# 설치된 자바 버전 리스트 확인
update-alternatives --list java

 

2. 버전을 변경하고자 한다면 아래 명령어 2가지를 실행한 후 java와 javac의 버전을 변경해 줍니다.

sudo update-alternatives --config java
sudo update-alternatives --config javac

 

3. 현재 자바 버전이 변경되었는지 확인합니다.

java -version

 

 

update-alternatives에 대한 추가 설명

  • /usr/bin/java 는 우분투에서 자바 명령어를 실행하기 위해 자바 설치시 자동으로 추가된 심볼릭 링크이며, /etc/alternatives/java 를 가르키고 있습니다.
  • /etc/alternatives/javaupdate-alternatives 에서 관리 중이며, 실제로 설치된 자바 디렉토리를 가르킵니다. sudo update-alternatives --config java 명령어를 통해 자바 디렉토리를 변경 가능합니다.
  • 링크를 정리하자면 /usr/bin/java/etc/alternatives/javaactual java directory 의 형태를 가지고 있습니다. 아래 readlink 명령어를 통해 보이는 link가 확인 가능합니다.

 

 

bashrc에 export 명령어가 하는 일

export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::")

1. readlink -f /usr/bin/java 는 해당 심볼릭 링크가 가르키는 최종 directory나 file의 경로를 가지고 옵니다(위 그림 참조)

2. sed "s:bin/java::" 는 문자열의 마지막 bin/java 를 제거해줍니다.

3. export JAVA_HOME=$(readlink -f /usr/bin/java | sed "s:bin/java::") 를 통해 JAVA_HOME이 update-alternatives가 관리하는 directory로 동적으로 변경하게 해줍니다.

 

우분투에서 기본적으로 지원하는 한글 입력기는 Telegram 등의 특정 앱에서 한글 입력이 안되는 현상이있습니다. 이를 해결하기 위한 방법으로 fcitx 입력기를 설치하는 방법을 공유합니다.

설치 PROCESS

 

  1. Terminal을 연 후 아래 명령어를 실행 후 fcitx-hangul 입력기 설치

    sudo apt install fcitx-hangul
    

     

     

  2. Ubuntu 화면 왼쪽 아래 부분에 있는 Show Applications 실행 후 Language Support 실행

  3. language pack 설치 안내가 나오면 설치 완료 후 Keyboard input method system을 fcitx로 변경한 후 컴퓨터 재부팅

  1. 재시작 후 화면 우측 상단에 생긴 키보드 모양을 클릭한 후 Configure Current Input Method 클릭

  1. [+] 버튼을 누른 후 Only Show Current Language를 체크해지 한 후 Hangul을 검색한 후 추가

  1. 아래 그림의 톱니바퀴를 눌러 Hangul 키보드 설정에 들어가 Hanja Mode가 체크되있다면 해지한 후 OK 클릭

    • 한자 입력모드가 자동으로 켜지는 현상을 방지하기 위한 절차입니다. 체크가 이미 해지되어 있는 경우도 있습니다.

  1. gnome-tweak-tool 설치 및 실행

    • 한영 변환이 잘되는 경우는 7번부터 진행하지 않아도 됩니다. 7번 process 부터는 키보드가 한/영 변환키가 없고 Alt키가 있는 경우 Alt키를 한/영 키로 매핑하는 작업입니다.

      sudo apt install gnome-tweak-tool
      gnome-tweaks
      

  1. Keyboard & Mouse Tab에서 Additional Layout Options을 선택한 후 [왼쪽 Alt] 키를 [Hangul]로 교체

    • Make right Alt a Hangul key 선택
    • Make right Ctrl a Hanja key 선택

  1. Global Config Tab에 들어가 Trigger Input Method를 선택후 Alt를 눌러 아래 그림과 같이 변경해주기

+ Recent posts