0%

개요

얼마 전 Maven 프로젝트에 custom jar를 local repository에 등록해서 사용해야하는 경우가 있었는데, 구체적인 방법을 몰라서 상당히 애를 먹었었다.

평소 대충 되면 되나보다 하고 넘어가며 딱히 Maven에 대한 공부를 게을리 한게 이렇게 고생하게 만들 줄이야.

Maven 프로젝트로 A 프로젝트를 만들어 a.jar를 만들고, 별도의 B 프로젝트에서 앞서 만든 a.jar를 local repository로 주입받아 사용하는 예제를 만들어 보겠다.

예제를 만들고 테스트하며 그 내용을 시간의 흐름대로 작성한 글이라 두서가 없다는 점을 미리 알린다.

a.jar를 만들 Maven 프로젝트 만들기

일단 intelliJ 에서 Maven 프로젝트를 만들어 보자.

Maven%20local%20repository%20jar/Untitled.png

Maven%20local%20repository%20jar/Untitled%201.png

Maven%20local%20repository%20jar/Untitled%202.png

Maven%20local%20repository%20jar/Untitled%203.png

위 화면들 처럼 Aproject라는 Maven 프로젝트를 만들었다.

Maven%20local%20repository%20jar/Untitled%204.png

생성된 프로젝트에서 App 클래스에 main 메소드에서 이 프로젝트가 A project 임을 명시했다.

실행해보니 콘솔에 System.out.println이 정상적으로 동작하는 것을 확인 할 수 있다.

지금 Aproject에는 App클래스와 그 안에 main 메소드만 덩그러니 있다.

나중에 생성할 Bproject에서 사용할 service 클래스를 추가하자.

Maven%20local%20repository%20jar/Untitled%205.png

위처럼 문자열을 리턴하는 service 클래스를 추가했다.

위 프로젝트를 Maven package 명령으로 jar를 만들고, 그 jar를 실행시키면 아래처럼 오류가 발생 할 것이다..

Maven%20local%20repository%20jar/Untitled%206.png

위처럼 Maven clean 성공.

Maven%20local%20repository%20jar/Untitled%207.png

그리고 Maven package 명령으로 Aproject의 jar를 생성했다.

생성된 jar를 java 명령으로 실행시키면 정작 아래처럼 메세지와 동작하지 않는다.

1
메세지: 기본 Manifest 속성이 없습니다.

Maven%20local%20repository%20jar/Untitled%208.png

실행 가능한 jar를 만들기 위해서는, 해당 jar파일을 실행하기위한 일종의 명세서 파일이 필요하다.

이 파일은 jar 파일 내부에 존재 해야 한다.

지금 Maven 프로젝트 build 설정에서는 그 명세서 파일(MANIFEST.MF)을 Maven package 명령시 자동으로 만들어주지 않아서 위처럼 jar가 실행되지 않는 것이다.

실행가능한 Maven jar 설정 추가하기

이제 위 프로젝트를 실행가능한 jar 프로젝트로 만들어 보자.

일단 pom.xml파일에 아래처럼 packaging을 jar로 하겠다고 명시한다.

Maven%20local%20repository%20jar/Untitled%209.png

그리고 기존의 build 부분을 아래처럼 수정해주자.

Maven%20local%20repository%20jar/Untitled%2010.png

중요한 부분은 mainClass태그 내부에 해당 프로젝트의 앤트리 포인트가 되는 클래스의 경로를 넣어주어야 한다.

pom.xml 전체소스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>Aproject</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<name>Aproject</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<mainClass>
org.example.App
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

이제 다시 maven clean 후 maven package 를 실행시켜 새로 jar파일을 생성하고 실행해보자.

Maven%20local%20repository%20jar/Untitled%2011.png

위처럼 jar파일을 직접 실행시켰을때, 정상동작하는 것을 확인 할 수 있다.

내가 개발한 일종의 커스텀 jar파일을 생성했다.

그럼 이제 새로운 B 프로젝트를 생성하고 이 jar 파일을 사용하려면 어떻게 해야 할까?

경우의 수는 다음과 같을 것이다.

  1. 만약 당신이 오픈소스를 개발한다면, 그냥 maven repository에 올려서 사용하면 될 것이다.
  2. 만약 당신이 인터넷망이 아닌, 일종의 사내망에서 개발중이고 사내망에 nexus와 같은 사설 maven 저장소가 존재한다면 그곳에 올려서 사용 할 수도 있을 것이다.
  3. 다 귀찮다. 그냥 해당 a. jar파일을 새로운 프로젝트B에 직접 주입해서 사용할 것이고, B프로젝트를 pakcage 했을때, 일종의 외부 라이브러리인 a.jar 가 같이 패키징이 되어야 한다.

내가 지금 할 방법은 3번이다.

Maven local repository를 사용해서 특정 jar파일을 프로젝트에 포함시키기

Maven local repository를 강조하는 이유는, 내가 이 글을 쓰는 목적이기도 한다.

Eclipce나 IntelliJ와 같은 툴에서는 자체적으로 외부라이브러리를 추가하는 설정이 존재한다.

Eclipce의 경우 External library 같은 설정으로 있었던 기억이 있다.

위와 같이 개발도구의 설정으로 jar를 추가할 경우, 개발할때는 문제가 없지만, 정작 프로젝트를 package 했을때, 내가 임이로 추가한 jar라 같이 패키징이 안되는 경우가 있다.

따라서 내가 임의로 jar등을 외부 라이브러리로 추가할 때는 개발도구의 설정을 사용하기보다는, 개발 중인 프로젝트의 build 도구(Maven, gradle)의 설정으로 jar 외부 라이브러리를 추가하는 것이 깔끔하다.

새로운 Maven 프로젝트를 생성하겠다.

프로젝트명은 Bproject이다. 생성방법은 위 Aproject와 동일하기 때문에, 그 과정은 생략하겠다.

Maven%20local%20repository%20jar/Untitled%2012.png

위처럼 이름만 다른 Bproject를 생성했다.

그 다음에 Bproject의 pom.xml을 다음과 같이 수정해주자.

pom.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>Bproject</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>

<name>Bproject</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<repositories>
<repository>
<id>localrepository</id>
<url>file://${basedir}/lib</url>
</repository>
</repositories>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.example</groupId>
<artifactId>Aproject</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>

</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>
org.example.App
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>
${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

Maven%20local%20repository%20jar/Untitled%2013.png

Aproject와 마찬가지로 jar 설정을 해준다.

Maven%20local%20repository%20jar/Untitled%2014.png

역시 Aproject와 마찬가지로 실행가능한 jar 생성을 위한 build plugin 설정도 추가해준다.

아래 부분이 실제 Maven에서 local repository를 설정하는 부분이다.

Maven%20local%20repository%20jar/Untitled%2015.png

id는 본인이 편한 고유값을 주면 된다.

url은 maven local repository의 jar 파일들이 있을 경로를 설정하는 부분이다.

관리하기 쉽게 위 처럼 basedir이라는 변수를 사용해서, 현재 프로젝트 root 경로에 lib 폴더를 설정했다.

이제 해야할 일은 Aproject에서 jar 파일과 pom 파일을 추출해야 한다.

Aproject로 돌아가서 jar파일과 pom파일을 추출하자.

Maven local repository를 위한 jar 추출하기

Aproject에서 maven clean 후 maven install 을 하자.

maven install을 하면 해당 프로젝트를 빌드해서 현재 pc의 전역 메이븐 저장소에 저장하게 된다.

Maven%20local%20repository%20jar/Untitled%2016.png

설치가 잘 되었는지 현재 pc의 메이븐 전역 저장소를 확인해보자.

윈도우 탐색기로 C:\Users\계정명.m2\repository 가면 메이븐 전역 저장소를 확인 할수 있다.

Aproject의 경로는 groupId와 artifactId 그리고 version 으로 경로가 조합되어 생선된다.

Maven%20local%20repository%20jar/Untitled%2017.png

해당 경로에 가보면 jar파일과 pom 파일이 생성된 것을 확인 할 수 있다.

위 Aproject 폴더를 통째로 복사하자.

그리고 Bproject 폴더로 이동해서 프로젝트 root 경로에 lib 폴더를 만들고 아래처럼 붙여넣자.

Maven%20local%20repository%20jar/Untitled%2018.png

그리고 Bproject의 pom.xml 에 아래처럼 해당 jar를 디펜던시로 추가해주자.

Maven%20local%20repository%20jar/Untitled%2019.png

lib 폴더의 경로와 pom.xml의 dependency groupId, artifactId, version을 잘 맞쳐주어야 오류가 나지 않는다.

Bproject의 main 메소드에서 추가한 자르의 Aservice클래스를 가져와서 호출하는 코드를 추가하고 실행하면 아래처럼 정상 동작을 확인 할 수 있다.

Maven%20local%20repository%20jar/Untitled%2020.png

여기까지 해서 된다고 안심 하면 안된다.

사실 maven local repository 설정 없이, 전역 maven 저장소에 maven install 로 설치되어 있다면 위처럼 개발툴에서 코드상에서 해당 jar를 가져와서 호출이 가능하다.

하지만 maven local repository 설정이 없다면 Bproject를 maven package해서 생성한 jar를 실행할 경우, 해당 jar를 찾지 못하고 오류가 날 것이다.

아래가 maven local repository 설정없이 maven package했을때, 라이브러리를 찾지 못하고 오류가 난 상황이다.

Maven%20local%20repository%20jar/Untitled%2021.png

하지만 우리는 앞서

pom.xml에 서 아래처럼 maven local repository 경로를 설정했고

Maven%20local%20repository%20jar/Untitled%2015.png

또 아래처럼 Aproject의 install 결과물을 해당 경로에 이동 시켰으며

Maven%20local%20repository%20jar/Untitled%2018.png

pom.xml 에 아래처럼 해당 라이브러리를 추가했기 때문에

Maven%20local%20repository%20jar/Untitled%2019.png

Bproject를 maven package하여 생성한 jar를 실행 시켰을때, 아래처럼 정상동작하는 것을 확인 할수 있다.

Maven%20local%20repository%20jar/Untitled%2022.png

끝!!!

예제 github 경로

https://github.com/hanumoka/20200124blog-maven-local-repository

참고자료

https://stackoverflow.com/questions/5692256/maven-best-way-of-linking-custom-external-jar-to-my-project

https://okjsp.tistory.com/1165644118

https://denodo1.tistory.com/282

https://blog.seotory.com/post/2016/03/maven-local-repository-setting

https://yujuwon.tistory.com/entry/maven에-custom-jar를-집어넣어-보자

개요

Create React App으로 배포 테스트용 React 프로젝트를 만들고, 빌드하여 배포하는 실습을 진행해보도록 하겠다.

실습 환경은 ubuntu 18.04 가상머신에서 진행하였으며, 기본적으로 nvm, node, npm(npx사용 가능한 버전)이 설치되어 있는 환경이다.

Ubuntu에 설치된 Nginx에 React 배포

ubuntu 18.04에 직접 설치된 Nginx 서버에 React를 배포해보자.

일단 현재 계정의 home 디렉토리에 examples 폴더를 만들고, 그 내부에서 create-react-app을 이용해서 배포할 리액트 프로젝트를 생성해보자.

create-react-app으로 배포할 react 프로젝트 생성

React%20Nginx/Untitled.png

1
npx create-react-app myapp

React%20Nginx/Untitled%201.png

위처럼 원하는 경로에 배포 태스트할 react 프로젝트를 생성하자.

create-react-app으로 프로젝트 생성이 완료되면 다음 명령어로 동작을 확인하자.

1
2
cd myapp
npm start

React%20Nginx/Untitled%202.png

React%20Nginx/Untitled%203.png

위처럼 localhost:3000으로 접속해서 방금 생성한 react 프로젝트 실행을 확인 했다.

react 프로젝트 build 하기

생성된 react 프로젝트를 build 해보자.

create-react-app 으로 생성한 react 프로젝트는 기본적으로 webpack이라는 번들러를 통해서 빌드 결과물을 생성한다.

프로젝트 경로에서 아래 명령어를 입력하자.

1
npm run build

React%20Nginx/Untitled%204.png

위처럼 react build가 진행되며 프로젝트 디렉토리 내부의 build 라는 폴더에 빌드 결과물이 생성된다.

React%20Nginx/Untitled%205.png

우리는 이 빌드 결과물이 있는 경로를 나중에 설정할 nginx라는 웹서버에게 알려줘야 한다.

정적인 웹을 위한 리소스를 번들링해주는 웹팩이라는 녀석은 정말 신기방기 한것 같다.

ubuntu18.04에 nginx 설치하기

이제 웹서비스를 위한 웹서버를 설치해보자.

다음 명령어로 설치하자.

1
sudo apt install nginx

설치가 완료되면 /etc/nginx 경로에 방금 설치된 nginx웹서버의 설정파일들이 생긴다.

참고:Nginx 기본파일과 폴더들

  • sites-available : 가상 서버 환경들에 대한 설정 파일들이 위치하는 부분입니다. 가상 서버를 사용하거나 사용하지 않던간에 그에 대한 설정 파일들이 위치하는 곳이다.
  • sites-enabled : sites-available 에 있는 가상 서버 파일들중에서 실행시키고 싶은 파일을 symlink로 연결한 폴더입니다. 실제로 이 폴더에 위치한 가상서버 환경 파일들을 읽어서 서버를 세팅합니다.
  • nginx.conf : Nginx에 관한 설정파일로 Nginx 설정에 관한 블록들이 작성되어 있으며 이 파일에서 sites-enabled 폴더에 있는 파일들을 가져옵니다.

그중 아래처럼 sites-available, sites-enabled 폴더를 수정하게 된다.

혹시 모르니 이 폴더들을 미리 백업해 놓자.

React%20Nginx/Untitled%206.png

1
2
sudo cp -r /etc/nginx/sites-available/ /etc/nginx/sites-available-origin
sudo cp -r /etc/nginx/sites-enabled/ /etc/nginx/sites-enabled-origin

그 다음에 sites-available, sites-enabled 폴더 내부의 default 설정 파일들을 아래 명령어로 제거해주자.

1
2
sudo rm /etc/nginx/sites-available/default
sudo rm /etc/nginx/sites-enabled/default

React%20Nginx/Untitled%207.png

그리고 앞서 생성한 react 프로젝트의 build 결과물을 배포할 설정 파일을 생성하자.

1
sudo touch /etc/nginx/sites-available/myapp.conf

그리고 내용을 아래처럼 채워준다.

1
2
3
4
5
6
7
8
server {
listen 80;
location / {
root /home/hanumoka/examples/myapp/build;
index index.html index.htm;
try_files $uri /index.html;
}
}

위 설정을 보면 해당 설정은 80포트로 서비스 한다는 것을 보여준다.

location / 이부분은 루트 진입시 설정이다.

root 설정은 앞서 생성한 react 프로젝트의 build 폴더 경로를 설정한다.

index 설정은 해당 폴더에서 redirect 할 index html 파일에 대한 설정이다. 앞 부터 우선순위가 있다.

try_files 설정은 좀 중요해보인다.

nginx를 잘 써보지 않아 이번에 찾아 봤는데, react 프로젝트의 경우 페이지 라우팅을 react-router가 보통 하게 될것이다.

즉 index.html 자체에서 페이지 라우팅을 하는 것이다.

try_files 설정은 일종의 nginx 자체의 라우팅 설정이다. 보통 이 부분에서 특정 패턴의 url에 특정 파일등을 redirct 하는 설정을 한다. 만약 페이지를 못 찾을 경우 404 not found 설정등도 이곳에서 한다.

하지만 react 프로젝트인 경우, 웹서버에서 먼저 리퀘스트 url 을 가로채면 react-router의 기능을 사용할수 없게 된다.(vue등도 마찬가지일 것이다.)

따라서 위처럼 모든 request를 index.html로 곧장 가게 설정해 줘야 한다.

sites-available 폴더에 가상호스트 설정을 끝냈다.

하지만 이 설정만으로는 서비스가 동작하지 않는다. 방금 생성한 설정파일을 sites-enabled 폴더로 symlink해야 해당서비스가 활성화 되며 실제 서비스가 가능한 상태가 된다.

아래 명령어를 입력해서 site-enabled 폴더에 심볼릭 링크를 만들자.

1
sudo ln -s /etc/nginx/sites-available/myapp.conf /etc/nginx/sites-enabled/myapp.conf

React%20Nginx/Untitled%208.png

위처럼 심볼릭 링크를 생성했다.

Nginx를 재기동하고 동작을 확인보자.

1
2
3
sudo systemctl stop nginx
sudo systemctl start nginx
sudo systemctl status nginx

React%20Nginx/Untitled%209.png

위처럼 nginx를 재기동하고 동작을 확인했다.

(주의: ubuntu 방화벽에서 80포트를 허가 해야 외부에서 접근이 가능하다. 아래 명령어로 포트를 방화벽에서 허용 시킬수 있다.)

1
sudo iptables -I INPUT 1 -p tcp --dport 80-j ACCEPT

아래처럼 nginx에 react가 정상적으로 배포된 것을 알 수 있다.

React%20Nginx/Untitled%2010.png

만약 아래처럼 nginx가 500 Internal Server Error 에러를 던진다면 /etc/nginx/sites-available/myapp.conf 파일에 문제가 있을 가능성이 있다.

내 경우 build 경로에 오타가 있을경우 500에러가 발생했다.

React%20Nginx/Untitled%2011.png

해당 설정파일을 다시 확인하고, nginx 를 재부팅하니 정상동작했다.

끝!!!

참고자료

ubuntu에 create react app을 nginx로 배포하기

https://codechacha.com/ko/deploy-react-with-nginx/

create react app을 nginx 도커나이즈 배포하기

https://codechacha.com/ko/dockerizing-react-with-nginx/

nginx에러 로그 확인

https://annajinee.tistory.com/17

nginx try_files 설정

https://stackoverflow.com/questions/43951720/react-router-and-nginx

개요

ubuntu 에서 열려 있는 포트를 확인하고, 원하는 포트를 열어보자.

포트열기

1
netstat -nap

위 명령어를 입력하면, 열려 있는 모든 포트를 확인 한다.

ubuntu18%2004/Untitled.png

상당히 많은 정보를 보여준다.

뭔가 시스템에서 내부적으로 점유하고 있는 포트가 많은것 같다.

리스트 최 상단 부분에 현재 22포트가 열려 있는 것을 확인 할 수 있다.

아래 명령어로 현재 LISTEN 중인 포트만 추려서 볼 수 있다.

1
netstat -nap | grep LISTEN

ubuntu18%2004/Untitled%201.png

인터넷을 찾아보면 아래처럼 특정 포트의 상태를 확인하라고 나오는데, 사실 불필요한 정보가 너무 많이 보이기는 한다.

1
netstat -nap | grep 22

ubuntu18%2004/Untitled%202.png

이번에는 원하는 포트를 방화벽에서 열어보자.

3000, 4000 번 포트를 다음과 같이 열었다.

1
2
sudo iptables -I INPUT 1 -p tcp --dport 3000 -j ACCEPT
sudo iptables -I INPUT 1 -p tcp --dport 4000 -j ACCEPT

ubuntu18%2004/Untitled%203.png

포트가 재대로 열렸는지 확인을 위해, 3000포트를 사용하는 react 프로젝트를 돌렸다.

아래처럼 정상적으로 포트가 열려서, 외부에서 접근이 가능한 것을 확인 할 수 있다. (로컬 버추얼박스 우분투를 사용한 것이라 브라우저에서 localhost로 접근했지만, 외부에서 접근한 것이다.)

ubuntu18%2004/Untitled%204.png

끝!!!

참고자료

https://server-engineer.tistory.com/418

개요

ubuntu 18.04 에 NVM, node, npm 을 설치하고 react 를 개발할수 있는 create react app을 설치해보자.

NVM 설치하기

1
curl -sL https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh -o install_nvm.sh

위 명령어를 이용해서 nvm 설치스크립트를 다운로드 한다.

1
bash install_nvm.sh

위 명령어를 이용해서 다운로드한 nvm 설치 스크립트를 실행 시킨다.

설치 스크립트가 실행되면서 export명령이 자동으로 동작하여 nvm에 필요한 환경변수를 설정해 준다.

아래 명령어로 os 가 리부트 되도 환경변수가 유지되게 설정하자.

1
source ~/.profile

아래 명령어를 사용하면 이제 nvm으로 사용가능한 node 버전이 리스트로 출력된다.

1
nvm ls-remote

1
nvm install 12.14.0

2019.12.28 기준으로 node 12.14.0이 최신 LTS라고 나온다.

위 명령으로 원하는 버전의 node를 설치하자.

아래처럼 node와 npm이 설치된 것을 확인할 수 있다.

Create react app 설치

1
2
npm install -g create-react-app
create-react-app test-react-project

위 명령어를 이용해서 create-react-app을 전역에 설치하고 react 프로젝트를 생성 할수 있지만, 아래의 npx 명령으로 create-react-app을 이용해서 react 프로젝트를 만들기를 추천한다.

NPM 5.2 버전 이후 NPX라는 node.js package 메니저를 이용해서 create-react-app을 실행할 수도 있다.

npx 명령어는 npm의 진화형태라고 보면된다.

속도도 npm보다 빠르다고 하며, 필요한 패키지를 전역에 설치하지 않고 필요할때 최신 패키지를 임시로 받아와서 설치해서 사용하게 된다.

npm 을 사용할 경우 글로벌 모듈이 혼잡해지는 것을 npx로 해결한다고 한다.

1
npx create-react-app test-react-project

생성된 프로젝트에 진입해서 react를 실행시키자.

1
2
cd test-react-project
npm

프로젝트가 실행되면 http://localhost:3000/ 로 접속해서 확인해 볼 수 있다.

참고자료

ubuntu create-react-app 설치

https://www.techomoro.com/how-to-install-and-setup-a-react-app-on-ubuntu-18-04-1/

npx 설명

[https://ljh86029926.gitbook.io/coding-apple-react/undefined/npm-npx](

개요

ubuntu18.04에 NVM으로 Node를 설치해보겠다.

ubuntu에 node를 설치해보신 분들을 알겠지만, 이게 여간 귀찮은 것이 아니다.

ubuntu에 패키지 메니저인 apt로 node를 설치할경우 2019.12.28 현재 기준으로 node 8버전을 설치시켜준다. ㅡㅡ;;;;;

물론 최신 버전을 설치할 수 있지만, 리눅스에서는 NVM(Node Versioin Manager)를 이용해서, 동시에 여러개의 node를 설치하고 상황에 따라서 원하는 버전을 선택해서 사용할 수 있다.

NVM 설치하기

curl -sL https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh -o install_nvm.sh

위 명령어를 이용해서 nvm 설치스크립트를 다운로드 한다.

bash install_nvm.sh

위 명령어를 이용해서 다운로드한 nvm 설치 스크립트를 실행 시킨다.

설치 스크립트가 실행되면서 export명령이 자동으로 동작하여 nvm에 필요한 환경변수를 설정해 준다.

아래 명령어로 os 가 리부트 되도 환경변수가 유지되게 설정하자.

source ~/.profile

Ubuntu18%2004%20NVM%20NODE/Untitled.png

아래 명령어를 사용하면 이제 nvm으로 사용가능한 node 버전이 리스트로 출력된다.

nvm ls-remote

Ubuntu18%2004%20NVM%20NODE/Untitled%201.png

nvm install 12.14.0

2019.12.28 기준으로 node 12.14.0이 최신 LTS라고 나온다.

위 명령으로 원하는 버전의 node를 설치하자.

아래처럼 node와 npm이 설치된 것을 확인할 수 있다.

Ubuntu18%2004%20NVM%20NODE/Untitled%202.png

끝!!!

NVM에 더 자세한 사용법등을 알고 싶다면, 아래 참고자료를 살피길 바란다.

참고자료

https://www.digitalocean.com/community/tutorials/how-to-install-node-js-on-ubuntu-18-04

문제발생

나는 코딩 테스트나 개발환경 셋팅을 할때, 그것들을 기록하고 싶은경우 OBS Studio 라는 화면 녹화 프로그램을 사용한다.

노트북에서 OBS Studio를 잘 쓰다가, 뭔가 업데이트(Windows인지, Nvidia인지 모르겠지만)된 뒤로 갑작이 OBS Studio의 디스플레이 캡쳐가 검은 화면으로 나오면서, 녹화시에 검은 화면만 녹화가 되었다.

참고로 특정 Window 화면 녹화는 정상적으로 되었다.

해결방법

내 경우에는 다음과 같은 방법으로 문제를 해결 했다.

만약 OBS studio가 실행중이라면 일단 종료를 시킨다.

그리고 바탕화면에서 마우스 우클릭으로 NVIDIA 제어판으로 들어간다.

설정1

열린 NVIDIA 제어판에서 3D 설정 - 3D설정 관리로 화면 진입후 프로그램 설정 탭을 선택한다.

내 경우에는 1.사용자 정의할 프로그램 선택에 OBS Studio가 이미 등록이 되어 있었으나, 만약 없다면 추가 버튼으로 OBS Studio를 추가해 준다.

그리고 2.이 프로그램에 대한 기본 그래픽 프로세서 선택에서 통합 그래픽을 선택하고 적용버튼을 클릭해서 설정을 저장한다.

이 설정으로 나는 문제를 해결 했다.

설정2

끝!!!

엘라스틱서치 입문과 활용

1.엘라스틱 서치 개요

1-1.엘라스틱 서치란

우리는 지금 정보의 홍수 속에 살고 있다. 매일 매초 인터넷에 연결된 수없이 많은 시스템으로부터 헤아릴 수 없을 만큼 많은 데이터가 쏟아져 나오고 있으며, 이 데이터로부터 의미 있고 가치 있는 정보를 뽑아내기 위한 시스템 또한 수도 없이 개발되고 있다.

특히 SNS와 각종 포털 사이트에서 사용자의 활동 정보 등에 대한 대용량 데이터의 실시간 분석 기술은 빅데이터라는 이름의 트렌드로 자리 잡으며 수많은 업체와 정부 기관에 데이터 활용의 새 지평을 열었다.

이와 같은 정보의 홍수속에서 필요로 하는 정확한 데이터를 검색하여 찾는 기술은 무엇보다 중요해 졌다. 데이터를 검색하는데 있어 전 세계적으로 가장 널리 사용되고 있는 기술중 하나가 바로 아파치 루씬(Apache Lucene)이다.

자바로 개발된 루씬은 오픈소스로 현재 아파치 Top 레벨 프로젝트로 등록돼 있다.

루씬은 강력한 검색 기능이 있지만, 완전한 솔루션이 아닌 라이브러리로 제공되기 대문에 개인이나 기업에서 실제로 사용혀려면 루씬 라이브러리를 이용해 검색 솔루션을 스스로 개발해야 한다.

아파치 루씬 라이브러리를 실무에 사용하기 위해 티카(Tica), 솔라(Solr)등의 솔루션이 개발되어 있는데 가장 최근에 개발돼 선풍적인 인기를 끌고 있는 솔루션이 바로 엘라스틱 서치이다.

엘라스틱서치는 샤이 배논(Shay Bannon)이 개발했으며 현재 오픈소스 프로젝트로 진행되고 있다.

엘라스틱 서치를 이용하여 분산환경에서의 병렬 처리와 실시간 검색을 지원하고, 확장성이 뛰어난 대규모 시스템을 쉽게 구축할 수 있다.

엘라스틱 서치를 요약하자면, 빅데이터(비정형데이터)로부터 원하는 데이터를 검색하기 위한 검색엔진 솔루션이라고 할수 있다.

1-2. 용어 정리를 통한 엘라스틱서치의 이해

네이버나 구글에서 제공하는 다양한 서비스는 일상에서 빼놓을 수 없는 서비스로 자리매김했다.

그중에서도 사용자가 원하는 검색어에 대한 결과를 제공하는 검색 서비스가 가장 많이 사용되고 있다.

그리고 이러한 검색 서비스를 부르는 용어도 다양하다.

검색엔진, 검색시스템, 검색서비스 등의 용어가 대표적인데 무언가 비슷하면서도 다른 듯한 알쏭달쏭한 느낌이 든다.

먼저 검색엔진(Search engine)은 광활한 데이터에서 원하는 검색결과는 제공하는 프로그램이다.

검색엔진은 검색 결과로 제공되는 데이터의 특성에 따라 구현 형태가 각각 달라진다.

검색 역사에 한 획을 그은 야후(Yahoo)는 디렉터리 기반의 검색 결과를 세계 최초로 제공했다.

이를 바탕으로 요즘에는 뉴스, 블로그, 카페 등 대범주에 따른 카테고리별 검색결과를 대부분의 검색 업체에서 제공하고 있다.

검색 시스템(Search system)은 대용량 데이터를 기반으로 신뢰성 있는 검색 결과를 제공하기 위해 검색엔진을 기반으로 구축된 시스템을 통칭하는 용어다.

수집기를 이용해 방대한 데이터를 수집하고 이를 다수의 검색엔진을 이용해 색인하고 검색결과를 UI로 제공한다.

시스템 내부의 정책에 따라 관련도가 다수 높은 문서를 검색 결과의 상위에 배치할 수 있을뿐더러 특정 필드나 문서에 가중치를 둬서 검색의 정확도를 높일 수도 있다.

검색 서비스(search service)는 검색엔진을 기반으로 구축한 검색 시스템을 활용해 검색 결과를 서비스로 제공한다.

엄밀히 말하자면 엘라스틱서치는 검색엔진으로 분류 할 수 있다.

그리고 ELK스택을 활용하여 검색엔진보다 더 큰 검색시스템을 구성 할수 있다.

검색 서비스(ex:google, naver ) > 검색 시스템(ex: ELK스택) > 검색엔진(ex: 엘라스틱 서치)

1-3. 검색 시스템의 구성 요소

이번에는 검색시스템의 구성요소를 통해 엘라스틱서치를 알아보자.

검색 시스템의 기본 구조는 개발사에 따라 서로 조금씩 다르지만 기본 구조는 같다.

일반적으로 정보를 수집하는 수집기, 수집한 데이터를 저장하는 스토리지, 수집한 데이터를 검색에 적절한 형태로 변환하는 색인기, 색인된 데이터에서 일치하는 문서를 찾는 검색기로 구성된다.

수집기

수집기는 웹사이트, 블로그, 카페 등 웹에서 필요한 정보를 수집하는 프로그램이다.

크롤러(Crawler), 스파이더(Spider), 웜(Worms), 웹 로봇(Web Robot) 등으로도 불린다.

파일, 데이터베이스, 웹페이지 등 웹상의 대부분의 정보가 수집대상이다.

파일의 경우 수집기가 파일명, 파일 내용, 파일 경로 등의 정보를 수집하고 저장하면 검색엔진이 저장된 정보를 검색하고, 사용자 질의에 답한다.

스토리지

데이터베이스에서 데이터를 저장하는 물리적인 저장소다. 검색엔진은 색인한 데이터를 스토리지에 보관한다.

색인기

검색엔진이 수집한 정보에서 사용자 질의와 일치하는 정보를 찾으려면 수집된 데이터를 검색 가능한 구조로 가공하고 저장해야 한다.

그 역할을 하는 것이 색인기다.

색인기는 다양한 형태로 분석을 조합해 정보에서 의미가 있는 용어를 추출하고 검색에 유리한 역색인 구조로 데이터를 저장한다.

검색기

검색기는 사용자 질의를 입력받아 색인기에서 저장한 역색인 구조에서 일치하는 문서를 찾아 결과로 반환한다.

질의와 문서가 일치하는지 유사도 기반의 검색 순위 알고리즘으로 판단한다.

검색기 또한 색인기와 마찬가지로 현태로 분석기를 이용해 사용자 질의에서 유의미한 용어를 추출해 검색한다.

따라서 사용하는 형태로 분석기에 따라 검색 품질이 달라진다.

Hello%20ElasticSearch/1.png

엘라스틱서치는 위 검색시스템 구성요소 중 색인기, 스토리지, 검색기를 포함하고 있다.

1-4. 관계형 데이터베이스와 엘라스틱서치의 차이점

검색엔진을 설명할 때 항상 비교되는 것이 관계형 데이터베이스(RDMBS)다.

두 가지 모두 질의와 일치하는 데이터를 찾아 사용자에게 제공한다는 점에서 유사점이 많이 때문이다.

하지만 관계형 데이터베이스로 검색 기능을 제공하는 데는 많은 문제점이 있다.

관계형 데이터베이스의 어떠한 한계 때문에 검색엔진이 등장하게 됐는지, 그리고 이 둘은 어떤 점에서 차이점이 있는지 살펴보자.

데이터베이스는 데이터를 통합 관리하는 데이터의 집합이다. 저장방식에 따라 크게 관계형 또는 계층형 데이터베이스로 나뉜다.

모든 데이터는 중복을 제거하고 정형 데이터로 구조화해 행과 열로 구성된 테이블에 저장된다.

SQL문을 이용해 원하는 정보의 검색이 가능한데 텍스트 매칭을 통한 단순한 검색만 가능하다.

텍스트를 여러 단어로 변형하거나 여러 개의 동의어나 유의어를 활용한 검색은 불가능하다.

반면 검색엔진은 데이터베이스에서 불가능한 비정형 데이터를 색인하고 검색할 수 있다.

형태소 분석을 통해 사람이 구사하는 자연어의 처리가 가능해지고 역색인 구조를 바탕으로 빠른 검색 속도를 보장한다.

엘라스틱서치와 관계평 데이터베이스 비교

엘라스틱서치 관계형 데이터베이스
인덱스(Index) 데이터베이스(Database)
샤드(Shard 파티션(Partition)
타입(Type) 테이블(Table)
문서(Document) 행(Row)
필드(Field) 열(Column)
매핑(Mapping) 스키마(Schema)
Query DSL SQL

위 표는 검색엔진의 대표 자자격인 엘라스틱서치와 관계형 데이터베이스의 주요 개념을 비교해 보여준다.

엘라스틱서치의 인덱스는 관계형 데이터베이스의 데이터베이스와 비슷한 문서의 모음을 뜻한다.

엘라스틱서치의 타입은 데이터베이스의 테이블과 같은 역을 한다.

6.0 이하 버전에서는 하나의 인덱스 내부에 기능에 따라 데이터를 분류하고 여러 개의 타입을 만들어 사용했지만 현재(7버전)는 하나의 인덱스에 하나의 타입만을 구성하도록 바뀌었다.

엘라스틱서치는 하나의 행을 문서라고 부르며, 해당 문서는 데이터베이스 테이블의 한 행을 의미한다.

또한 엘라스틱서치의 매핑은 필드의 구조와 제약조건에 대한 명세를 말하며 이에 대응하는 관계형 데이터베이스의 개념을 스키마라 한다.

관계형 데이터베이스와 엘라스틱서치는 인덱스라는 개념을 다르게 사용한다.

엘라스틱서치의 인덱스는 Database, 앞에 설명했지만 관계형 데이터베이스에서의 인데스는 WHERE 절의 쿼리와 JOIN을 빠르게 만드는 보조 데이터 도구로 사용된다.

엘라스틱서치와 데이터베이스는 데이터의 추가, 수정, 삭제 방식에도 차이가 있다.

엘라스틱서치는 기본적으로 HTTP를 통해 JSON 형식의 RESTful API를 이용한다.

엘라스틱서치는 자바로 개발 됐지만 여러 가지 프로그래밍 언어를 통해 사용할 수도 있다.

Copy of 추가, 검색, 삭제, 수정 기능 비교

엘라스틱서치에서 사용하는 HTTP 메소드 기능 데이터베이스 질의 문법
GET 데이터조회 SELECT
PUT 데이터생성 INSERT
POST 인덱스 업데이트, 데이터조회 UPDATE, SELECT
DELETE 데이터삭제 DELETE
HEAD 인덱스정보확인 -

1-5. 엘라스틱서치의 특징

요즘에는 대량의 데이터를 빠르게 검색하기 위해 NoSQL(No Structured Query Language)를 많이 사용한다.

엘라스틱서치 NoSQL의 일종으로서 분류가 가능하고 부산 처리를 통해 실시간에 준하는 빠른 검색이 가능하다.

기존 데이터베이스로는 처리하기 어려운 대량의 비정형 데이터도 검색할 수 있으며, 전문검색(Full Text)과 구조 검색 모두를 지원한다.

기본적으로는 검색엔진이지만 MongoDB나 Hbase처럼 대용량 스토리지로도 활용할 수 있다.

1-5-1. 엘라스틱서치의 강점

오픈소스 검색엔진

엘라스틱서치는 아파치 재단의 루씬(Lucene)을 기반으로 개발된 오픈소스 검색엔진이다.

따라서 전 세계에서 수많은 사람들이 사용하고 있으며, 버그가 발생할 경우에도 대부분 빠르게 해결된다.

현재 약 2억 5천만 번 이상 다운로드됐는데, 이 수치만 보더라도 얼마나 많은 사람들이 사용하고 있는지 알 수 있다.

다운로드가 많이 일어난다는 것은 프로젝트가 많이 활성화돼 있다는 것을 의미한다.

전문검색

PostgreSQL, MongoDB 같은 대부분의 데이터베이스는 기본 쿼리 및 색인 구조의 한계로 인해 기본적인 텍스트 검색 기능만 제공한다.

하지만 엘라스틱서치는 좀 더 고차원적인 전문검색(Full Text)이 가능하다.

전문검색이란 내용 전체를 색인해서 특정 단어가 포함된 문서를 검색하는 것을 말한다.

기존 관계형 데이터베이스는 전문 검색에 적합하지 않지만 엘라스틱서치는 다양한 기능별, 언어별 플러그인을 조합해 빠르게 검색할 수 있다.

통계분석

비정형 로그 데이터를 수집하고 한곳에 모아 통계 분석을 할 수 있다.

엘라스틱서치와 키바나(Kibana)를 연결하면 실시간으로 쌓이는 로그를 시각화하고 분석할 수 있다.

스키마리스(Schemaless)

데이터베이스는 스키마라는 구조에 따라 데이터를 적합한 형태로 변경해서 저장하고 관리한다.

반면 엘라스틱서치는 정형화되지 않은 다양한 형태의 문서도 자동으로 색인하고 검색할 수 있다.

RESTful API

엘라스틱서치는 HTTP 기반의 RESTful API를 지원하고 요청뿐 아니라 응답에도 JSON 형식을 사용해 개발 언어, 운영체제, 시스템에 관계없이 이기종 플랫폼에서도 이용 가능하다.

멀티테넌시(Multi-tenancy)

서로 상이한 인덱스일지라도 검색할 필드명만 같으면 여러 개의 인덱스를 한번에 조회할 수 있다.

이를 이용해 멀티테넌시 기능을 제공할 수 있다.

Document-Oriented

여러 계층의 데이터를 JSON 형식의 구조화된 문서로 인덱스에 저장할 수 있다.

계층 구조로 문서도 한번의 쿼리로 쉽게 조회할 수 있다.

역색인(Inverted Index)

앞서 언급했듯이 엘라스틱서치는 루씬 기반의 검색엔진이다. 따라서 엘라스틱서치 또한 역색인을 지원한다.

반면 MongoDB, 카산드라(Cassandra)같은 일반적인 NoSQL은 역색인을 지원하지 않는다.

이는 다른 NoSQL 대비 엘라스틱서치의 매우 큰 장점이라 할 수 있다.

Hello%20ElasticSearch/KakaoTalk_20191204_215703353.png

색인:책의 목차와 같다.

Hello%20ElasticSearch/KakaoTalk_20191204_215708663.png

역색인:책의 뒷부분에 중요한 키워드로 페이지를 찾을수 있다.

확장성과 가용성

10억 개의 문서를 색인한다고 가정해보자. 모든 문서를 색인하는 데 막대한 비용과 시간이 드는 것은 불보듯 뻔하나.

하지만 엘라스틱서치를 분산 구성해서 확장한다면 대량의 문서를 좀 더 효율적으로 처리할 수 있다.

분산 환경에서 데이터는 샤드(Shard)라는 작은 단위로 나뉘어 제공되며, 인덱스를 만들 때마다 샤드의 수를 조절할 수 있다.

이를 통해 데이터의 종류와 성격에 따라 데이터를 분선해서 빠르게 처리할 수 있다.

1-5-2. 엘라스틱서치의 약점

마법주문처럼 보이는 엘라스틱서치도 약점이 있다.

첫째, 실시간이 아니다. 일반적으로 색인된 데이터는 통상적으로 1초 뒤에나 검색이 가능해진다.

색인된 데이터는 내부적으로 커밋(Commit)과 플러쉬(Flush)같은 복잡한 과정을 거치기 때문에 실시간이 아니다.

엄밀히 따지자면 준 실시간(Near Realtime)이라고 할 수 있다.

둘째, 트랜잭션과 롤백 기능을 제공하지 않는다. 엘라스틱서치는 기본적으로 분산 시스템으로 구성된다. 전체적인 클러스터의 성능 향상을 위해 시스템적 비용 소모가 큰 롤백(Rollback)과 트랜젝션(Transaction)을 지원하지 않기 때문에 최악의 경우 데이터 손실의 위험이 있다.

셋째, 데이터의 업데이트를 제공하지 않는다. 엄밀히 말하자면 엘라스틱서치는 업데이트 명령이 요청될 경우 기존 문서를 삭제하고 변경된 내용으로 새로운 문서를 생성하는 방식을 사용한다.

이러한 이유로 단순 업데이트에 비해서는 상대적으로 많은 비용이 발생한다.

하지만 이것은 큰 단점은 아니다. 이를 통해 불변적(Immutable)이라는 이점을 취할 수 있기 때문이다.

1-6.엘라스틱서치 사용사례

  • 위키피디아(Wikipedia)는 엘라스틱서치를 이용해 전문검색(Full Text Search)를 수행하고 실시간 타이핑 검색, 추천검색어 기능등에 활용 중이다.
  • 더 가디언(The Guardian)지는 방문객의 로그 분석을 통한 소셜 데이터를 생성해 실시간 응대와 기사에 대한 반응 분석등에 엘라스틱서치를 사용하고 있다.
  • 스택오버플로어(StackOverflow)에서는 검색 내용과 결과를 통합해 유사한 질문과 해답을 연결하는 데 엘라스틱서치를 활용하고 있다.
  • 깃허브(Github)에서는 1,300억 줄이 넘는 소스코드를 검색하는 데 엘라스틱서치를 사용중이다.
  • 골드만 삭스(Goldman Sachs)에서는 매일 5TB가 넘는 데이터를 저장하고 있으며, 엘라스틱서치를 이용해 이 데이터를 주식 시장의 변동을 분석하는데 사용한다.

2.엘라스틱서치 검색원리(분석과 역색인)

엘라스틱서치에서 입력된 데이터를 통해 검색어를 추출하기 위한 프로세스를 거치는데 이 과정을 분석(Analysis)이라고 한다.

이때 분석 과정에서 사용하는 프로그램을 분석기-애널라이저(Analyzer)라고 하며 분석기는 하나의 토크나이저(Tokenizer)와 0개 또는 1개 이상의 토큰필터(Token Filter)로 구성돼 있다.

토크나이저는 입력 데이터를 토크나이저에 설정된 기준에 따라 검색어 토큰으로 분리하는 작업을 한다.

토큰 필터는 토크나이저로 분리된 토큰들에 다시 필터를 적용해서 실제로 검색에 쓰이는 검색어들로 최종 변환하는 작업을 한다.

엘라스틱 서치에서는 내부적으로 다양한 분석기를 가지고 있으며, 자신만의 분석기를 생성해서 적용할 수도 있다.

2-1. 분석과정

엘라스틱서치에서 데이터를 색인할 때 문사가 분석되는 가정을 한번 살펴보자.

데이터는 색인될 때 인덱스에 설정된 분석기의 종류에 따라 토크나이저 → 토큰필터 순으로 분석과정을 거친다.

예제로 문자열 “Around the World in Eighty Days”에 whitespace 토크나이저와 lowercase그리고 stop 토큰필터를 적용시켜 가면서 분석 과정을 차례대로 확인해보자.

먼저 이 문자열에 whitespace 토크나이저를 적용시켜서 분석을 진행하면 문자열이 다음과 같이 분리된다.

Hello%20ElasticSearch/1-Page-2_(1).png

whitespace 토크나이저는 공백 또는 줄바꿈을 기준으로 단어를 불리하는 토크나이저다.

위에서 처럼 withespace토크나이저를 거친 문자열 “Around the Wrold in Eighty Days”는 각 Around, the, World, in, Eighty, Days라는 검색어 토큰으로 색인된다.

이제 이 검색어 토큰에 lowercase 토큰필터를 적용하면 각 검색어 토큰은 다음과 같이 변경된다.

Hello%20ElasticSearch/1-Page-3.png

lowercase 토큰필터를 거친 검색어 토큰은 모두 소문자로변환된다. lowercase 토큰필터를 거친 검색어 토큰에 마지막으로 stop 토큰필터를 한번 더 적용하면 검색어 토큰은 다음과 같이 된다.

Hello%20ElasticSearch/1-Page-4_(1).png

stop 토큰필터는 검색어 토큰 중 불용어(stopwords)에 해당하는 토큰을 검색어 토큰 목록에서 제외시키는 역할을 한다.

일반적으로 영어 단어 중 the, end, is와 같이 거의 대부분의 문장에 빠지지 않고 들어있는 대명사 또는 전치사 등의 단어를 실제로 검색어로 사용하기에는 문제가 있기 때문에 이러한 단어는 불용어에 해당된다.

위 내용을 실제 엘라스틱서치에 _analyze API를 통해 확인해 볼 수 있다.

아래는 whitespace 토크나이저만 적용하여 “Around the Wrold in Eighty Days” 텍스트의 분석을 요청하는 화면이다.

Hello%20ElasticSearch/Untitled.png

Hello%20ElasticSearch/Untitled%201.png

위처럼 공백 단위로 잘려진 토큰을 확인 할 수 있다.

filter로 lowercase를 적용한 결과 아래처럼 분석된 토큰들이 소문자로 변환된 것을 확인 할 수 있다.

Hello%20ElasticSearch/Untitled%202.png

Hello%20ElasticSearch/Untitled%203.png

이제 여기서 추가로 stop 토큰필터를 적용해보자.

Hello%20ElasticSearch/Untitled%204.png

Hello%20ElasticSearch/Untitled%205.png

the, in 이 삭제된 것을 확인할 수 있다.

분석기(Analyzer)는 데이터의 분석에 사용할 토크나이저와 토큰 필터를 저장하고 있는 일종의 배치 프로그램으로 이해할 수 있다.

엘라스틱서치에서 기본적으로 제공하는 분석기 역시 모두 토크나이저와 토큰필터를 가지고 있으며, 이 외에 추가로 사용자가 임의의 토크나이저와 토큰필터를 선택해서 사용자 정의 분석기를 생성할 수 있다.

사용자 정의 분석기는 인덱스 단위로저장되며 해당 인덱스에 데이터 색인할 때 분석기를 명시해서 사용할 수 있다.

다음은 실제 인덱스를 생성하면서 분석기를 설정하는 화면이다.

Hello%20ElasticSearch/Untitled%206.png

inca_index라는 인덱스를 생성하며 settings에 분석기를 설정했다.

아래는 맵핑정보로서 RDB의 테이블 정의라고 생각하면 된다. title이라는 프로퍼티에 위에서 생성한 my_analyzer를 설정했다.

인덱스를 생성한뒤 해당 인덱스에 아래처럼 데이터를 입력하게 되면, title이라는 프로퍼티는 자동으로 index생성시 설정한 my_analyzer를 통해 역색인 과정을 거쳐 해당 역색인 데이터를 엘라스틱서치 내부에 따로 저장하게 된다.

Hello%20ElasticSearch/Untitled%207.png

Hello%20ElasticSearch/1-Page-5.png

3.엘라스틱 서치의 활용예시

3-1. ELK 스택

엘라스틱서치는 뛰어난 검색엔진이지만 실무에서 사용하려면 입력할 데이터를 JSON형태로 가공 해야 하고, 검색된 데이터를 시각화하려면 별도의 차트 프로그램이나 라이브러리를 사용해야 하는등 부가적인 작업을 거쳐야 한다.

이를 위해 엘라스틱서치에서는 데이터 입력을 다양한 방식으로 간편하게 할 수 있는 프로그램인 로그스태시(Logstash)와 검색 데이터를 편리하게 시각화할 수 있는 도구인 키바나(Kibana)를 홈페이지에서 함께 제공하고 있다.

엘라스틱서치(Elasticsearch), 로그스테이시(Logstash), 키바나(Kibana)를 연동해서 구성한 시스템을 ELK 스택(ELK Stack)이라 한다.

Hello%20ElasticSearch/Untitled%208.png

ELK 스택와 더불어 ELK 스택에 경량 데이터수집 플랫폼인 Beats를 통해 다양한 환경에서 다양한 데이터를 수집, 가공, 저장, 시각화 하는 구조를 구성할 수 있다.

Hello%20ElasticSearch/beats-platform.png

3-2. 한글 형태소 분석기

엘라스틱서치에서는 여러종류의 분석기와 토크나이저, 토큰필터를 내장하고 있다.

하지만 영어가 아닌 우리말(한글)로 된 문장을 분석하려면 내장된 분석기로 만족할 만한 결과를 얻기가 쉽지 않다.

예를 들어 “동해물과 백두산이 마르고 닳도록”과 같은 문장을 분석하면 보통은 “동해물과”, “백두산이”와 같이 공백 정도로만 토큰을 구분하거나 CJK 알고리즘을 사용한 경우에도 “동해”, “해물”과 같이 2음절의 토큰을 생성하는 정도로만 분석된다.

이 문장에서 “동해”, “백두산” 같은 검색어 토큰을 분석하려면 한글을 의미로 해석해서 분리할 수 있는 별도의 한글 형태소 분석기가 필요하다.

엘라스틱서치나 아파치 루씬에서는 한글을 위한 별도의 분석기 또는 사전을 제공하지 않고 있다.

하지만 정확한 한글 분석을 위해 국내 개발자들에 의해 별도로 개발되어 있는 한글 형태소 분석기들이 있다.

잘 알려진 분석기로는 아리랑 한글 분석기 프로젝트, 은전한잎 한글 분석기 프로젝트 등이 있으며 대부분 오픈소스로 개발되고 있으므로 해당 프로젝트 페이지에서 소스코드와 다양한 정보를 구할 수 있다.

Hello%20ElasticSearch/Untitled%209.png

참고자료

시작하세요! 엘라스틱서치(책)

엘라스틱서치 실무 가이드(책)

hexo는 jekyll과 같은 정적 블로그 생성 프레임 워크이다.

다만 hexo는 루비가 아닌 javascript, node등을 기반으로한 정적 블로그 생성기이다.

hexo도 markdown으로 글을 작성하며, github page와 연동해서 로컬에서 생성한 hexo 블로그를 웹에 공개 할수도 있다.

hexo의 자세한 설명은 아래 공식 페이지에서 확인 할 수 있다.

Hexo

Hexo 블로그를 만들기 전에, 로컬에 미리 node가 설치 되어 있어야 한다.

설치가 되어있지 않다면, 구글링해서 설치하길 바란다.

/images/Hexo20191219/Untitled.png

블로그를 생성한 경로로 이동해서 터미널을 열고 아래 명령어를 순차적으로 입력하면된다.

npm install hexo-cli -g    #hexo cli를 글로벌로 설치
hexo init hexoblog         #hexoblog라는 폴더로 hexo 블로그 생성     
cd blog                    #생성된 폴더로 진입
npm install                #의존성 설치
hexo server                #hexo 블로그 기동

아래 hexo init명령으로 hexoblog라는 hexo blog 폴더를 생성한다.

요즘에는 자동으로 기본 디펜던시를 다운로드 해주는것 같다.

/images/Hexo20191219/Untitled%201.png

아래처럼 폴더가 생성 된다.

/images/Hexo20191219/Untitled%202.png

/images/Hexo20191219/Untitled%203.png

위 이미지에서 hexo-deployer-git 을 추가로 설치했다.

해당 모듈은 나중에 gitpage에 hexo로 빌드한 정적 웹을 배포하는 용도의 모듈이다.

마지막으로 hexo s 또는 hexo server 를 입력하면 hexo가 동작중이라는 문구와 url 이 나온다.

/images/Hexo20191219/Untitled%204.png

브라우저로 hexo 블로그가 동작하는 것을 확인 할 수 있다.

아래 블로그의 테마는 hexo의 기본 테마인 landscape 테마이다.

다음글에서는 이 테마를 Next 테마로 변경하는 내용을 다뤄 보도록 하겠다.

/images/Hexo20191219/Untitled%205.png

windows에서 create-react-app으로 예제 프로젝트를 준비했다.

https://reactstrap.github.io/

react에서 bootstrap을 컴포넌트를 제공하는 라이브러리가 있다. reactstrap이라는 라이브러리이다.

설치하자. 이 라이브러리에 있는 모달을 사용할 예정이다.

npm install --save reactstrap react react-dom

https://www.npmjs.com/package/react-draggable

react에서 마우스 드래그 기능을 제공하는 라이브러리이다 설치하자.

해당 라이브러리는 modal에만 해당하는것이 아니라 감싼 컴포넌트 모두를 지원한다.

npm install react-draggable

ModalExample.js 라는 파일을 만들자. 이 파일이 마우스 드래그가 가능한 모달 컴포넌트이다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
    import React from 'react';
import { Button, Modal, ModalHeader, ModalBody, ModalFooter } from 'reactstrap';
import Draggable from 'react-draggable';

class ModalExample extends React.Component {
constructor(props) {
super(props);
this.state = {
modal: false
};

this.toggle = this.toggle.bind(this);
}

toggle() {
this.setState(prevState => ({
modal: !prevState.modal
}));
}

render() {
return (
<div>
<Button color="danger" onClick={this.toggle}>{this.props.buttonLabel}</Button>
<Draggable
axis="both"
handle=".handle"
defaultPosition={{x: 0, y: 0}}
position={null}
grid={[25, 25]}
scale={1}
onStart={this.handleStart}
onDrag={this.handleDrag}
onStop={this.handleStop}>
<Modal isOpen={this.state.modal} toggle={this.toggle} className={this.props.className}>
<ModalHeader toggle={this.toggle} className="handle">Modal title</ModalHeader>
<ModalBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</ModalBody>
<ModalFooter>
<Button color="primary" onClick={this.toggle}>Do Something</Button>{' '}
<Button color="secondary" onClick={this.toggle}>Cancel</Button>
</ModalFooter>
</Modal>
</Draggable>
</div>
);
}
}

export default ModalExample;

App.js

import React from 'react';
import './App.css';

import ModalExample from './ModalExample';

function App() {
return (
<div className="App">
<ModalExample buttonLabel={"모달 테스트"}></ModalExample>
</div>
);
}

export default App;

npm run start 로 실행해보자.

모달창을 열고 모달의 제목을 마우스로 드래그 하면 드래그가 가능한 것을 확인 할 수 있다.

현재 드래그가 좀 버벅이는 것 처럼 보이는데, 그것은 react-draggable의 옵션으로 부드러움 정도를 설정 할수 있다.

해당 예제는 아래 github에 올려놓았다.

https://github.com/hanumoka/react-modal-draggable.git

들어가기

이번은 로컬에 docker로 올린 jenkins를 사용해서 Gitlab(online)에 연동하는 방법을 알아보겠다.

실습전 준비

위 처럼 gitlab에 테스트할 리파지토리를 하나 준비했다.

위처럼 젠킨스에서는 Git plugin, GitLab Plugin을 설치해주자.

Git plugin은 기본적으로 설치되어 있지만, GitLab Plugin은 추가로 설치해 주어야 할 것이다.

Git, GitLab관련 다양한 기능을 제공하는 플러그인들이 추가로 있으니, 필요기능별로 찾아 사용하면 된다.

실습

구글링 해보면, Gitlab에 accesstoken을 사용해서 jenkins와 연동하는 예제는 많이 있다.

하지만 내가 셋팅한 jenkins에 뭔가 문제가 있는지, Gitlab accesstoken을 저장까지는 되지만 막상 Project에서 Gitlab accesstoken credential을 불러오지 못했다.

따라서 차선책으로 Gitlab의 accesstoken대신 Gitlab의 계정을 사용하여, jenkins에 연동을 해볼것이다.

jenkins에 github 계정 Credential 추가하기

jenkins에서 Credentilas로 이동 → global 클릭

Add Credentials클릭

이 화면에서 Credential을 저장하고 젠킨스의 project에서 필요한 Credential을 불러와서 사용한다.

Username에 gitlab 계정아이디(필수 값)

Password에 gitlba 계정비밀번호(필수 값)

ID에는 Credential을 식별하는 아이디(필수 값)

Description은 이 Credential에 대한 설명을 입력하자.

Credential저장이 완료되었다면, 이제 새로운 Item을 생성하자.

아이템 이름을 입력하고, Freestyle project 를 선택하고 OK 를 클릭하자.

GitLab의 특정 프로젝트로 가서 리파지토리 URL을 클립보드로 복사하자.

다시 jenkins로 이동해서

앞서 생성한 Item의 소스코드 관리로 이동후 Git 선택.

그리고 Repository URL에 앞서 복사한 Gitlab 프로젝트 URL을 붙여넣자.

처음에는 Credential이 none이므로 아래처럼 빨란 경고문그로 접근할수 없다고 나온다.

Credentials 셀렉트박스를 눌러서 앞서 입력한, Credential을 선택하자.

아래 그림에서는 내가 테스트로 여러개를 입력해서 여러개가 나오는 것 뿐이다.

선택한 뒤 조금 지나면, 아래처럼 빨간 문구가 사라진 것을 확인 할 수 있다. 이것으로 연동이 된 것이다.

실제 연동이 됬는지 확인하기 위해 item에 build로 가서 Execute shell을 클릭한뒤 ls -al 명령어를 입력하자.

아래처럼 ls -al을 입력해서 gitlab 리파지토리에서 소스를 받아오는지 출력해보자.

저장을 눌러서 jenkins item을 저장하자.

아래처럼 저장이 완료 되었다.

Build Now를 눌러서 Jenkins item을 동작 시키자.

아래처럼 Build History가 성공적으로 끝났다.

#1을 클릭해서 내용을 확인해 보자.

아래처럼 gitlab의 소스를 받아오는 것을 확인 할 수 있다.

끝!!!