0%

가상머신을 생성하고 기초적인 설정하기

우선 oracle vm virtualBox를 열고 새로운 가상머신을 추가하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled.png

원하는 가상머신 이름과 머신을 저장할 폴더를 지정하자.

그리고 종류는 Linux, 버전은 RedHat(64-bit)로 설정한 다음에 다음을 눌러주자.(이름이 centos인 경우 종류와 버전은 oracle vm virtualbox에서 자동으로 지정해준다.)

다음은 가상머신의 메모리를 지정하는 부분이다. 난 2048로 지정했다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%201.png

다음은 가상머신의 하드디스크 설정인데, 기본을 설정된 지금 새 가상 하드 디스클 만들기로 두고 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%202.png

다음도 기본으로 설정된 VDI를 설정한 뒤 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%203.png

다음화면에서는 동적할당을 고정크기로 변경 했다. 가상머신은 워낙 느리기 때문에 디스크 용량이 넉넉하다면 고정크기가 좋은듯하다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%204.png

디스크 용량을 20GB로 지정했다. 난 centos 그놈 데스크탑 버전으로 설치할 거라서 좀 넉넉하게 잡았다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%205.png

만들기 버튼을 누르면, oracle vm virtualbox가 앞서 설정한대로 가상머신을 만든다.

시간이 좀 걸리니 커피나 한잔 때리고 오면 된다. SSD는 좀 빠를 줄 알았는데, 시간이 꽤나 걸린다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%206.png

아래처럼 가상머신이 생성되면, 가상머신을 마우스 우클릭한 뒤 설정에 들어간다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%207.png

가상머신 설정 - 일반 - 고급에서 클립보드 공유와 드래그 앤 드롭을 양방향으로 만들어준다.

사실 터미널만 사용하면 별 쓸일이 없긴하지만, 데스크탑 버전 리눅스에서 혹시나 쓸수도 있다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%208.png

가상머신 설정 - 시스템 - 마더보드에서 부팅순서에 플로피 디스크에 체크박스를 해제한다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%209.png

가상머신 설정 - 시스템 - 프로세서에서 프로세서 개수를 2개로 늘려주었다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2010.png

가상머신 설정 - 디스플레이 - 화면에서 비디오메모리를 최대치로 설정하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2011.png

가상머신 설정 - 오디오에서 오디오 사용하기 체크박스를 해제한다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2012.png

가상머신 설정 - 네트워크에 - 어뎁터 1 탭에서 다음에 연결됨 이라는 항목을 어뎁터에 브리지로 지정한다.

이렇게 지정하면 해당 가상머신은 현재 호스트 PC인 windows10의 공유기에서 자동으로 IP를 할당 받게 된다. 즉 호스트 PC와 동일한 네트워크를 사용하게 된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2013.png

확인을 눌러서 설정을 저장하자.

이제 centos7.7 ISO파일을 이용해서 해당 가상머신에 centos를 설치해보자ㅏ.

가상머신에 centOS 설치하기

https://mirrors.oit.uci.edu/centos/

centos ISO 파일은 위 사이트에서 구할 수 있다. 원하는 버전을 다운 받으면 된다.

나는 centos7.7 Everything.iso 파일을 다운 받았다. 참고로 토렌트가 속도가 조금더 빠른 느낌이다.

앞서 생성한 가상머신을 선택하고 시작 버튼을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2014.png

가상머신 실행시 OS 설치되지 않은 상태에서 OS 설치파일이 가상머신에 등록되지 않은 경우 아래처럼 창이 뜬다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2015.png

파일 탐색기를 열어서, 다운받은 centos ISO 파일을 선택하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2016.png

그리고 시작 버튼을 누르면 해당 설치파일이 동작하게 된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2017.png

아래처럼 뜨면 Install Centos7을 선택하자. 가상머신창을 마우스로 클릭하고 키보드로 제어하면 된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2018.png

뭔가 한참 진행이 되다가 아래처럼 언어 선택창이 나온다. 한국어를 선택하고 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2019.png

다음 화면에서는 centos 설치전 설정이 나오는데, 자세히 보면 언어지원의 경우 진한 검정색이지만, 다른 설정들은 옅은 회색인 것을 확인 할 수 있다.

옅은 회색인 경우 설정이 안됨을 표시한다. 먼저 날짜&시간을 선택하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2020.png

다음과 같이 나오는데, 보통 디폴트로 서울이 선택 되어 있다. 완료버트을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2021.png

아래처럼 날짜&시간이 검정색으로 변한것을 확인 할 수 있다.

다음은 키보드를 선택하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2022.png

키보드 역시 기본으로 한국어로 설정 되어 있다. 완료 버튼을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2023.png

그 다음에 설치 대상을 클릭하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2024.png

앞서 가상머신을 생성할때 지정하나 고정 드라이브 20GB가 나온다. 해당 디스크에 체크를 확인하고 완료 버튼을 눌러주자(체크 표시가 없다면, 마우스로 클릭해서 체크해주자.)

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2025.png

아래처럼 노란색 느낌표가 사라진다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2026.png

그 다음에 소프트웨어선택에 들어가서 최소설치로 되어 있던 설정을 GNOME 데스크탑으로 변경한다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2027.png

그 다음에 네트워크 & 호스트 이름에 들어가서 이더넷을 켬으로 바꿔주자.

아래처럼 공유기로부터 자동으로 이더넷설정을 받아온다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2028.png

이제 설치시작을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2029.png

다음 화면처럼 설치가 진행다.

Root암호 설정과, 사용자 생성 메세지가 나온다.

ROOT암호를 눌러서 root 계정의 암호를 설정하자.

사용자 생성은 지금 안하고, 나중에 centos 설치가 완료되고 할 것이다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2030.png

Root암호를 누르면 아래처럼 창이 나오고 root암호를 입력하면 된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2031.png

아래처럼 root계정의 암호를 설정했다. centos 다 설치되고 리부트가 될때까지 기다려 주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2032.png

설치가 완료되면 다음처럼 완료되었다고 나온다. 재부팅을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2033.png

가상머신이 리부팅되면서 다음처럼 화면이 나온다. CentOs Linux를 선택하면, 설치한 Centos 가 실행된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2034.png

아래처럼 화면이 나오는데, 뭔가 라이센스 동의를 원하는것 같다. 클릭한 뒤 동의해주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2035.png

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2036.png

설정 완료를 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2037.png

다음과 같이 환영창이 나오면서 다시 한번 언어를 물어본다. 한국어를 그대로 두고 다음으로 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2038.png

다시 한번 키보드입력 방식을 물어보는데 기본으로 두고 다음으로 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2039.png

위치 정보를 쓰겠다고 하는데, 그냥 쓰라고 하고 다음

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2040.png

시간대 역시 또 물어본다. 다음

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2041.png

온라인 계정 연결을 물어보는데, 테스트 용도니 필요없다 건너뛰기

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2042.png

이제 로그인하여 사용할 사용자 계정을 입력하라고 한다.(아까 초기에 설치시 생성하지 않아서 지금 생성하라고 나온것 같다. 사실 난 사용자 계정은 필수 생성할 필요가 없을줄 알았는데 centos7에서 기본적으로 로그인 사용자생성을 강요하는것 같다.)

전체이름에 원하는 사용자 id를 입력하자

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2043.png

전체이름을 입력하면, 자동으로 사용자 이름이 따라 생성된다. 다음으로 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2044.png

생성한 사용자의 암호를 입력하고 다음으로 넘어가자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2045.png

휴 모든 설정이 끝났다. centos linux시작을 눌러주면 된다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2046.png

마지막으로 이렇게 centos 그놈 데스크탑이 열린다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2047.png

끝!

버추얼 박스 팁

단축키로 버추얼 박스의 마우스점유를 호스트 PC로 가져오기

호스트 PC에서 버추얼 박스내부를 제어하기 위해서는 마우스의 점유를 버추얼박스 내부의 가상머신에게 위임하게 되다. 버추얼박스를 사용하다가 다시 호스트 PC를 제어하기 위해서는 가상머신 내부에 같혀 있는 마우스의 점유권한을 호스트PC로 이동 시켜야 하는데 이때 ctrl + alt + delete로 빠져나가는 방법이 있다. 하지만 이 방법보다는 아래처럼 버추얼박스에서 입력 - 키보드 - 키보드 설정 메뉴에서 단축키를 지정해서 사용하는 것이 편하다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2048.png

아래처럼 가상머신 탭에서 호스크티 조합의 단축키를 Shift + Ctrl로 변경 하면, 편하게 가상머신의 마우스 점유를 호스트PC로 가져올 수 있다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2049.png

게스트 확장 CD 이미지 삽입

게스트 확장이란 가상머신에 설치된 OS에 가상머신사용시 편리한 부가기능등을 설치하는 것이다.
클립보드, 폴더공유, 자동 해상도 맞춤 등 자잘하게 편리한 기능등이 있다.

centos를 설치한 뒤, 가상머신에서 장치 - 게스트 확장 CD 이미지 삽입을 누른다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2050.png

아래처럼 실행을 눌러주자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2051.png

앞서 생성산 사용자 로그인 정보를 입력해서 인증하라고 나오는데, 비밀번호를 입력하고 인증하자.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2052.png

다음처럼 설치가 된다. ubuntu 데스크탑 경우 게스트학장 기능을 설치하면 버추얼 박스에서 자동으로 해상도를 잡아주는데 centos7에서는 그런 기능은 없는 듯하다.

virtual%20box%20centos7%207%207b6baf1bf9194edc8144beaf32dd7405/Untitled%2053.png

끝!!!

참고자료

https://extrememanual.net/8513

https://wnw1005.tistory.com/21

들어가기

springboot 프로젝트에 thymeleaf-layout-dialectt이라는 라이브러리를 사용해서 thymeleaf 템플릿 엔진에 레이아웃을 적용해 보겠다.

보통 웹 페이지를 만들면 화면을 header, contents, footer 등으로 나누고 header와 footer는 고정한 뒤 contents 영역만 바꿔가면서 렌더링을 해야 한다.

thymeleaf-layout-dialect 라이브러리가 thymeleaf에서 이런 레이아웃을 가능하게 도와준다.

주의

실습 마지막 부분에, 오래된 문법 교체작업이 있다.

실습환경

  • windows10
  • intellij comunity
  • jdk1.8 (2020-05-21 기준으로 jdk 1.8을 추천한다.)
  • thymeleaf-layout-dialect 2.4.1
  • springboot 2.3.0
  • gradle

목표

아래처럼 header, footer는 고정하고, page url에 따라서 contents 영역만 바뀌게 하는 것이 목표이다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled.png

실습

springboot 프로젝트 만들기

아래 spring initializr 페이지로 이동해서 springboot 프로젝트를 만들어보자.

https://start.spring.io/index.html

디펜던시에 Spring Web, Thymeleaf 두개를 추가해주자.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%201.png

일단 thymeleaf 가 잘 동작하는지 확인해 보기 위해서, HomeContoller를 추가하자.

HomeController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package hanumoka.example.springbootthymeleaflayout;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {

@RequestMapping("/")
public String home(){
return "index";
}

}

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%202.png

앞서 프로젝트 생성시 thymeleaf를 추가했기때문에, 컨트롤러가 리턴하는 String은 프로젝트의 resources/templates 폴더 내부의 html파일과 바인딩이 된다.

resources/templates 폴더에 index.html 파일을 만들오 내용을 아래처럼 채우자.

index.html

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>springboot thymeleaf layout example</title>
</head>
<body>
index 페이지
</body>
</html>

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%203.png

이제 프로젝트를 기동시켜서 thymeleaf가 잘 동작하는지 확인해보자.

프로젝트를 기동하고, 브라우저에서 루트 경로로 접속하면 앞서 생성한 index.html 페이지가 렌더링 되는 것을 확인 할 수 있다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%204.png

Springboot에 thymeleaf dialect layout 라이브러리를 적용해서 thymeleaf 레이아웃을 구성해보자.

메이븐 리파지토리에서 thymeleaf 를 검색해보자.

https://mvnrepository.com/

다섯번째 정도에 Thymeleaf Layout dialect가 보인다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%205.png

들어가서 2020-05-21 기준 최신버전인 2.4.1의 gradle 방식의 의존성 스크립트를 복사한다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%206.png

프로젝트의 build.gradle에 해당 내용을 추가해준다.

build.gradle

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
plugins {
id 'org.springframework.boot' version '2.3.0.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}

group = 'hanumoka.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'

repositories {
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation group: 'nz.net.ultraq.thymeleaf', name: 'thymeleaf-layout-dialect', version: '2.4.1'
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}

test {
useJUnitPlatform()
}

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%207.png

gradle에 관해서 잘 모르지만, compile방식은 구식이라 implementation구문으로 변경 했다.

주의, jdk가 1.8보다 높은 경우 thymeleaf-layout-dialect에서 groovy관련 문제가 발생할 수 있다. jdk1.8을 추천한다.

jdk11 + thymeleaf-layout-dialect 2.4.1 적용시 오류 내용

1
2
3
4
5
6
WARNING: An inllegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.reflection.CachedClass ~
WARNING: Please consider reporting this to the maintainers of org.codehaus.grovy.refleaction.CachedClass
WARNING: Use --illegal-access=warn to enable warnings of fucther inllegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
WARNING: An inllegal reflective access operation has occurred

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%208.png

jdk11에서 위처럼 경고가 나면서, 서버가 동작 될때도 있었고 아닐때도 있었다.

jdk1.8로 변경 후 문제가 해결되었다.

thymeleaf-layout-dialect로 thymeleaf 레이아웃 셋팅하기

아래처럼 templates폴더 내부에 fragments, layouts폴더와 html파일들을 만들어주자.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%209.png

layouts폴더 내부의 html파일은 말그대로 레이아웃으로 사용할 html 파일이다.

fragments폴더 내부의 파일들은 layout파일에서 공통적이며 반복적으로 사용 할 레이아웃 구성요소 html파일들이다.

templates/layouts/layout.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!DOCTYPE html>
<html
lagn="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head th:replace="fragments/config :: configFragment"></head>

<header th:replace="fragments/header :: headerFragment"></header>

<div layout:fragment="content"></div>

<footer th:replace="fragments/footer :: footerFragment"></footer>
</html>

레이아웃 html 페이지에서는 fragments폴더 내부의 html 들을 부속으로 호출한다.

config, header, footer 들은 레이아웃으 공통 구성 요소이고,

아래 부분이 실제 page url에 따라 바뀔 부분이다.

1
<div layout:fragment="content"></div>

templates/fragments/config.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head th:fragment="configFragment">
<meta charset="UTF-8" />
<!-- 공통으로 쓰이는 css파일을넣는다.-->
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
/>
<!-- 컨텐츠페이지의 CSS 영역이 들어감 -->
<th:block layout:fragment="css"></th:block>

<!-- 공통으로 쓰이는 css파일을넣는다.-->
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<!-- 컨텐츠페이지의 스크립트 영역이 들어감 -->
<th:block layout:fragment="script"></th:block>
</head>
</html>

config.html은 렌더링 되는 페이지에서 공통으로 사용할 css, script등을 설정한다.

아래부분에서 라우팅 될 contents 페이지에 설정된 css, script등을 역으로 받아온다.

1
2
3
4
<!-- 컨텐츠페이지의 CSS 영역이 들어감 -->
<th:block layout:fragment="css"></th:block>
<!-- 컨텐츠페이지의 스크립트 영역이 들어감 -->
<th:block layout:fragment="script"></th:block>

위 부분은 나중에 페이지가 동작하는 것을 보고 더 설명 하겠다.

templates/fragments/header.html

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<header th:fragment="headerFragment">
<div style="border: 1px solid green">
header.html 입니다.
</div>
</header>
</html>

templates/fragments/footer.html

1
2
3
4
5
6
7
8
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<footer th:fragment="footerFragment">
<div style="border: 1px solid gold">
Footer영역입니다.
</div>
</footer>
</html>

templates/index.html(컨텐츠 페이지)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layouts/layout"
>
<!-- index.html 고유 CSS 추가 -->
<th:block layout:fragment="css"> </th:block>

<!-- index.html 고유 스크립트 추가 -->
<th:block layout:fragment="script"> </th:block>

<div layout:fragment="content">
<div style="border: 1px solid red">
index.html 입니다. 즉 컨텐츠 영역
</div>
</div>
</html>

templates/hello.html(컨텐츠 페이지)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorator="layouts/layout"
>
<!-- hello.html 고유 CSS 추가 -->
<th:block layout:fragment="css"> </th:block>

<!-- hello.html 고유 스크립트 추가 -->
<th:block layout:fragment="script">
<script>
alert("hello.html");
</script>
</th:block>

<div layout:fragment="content">
<div style="border: 1px solid red">
hello.html 입니다. 즉 컨텐츠 영역
</div>
</div>
</html>

index.html, hello.html 은 컨텐츠 페이지다. 대충 코드를 보면 감이 올것이다.

아래처럼 index.html의 layout:fragment=”content” 영역이 layout.html의 layout:fragment=”content”에 치환되는 방식이다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2010.png

위에서 fragments/config 부분을 설명하다 말았는데, 여기서 보자

아래 이미지를 보면 이해가 될 것이다. hello.html 이 렌더링 되면 아래처럼 조립이 된다.

즉 config.html 파일을 통해서, contents 페이지 고유의 css, script등을 고립 시킬 수 가 있다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2011.png

hello.html을 리다이렉트 할 메소드도 추가해주자.

HomeController.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package hanumoka.example.springbootthymeleaflayout;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {

@RequestMapping("/")
public String home(){
return "index";
}

@RequestMapping("/hello")
public String hello(){
return "hello";
}

}

java코드는 레이아웃을 적용한다고 해도 딱히 문법적으로 바뀌는 부분이 없다.

이제 프로젝트를 기동시키고 http://localhost:8080/, http://localhost:8080/hello 페이지 url 접근해서 제대로 동작하는 지 확인 해보자.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2012.png

hello에서는 javascript 코드인 alert 창이 동작한다.(window.onload 코드를 생략해서 alert이 먼저 동작 했다.)

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2013.png

추가

위 예제로 정상 동작 하지만, 일부 문법이 deprecated 될거라는 WARN이 발생한다.

1
2
3
2020-05-21 22:28:23.122  WARN 15980 --- [nio-8080-exec-1] n.n.u.t.decorators.DecoratorProcessor    : The layout:decorator/data-layout-decorator processor has been deprecated and will be removed in the next major version of the layout dialect.  Please use layout:decorate/data-layout-decorate instead to future-proof your code.  See https://github.com/ultraq/thymeleaf-layout-dialect/issues/95 for more information.
2020-05-21 22:28:23.207 WARN 15980 --- [nio-8080-exec-1] n.n.u.t.expressions.ExpressionProcessor : Fragment expression "layouts/layout" is being wrapped as a Thymeleaf 3 fragment expression (~{...}) for backwards compatibility purposes. This wrapping will be dropped in the next major version of the expression processor, so please rewrite as a Thymeleaf 3 fragment expression to future-proof your code. See https://github.com/thymeleaf/thymeleaf/issues/451 for more information.
2020-05-21 22:28:23.373 WARN 15980 --- [nio-8080-exec-1] n.n.u.t.fragments.FragmentProcessor : You don't need to put the layout:fragment/data-layout-fragment attribute into the <head> section - the decoration process will automatically copy the <head> section of your content templates into your layout page.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2014.png

음… 위 예제는 몇 년전에 내가 만든 기준으로 해서 문법 변경이 조금 있었나 보다.

빠르게 수정해보자.

일단 기존에 사용하던 config.html 파일을 이제 사용할 필요가 없다.

layout.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<!DOCTYPE html>
<html
lagn="ko"
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
>
<head>
<meta charset="UTF-8" />
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
/>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
</head>

<header th:replace="fragments/header :: headerFragment"></header>

<div layout:fragment="content"></div>

<footer th:replace="fragments/footer :: footerFragment"></footer>
</html>

fragments/config 부분을 지워주고, config.html에 있던 공통 css, script 등을 layout.html head태그로 옮긴다.

아래 이미지 처럼 contents.html의 head태그가 렌더링 될 때, 자동으로 layout.html head 태그에 추가 된다.(치환이 아니라 추가 된다.)

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2015.png

index.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!DOCTYPE html>
<html
xmlns:th="http://www.thymeleaf.org"
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
layout:decorate="~{layouts/layout}"
>
<head>
<!-- thymeleaf layout dialect가 contents페이지의 head태그를 layout의 head태그에 자동으로 추가해준다. -->
<!-- 필요힌 css, script 추가영역 -->
</head>

<div layout:fragment="content">
<div style="border: 1px solid red">
index.html 입니다. 즉 컨텐츠 영역
</div>
</div>
</html>

contents html 페이지에서는 layout:decorator=”layouts/layout” 설정도 layout:decorate=”~{layouts/layout}” 이렇게 변경 되었다.

수정하고 확인해보면, 정상동작 아래처럼 잘 동작 한다.

Springboot%20thymeleaf%20layout%20dialect%20f1913625c1b946eca3591005c7e07316/Untitled%2016.png

github 소스

https://github.com/blog-examples/20200520-springboot-tymeleaf-dialect

참고자료

https://ultraq.github.io/thymeleaf-layout-dialect/Examples.html#passing-data-to-layouts

들어가기

이 예제는 Nginx등과 같은 웹서버에 HTTPS를 적용하기 위한 테스트용 SSL 인증서를 생성하는 예제이다.

실습환경

  • Windows10
  • OpenSSL
  • cmd

테스트용 HTTPS 인증서 생성하기

웹서버에 HTTPS를 적용하려면, CA에서 발급하는 SSL인증서가 필요하다.
보통 사설업체에 Domain을 기준으로 돈을 주고 인증서를 신청하는데, 지금은 테스트 용이므로 로컬에서 가짜 인증서를 만들어 보자.

Windows10에 OpenSSL 설치하기

인증서를 생성하기 위해서는 OpenSSL이라는 툴이 필요하다. 아래 링크해서 해당 툴을 다운 받자.

https://sourceforge.net/projects/openssl/files/latest/download?source=typ_redirect

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled.png

광고를 좀 봐주면서 시간이 지나면, OpenSSL zip파일이 다운로드가 된다.

아래처럼 zip파일 압축을 풀어주자.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%201.png

압축이 풀린 폴더 내부에 bin폴더 내부로 들어가 보면 아래처럼 openssl.exe 파일이 있다.
해당 파일을 관리자 권한으로 실행한 cmd로 실행해보자.

1
openssl-1.0.2j-fips-x86_64\OpenSSL\bin\openssl.exe

내 경우 문제가 발생했는데, openssl.exe 실행시 openssl.cnf 파일을 읽어오시 못한다는 경고가 나온다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%202.png

1
WARNING: can't open config file: C:/OpenSSL/openssl.cnf

경고 메세지를 보면 OepnSSL 폴더가 C 드라이브 바로 아래에서 읽어 오고 있다.

따라서 OpenSSL 폴더를 C 드라이브 경로로 옮겨서 다시 실행해보자.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%203.png

OpenSSL 폴더를 C 드라이브로 옮겼다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%204.png

C:\OpenSSL\bin\openssl.cnf 파일을 복해서 C:\OpenSSL로 옮겨주자.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%205.png

다시 C:\OpenSSL\bin\openssl.exe 파일을 관리자 권한 cmd로 실행해보자.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%206.png

아래처럼 정상적으로 openSSL이 실행된다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%207.png

RSA 개인키를 생성하자.

OpenSSL 커멘드에 아래 명령어를 입력해서 개인키를 생성하자.

1
genrsa -out private.key 2048

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%208.png

아래처럼 openSSL.exe 실행경로에 private.key 파일이 생성된 것을 확인 할 수 있다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%209.png

파일을 열어보면 아래처럼 개인키가 보인다.

테스트 용도라서 이렇게 노출하지만, 실제 절대 외부로 노출되서는 안되는 개인키 이다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2010.png

RSA 개인키를 이용해서 RSA 공개키를 생성하자.

개인키가 있는 경로에서 아래 명령어를 입력해서 공개키를 생성하자.

1
rsa -in private.key -pubout -out public.key

아래처럼 public.key 가 생성된다. (이미지에서는 명령어 입력시 오타를 쳐서 파일명이 이상하다.)

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2011.png

공개키 파일을 열어보면 아래와 같다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2012.png

CSR(인증요청서) 생성하기

CA 인증기관에게 인증서를 받기위한 인증요청서를 생성해야 한다.
신청할 때에는 국가코드, 도시, 회사명, 부서명, 이메일, 도메인주소등 다양한 정보를 입력 받게된다.

이 CSR은 앞서 생성한 RSA 개인키를 이용해서 생성 할 수 있다.

openSSL커맨드로 아래 명령어를 입력하자.

1
req -new -key private.key -out private.csr

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2013.png

아래처럼 국가 코드를 입력하라고 나온다. kr 이라고 입력하고 넘어가면

아래처럼 추가정보를 입력하라고 주르륵 나온다. 테스트 용이니 대충 입력하고 넘기자.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2014.png

아래처럼 private.csr 인증 요청서가 생성 되었다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2015.png

CRT(인증서)만들기

이제 인증요청서로 테스트 용도의 가짜 CRT를 만들어보자.

CA 역할을 할 CA 대칭키 생성

아래 명령어로 CA역할을 할 CA 대칭키(aes256)를 생성하자.

(사실 왜 대칭키를 생성하는지 모르겠다.)

1
genrsa -aes256 -out rootCA.key 2048

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2016.png

아래처럼 rootCA.key 가 생성 되었다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2017.png

rootCA.key를 이용해서 rootCA.pem 생성

(사실 이녀석도 뭔지 잘 모르겠다.)

1
req -X509 -new -nodes -key rootCA.key -days 2650 -out rootCA.pem

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2018.png

비밀번호등 국가코드, 도시 기타 등등 정보를 입력해야 한다.(테스트니 대충 넣자)

아래처럼 rootCA.pem 파일이 생성된다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2019.png

웹서버에 HTTPS적용을 위해 필요한 CRT 인증서를 생성

이제 마지막으로 CRT를 즉 웹서버에 HTTPS를 적용하기 위한 인증서를 생성해보자.

아래 명령어를 이용해서 앞서 생성한, 인증 요청서(private.csr) , rootCA.pem, rootCA.key 를 이용해서 웹서버에 등록할 CA 인증서 private.crt 를 생성하자.

1
x509 -req -in private.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out private.crt -days 3650

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2020.png

아래처럼 private.crt 파일이 생성되었다. 모양세도 지금까지 생성한 파일과는 좀 다르다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2021.png

파일을 열어보면 아래처럼 나온다.

HTTPS%20SSL%20OpenSSL%2080f6b0d2700149518b84d5d8a5a4509e/Untitled%2022.png

실습 끝!!!

ps

사실 이런 인증서 부분에 대해 정확히 알지 못해, 실습을 하면서도 다 이해하지 못했다.
특히 CA 인증서 생성부분… 시간이 좀 나면 해당 내용을 공부해서 보충 해야 겠다.

참고자료

https://namjackson.tistory.com/24
https://opentutorials.org/course/228/4894

들어가기

React 프로젝트를 만약 서버에 배포해야 한다면, 어떻게 해야할까?

서버에 Apache나 Nginx등을 설치하고 웹 서버 설정을 한뒤, React로 build한 소스를 해당 서버에 FTP로 전송하면된다.

이런 방법도 좋지만, Docker를 사용해서 웹서버를 React와 묶어놓은 이미지가 있다면 어떤 서버든 docker engine만 설치되어 있다면 바로 실행시킬수 있을것 같다.

이런식으로 배포할경우 웹서버의 설정역시 Docker의 설정으로 관리할 수 있을것이다.

이번에는 Docker를 이용해서 React와 Nginx를 합쳐 이미지화하고 그 이미지를 컨테이너화 하여 실행해보자.

개발환경

  • windows10
  • docker desktop
  • VisualStudioCode
  • GitBash

실습

일단 테스트할 react 프로젝트를 생성하자.

1
npx create-react-app docker-react-ngnix

Docker%20React%20Nginx/Untitled.png

생성된 프로젝트으 root 경로에 Dockerfile-prod 이라는 파일을 생성하자.

여기서 파일명은 무엇으로 해도 상관 없으나 prod(production)이라고 표시해두면, Dockerfile, Dockerfile-dev, Dockerfile-prod등 배포 환경에 따라서 관리하기가 편하다.

Docker%20React%20Nginx/Untitled%201.png

그리고 해당파일을 아래처럼 채우자.

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
FROM node:12.16.2 as builder

# 작업 폴더를 만들고 npm 설치
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts@3.4.1 -g --silent

# 소스를 작업폴더로 복사하고 빌드
COPY . /usr/src/app
RUN npm run build

FROM nginx:latest
# nginx의 기본 설정을 삭제하고 앱에서 설정한 파일을 복사
RUN rm -rf /etc/nginx/conf.d
COPY conf /etc/nginx

# 위에서 생성한 앱의 빌드산출물을 nginx의 샘플 앱이 사용하던 폴더로 이동
COPY --from=builder /usr/src/app/build /usr/share/nginx/html

# 80포트 오픈하고 nginx 실행
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]

Node, react-script, nginx 등 원하는 버전을 설정하자.

Docker%20React%20Nginx/Untitled%202.png

이미지를 생성할 Dockerfile-prod는 만들었으니, 이 Dockerfile-prod파일에서 사용하는 nginx설정 파일을 만들어 줘야 한다.

Docker%20React%20Nginx/Untitled%203.png

프로젝트 root 경로에 conf/conf.d 파일을 만들어주자.

Docker%20React%20Nginx/Untitled%204.png

그리고 해당 파일 내부를 아래처럼 채워주자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;

location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}

error_page 500 502 503 504 /50x.html;

location = /50x.html {
root /usr/share/nginx/html;
}
}

위 내용은 Nginx의 설정 파일이다.

이제 준비는 끝났다.

프로젝트 root 경로, 즉 Dockerfile-prod 파일이 있는 경로에 터미널을 열고 아래 명령으로 이미지를 생성하자.

1
docker build -f Dockerfile-prod -t docker-react-ngnix

위 명령어 설명

  • -f Dockerfile-prod : 해당 파일을 기반하여 docker image를 생성한다.
  • -t docker-react-ngnix : 생성할 이미지를 지정한다.

Docker%20React%20Nginx/Untitled%205.png

위 이미지에서는 마지막에 .(콤마) 가 찍혀 있지만 앞에 -f 옵션으로 Dockerfile을 지정해 주었기 때문에 없어도 될거 같지만, 반드시 찍어주어야 한다.

Docker%20React%20Nginx/Untitled%206.png

위 처럼 docker-react-ngnix 이미지가 생성 되었고, 해다 이미지에서 참조하는 nginx, node 이미지들도 다운이 되었다.

다음 명령어로 docker-react-ngnix 이미지를 컨테이너화 하고 실행시키자.

1
docker run -it -p 80:80 docker-react-ngnix

Docker%20React%20Nginx/Untitled%207.png

그리고 새로운 터미널에서 다음 명령어로 실행중인 docker 프로세스를 확인해 보자.

1
docker ps

아래처럼 컨테이너가 실행중임을 확인 할 수 있다.

Docker%20React%20Nginx/Untitled%208.png

아래처럼 브라우저에서도 정상 동작을 확인 할 수 있다.

Docker%20React%20Nginx/Untitled%209.png

참고자료

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

들어가기

AWS에 ec2를 이용해서 Ubuntu를 설치하고 접속해보는 예제이다.

ec2 하드웨어 사양은 무료티어(t2.micro)를 사용했다.

개발환경

  • windows10
  • putty
  • aws 계정(미리 가입되어 있어야 한다.)
  • git bash

실습

일단 aws의 AWS Management Console에 접속하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled.png

EC2를 선택하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%201.png

대시보드화면이 나오는데 화면 가운데 오랜지색 버튼인 인스턴스 시작을 눌러주자.

다음 화면에서 EC2에 사용할 이미지(AMI)를 고를수 있다.

나는 개인적으로 익숙한 Ubuntu18.04를 선택했다.

이미지 설명에 프리티어 사용가능한 이미지로 선택했다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%202.png

위 이미지처럼 원하는 이미지의 선택버튼을 누르자.

다음 화면에서는 EC2의 하드웨어 설정이 나온다.

역시 무료사용이 가능한 프리티어 t2.micro @ 를 선택하고 다음:인스턴스 세부 정보 구성을 클릭한다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%203.png

다음 화면은 인스턴스 세부 정보 구성 화면이다. 기본 값을 건드리지 말고 다음:스토리지 추가를 클릭하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%204.png

다음 화면은 스토리지 추가 화면이다. 설명을 보면 프리티어 사용가능 고객은 최대 30GB의 EBS 범용(SSD) 또는 마그네틱 스토리지를 사용할 수 있다고 한다.

나는 그냥 기본으로 두고 다음: 태그 추가 버튼을 클릭했다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%205.png

다음화면은 태그 추가 화면이다.

아무것도 하지 않고 다음: 보안:그룹 구성을 클릭하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%206.png

다음화면은 보안그룹 구성 화면이다.

기본적으로 SSH 유형만 설정되어있는데, 나는 규칙추가를 통해 HTTP, HTTPS도 추가해주었다.

나중에 해당 인스턴스에 웹서버를 올려서 테스트 해볼까 하기 때문이다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%207.png

설정이 끝나면 검토 및 시작 버튼을 클릭하자.

마지막 단계인 인서턴스 시작 검토 화면이다.

지금까지 설정한 내용이 요약으로 보여진다.

시작하기 버튼을 클릭하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%208.png

다음처럼 키페어를 생성하는 팝업 창이 열린다.

여기서 생성한 키페어파일를 이용해서 생성된 인스턴스에 SSH로 접속이 가능하다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%209.png

만약 기존에 생성한 키페어가 있다면, 그것을 재 사용할수 있다.

하지만 난 없으니 새 키페어 생성을 선택하고 키페어 이름을 지정한다.(영문)

그리고 키페어 다운로드 버튼을 눌러, 입력한 키페어이름.pem 파일을 다운 받는다.

해당 파일이 있어야 인스턴스에 접속이 가능하므로, 외부에 유출되지 않게 잘 보관해야 한다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2010.png

아래처럼 pem 파일이 다운받아진다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2011.png

pem 파일을 다운 받은후 인스턴스 시작 버튼을 눌러주자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2012.png

아래처럼 인스턴스가 시작중이라고 나온다.

인스턴스 보기 버튼을 눌러주자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2013.png

다음처럼 대쉬보드 화면으로 이동하고 인스턴스 상태가 pending으로 나온다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2014.png

pending은 인스턴스가 준비되고 있다는 것을 의미한다. running으로 바뀔 때 까지 기다린다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2015.png

Git bash에서 ssh로 Ec2에 접속하기

이제 실행중인 인스턴스에 접속해보자.

대쉬보드 화면에서 해당 인스턴스를 마우스 우클릭 후 연결을 클릭하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2016.png

다음처럼 SSH 클라이언트로 인스턴스에 연결 할 수 있응 방법이 나온다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2017.png

빨간줄과, 녹색줄은 보안을 위해 지웠다.

중요한건 예: 아래의 ssh 명령어 줄이다.

ssh 명령의 형식은 아래와 같다.

1
ssh -i "인스턴스 키패어.pem" 계정명@인스턴스 주소

aws에서 ubunt 이미지로 인스턴스를 생성했을대 기본 계정으로 ubuntu를 생성해준다.

@이 뒤에 인스턴스 주소는 aws에서 인스턴스를 생성할때 유니크한 도메인을 자동으로 생성해준다.

팝업에 나오는 ssh 명령어 한줄을 그대로 복사한 뒤, git bash 창을 열고 접속해보자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2018.png

뭔가 연결을 진행할 거냐 물어보는데 yes를 눌러주자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2019.png

다음처럼 접속이 된 것을 확인 할 수 있다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2020.png

putty로 Ec2 인스턴스에 접속하기.

과정요약

  • 키페어.pem 파일을 puttygen프로그램을 이용해서 ppk파일로 변환
  • putty에 ppk파일을 등록
  • putty로 Ec2 인스턴스에 접속

실습

일단 puttygen.exe를 실행한다.

보통 putty가 설치된 폴더에 같이 있다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2021.png

puttygen 프로그램의 Conversions-import key 항목을 선택한다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2022.png

아까 인스턴스 생성시 다운받은 키페어.pem 파일을 탐색창에서 찾아 연다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2023.png

그 다음에 Save private key 버튼을 클릭하면 새로운 ppk 파일을 생성 할 수 있다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2024.png

생성된 ppk 파일.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2025.png

이제 위에서 생성한 ppk 파일을 putty에 등록해서 사용하면된다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2026.png

일단 putty를 열고 카테고리에서 Connection-SSH-Auth 들어가서 Private key file for authentication 항목의 Browse를 클릭해서 ppk 파일을 등록하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2027.png

다시 아까 인스턴스 연결에서 보았던 접속주소를 복사한다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2028.png

위 이미지의 녹색 영역이 접속주소이다.

해당 내용을 putty session에 Host Name에 입력하고 Open 버튼을 클릭하자.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2029.png

다음처럼 접속이 잘 되는 것을 확인 할 수 있다.

aws%20ec2%20ubuntu%20AMI%20t2%20micro/Untitled%2030.png

끝!!!

참고자료

책: 당신이 지금 알아야 할 AWS(이영호, 한동수)

들어가기

Docker를 사용해서 React와 Node를 묶어 이미지를 만들고 그 이미지를 이용해서 컨테이너를 생성하고 실행하는 예제이다.

개발환경

  • windows10
  • visual studo code
  • docker desktop

실습

일단 create-react-app 으로 사용할 react 프로젝트를 생성한다.

1
npx create-react-app react-docker-example1

프로젝트 명은 react-docker-example1로 지정했다.

Docker%20React%20Node/Untitled.png

프로젝트가 생성되면 정상동작하는지 확인 해 보자.

Docker%20React%20Node/Untitled%201.png

잘 동작하는 것을 확인 할 수 있다.

Docker%20React%20Node/Untitled%202.png

프로젝트 경로로 진입해서 VisualStudoCode를 실행하자

아래 명령으로 현재경로에서 VisualStudoCode를 실행 할 수 있다.

1
code .

Docker%20React%20Node/Untitled%203.png

프로젝트 최상위 경로에 DockerFile을 생성하고 내용을 아래처럼 채우자.

node 이미지 버전의 경우 자신에 맞게 설정해주자.

1
2
3
4
5
6
7
8
9
10
11
12
13
FROM node:12.16.2 as builder

# 작업 폴더를 만들고 npm 설치
RUN mkdir /usr/src/app
WORKDIR /usr/src/app
ENV PATH /usr/src/app/node_modules/.bin:$PATH
COPY package.json /usr/src/app/package.json
RUN npm install --silent
RUN npm install react-scripts@2.1.3 -g --silent

# 소스를 작업폴더로 복사하고 앱 실행
COPY . /usr/src/app
CMD ["npm", "start"]

Docker%20React%20Node/Untitled%204.png

DockerFile을 만들었다면, 이제 이 DockerFile을 이용해서 image를 생성하자.

1
docker build -t react-docker-example1

난 프로젝트명과 이미지명을 동일하게 지정했다.

Docker%20React%20Node/Untitled%205.png

난 DockerFile에 설정한 node 버전의 이미지가 없어서 다운받는데 좀 시간이 걸렸다.

node 이미지가 받아지면 DockerFile을 기반해서 새로운 이미지가 생성될 것이다.

아래 명령어로 확인해보자.

1
docker images

Docker%20React%20Node/Untitled%206.png

DockerFile에서 참조하고 있는 node 이미지와 그 기반으로 만들어진 react-docker-example1 이미지가 보인다.

아래 명령어로 생성한 react-docker-example1 이미지를 컨테이너화 하고 실행해보자.

1
docker run -it -p 3000:3000 --rm 이미지명또는아이디

Docker%20React%20Node/Untitled%207.png

docker run 옵션중 -it 로 인해 아래처럼 컨테이너 실행시 react 컨테이너에서 출력하는 콘솔이 터미널로 출력된다.

1
**--rm** 옵션은 컨테이너가 종료될때 해당 컨테이너를 자동으로 지워준다.

Docker%20React%20Node/Untitled%208.png

정상적으로 컨테이너가 동작하는 것을 확인 할 수 있다.

Docker%20React%20Node/Untitled%209.png

새로운 터미널에서 아래 명령어로 실행중인 컨테이너를 확인해보자.

1
docker ps

Docker%20React%20Node/Untitled%2010.png

이제 해당 컨테니어를 종료해보자.

1
docker stop 컨테이너id

일반적으로 위 명령어로 docker 컨테이너를 종료한다.

하지만 docker run 옵션으로 -it 사용했기에, docker run을 실행중인 터미널에서 ctrl+c 를 입력해도 docker 컨테이너가 종료된다.

Docker%20React%20Node/Untitled%2011.png

다시 docker ps로 해당 컨테이너가 자동으로 삭제되었는지 확인해보자.

Docker%20React%20Node/Untitled%2012.png

끝!!!

참고자료

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

들어가기

docker로 간단하게 테스트용 mongodb 서버를 실행하는 예제이다.

이글은 컨테이너 생성과 접근정도만 다룬다.

관리자 계정생성등은 구글링 ㄱㄱ

환경

  • windows10
  • docker desktop

실습

콘솔에서 아래 명령어로 mongodb 이미지를 검색하자.

docker search mongo

Docker%20mongodb/Untitled.png

아래 명령어로 해당 이미지를 다운받자.

docker pull mongo

Docker%20mongodb/Untitled%201.png

아래 명령어로 다움받은 mongo 이미지를 컨테이너화 하고 실행하자.

docker run --name mongodb_test -d -p 27017:27017 mongo

옵션설명

  • –name mongodb_test : 컨테이너 이름을 mongodb_test로 지정
  • -d : 데몬으로 실행 설정
  • -p 27017:27017 : 호스트 포트 27017로 접슨시 해당 컨테이너의 27017로 포트포워딩

주의

위에서 생성한 mongodb_test 는 테스트용 db로 사용할 목적이라서 로그인없이 db에 접근이 가능하다.

만약 몽고 컨테이너 생성시 로그인 기능을 활성화 시키려면 아래 명령어로 컨테이너를 실행시키자.

docker run -name mongodb_test -d -p 27017:27017 mongo –auth

마지막에 -auth를 추가해주면 된다. 나느 테스트 용이므로 -auth 옵션은 생략한다.

Docker%20mongodb/Untitled%202.png

mysql는 이전에 테스트용으로 생성한 것이다. mongodb_test 컨테이너가 생성된 것을 확인 할 수 있다.

이제 컨테이너에 bash로 붙어보자.

docker exec -it mongodb_test /bin/bash

위 명령어로 컨테이너에 진입하게 되면 다시 아래 명령어로 mongodb에 붙어보자.

mongo

Docker%20mongodb/Untitled%203.png

위처럼 정상 접근이 되는 것을 확인 할 수 있다.

끝!

들어가기

이 블로그는 hexo라는 정적 웹 생성기로 만들어져 있고, hexo로 만들어진 정적웹을 github 페이지에 배포하여 운영하고 있다.

여기서 gitpage로 hexo블로그를 배포하기 위해서는 hexo 블로그를 작성하고 배포하는 pc에서 ssh키를 생성하고, 이 생성된 ssh키의 공개키를 github 계정에 등록해 줘야 한다.

이번에는 그 과정을 정리해본다. (간단한 거지만 이따금 하는 일이라 자주 까먹는다.)

환경

  • windows10
  • git bash

실습

1.개발PC에서 ssh 키 생성하기

Github%20push%20pull%20ssh%20windows10/Untitled.png

일단 git bash를 열자. (cmd, power shell 등을 사용해도 상관 없으나 윈도우 커맨드를 별로 안좋아해서 git bash를 사용했다.)

git bash 명령어

pwd
cd ~/.ssh

Github%20push%20pull%20ssh%20windows10/Untitled%201.png

현재 사용자 계정의 폴더에 .ssh라는 폴더 가 있는지 확인해보자.

난 현재 OS를 초기화 한 상태라서 위처럼 폴더 자체가 없다.

해당 폴더를 만들고 내부로 진입하자.

git bash 명령어

cd ~/.ssh
mkdir ./ssh
ls -al

Github%20push%20pull%20ssh%20windows10/Untitled%202.png

이제 .ssh 폴더 내부에서 ssh를 생성하자.

git bash 명령어

ssh-keygen -t rsa -b 4096 -C "example@email.com"

위 명령어는 ssh 비대칭 키를 생성하는 명령어 이다.

  • ssh-keygen : ssh 비대칭키 생성 명령어
  • -t rsa : 암호화 타입을 rsa 방식을 사용
  • -b 4096 : 생성할 키의 비트수 4096으로 지정, rsa 타입을 위해선 최소 768 비트가 필요하며 default로 2048 비트이다. 4096으로 더 난독화된 키를 생성한다.
  • -C “example@email.com“ : 코멘트로 일종의 주석이다. 보통 이메일 계정이나 아이디등을 입력한다.

위명령어를 입력하면 다음처럼 공개키, 비밀키를 생성을 한다.

Github%20push%20pull%20ssh%20windows10/Untitled%203.png

Enter를 눌러서 현재위치인 .ssh/id_rsa 파일을 생성하게 하자.

Github%20push%20pull%20ssh%20windows10/Untitled%204.png

그 다음에는 암호를 입력하라고 한다. 이 ssh를 사용할 때 암호 입력으로 한번더 검증을 하기 위해서는 여기에 암호를 넣어주어야 한다.

그냥 enter를 누를경우 ssh키 사용시 암호입력 없이 사용이 된다.

난 암호 입력을 사용하고 싶으니 암호를 입력한다.

암호 확인을 위해서 두번 입력해 주어야 한다.

Github%20push%20pull%20ssh%20windows10/Untitled%205.png

Github%20push%20pull%20ssh%20windows10/Untitled%206.png

위처럼 ssh 가 생성이 완료 되었다.

id_rsa는 비밀키이고, id_rsa.pub는 공개키이다.

id_rsa.pub 공개키가 github에 등록해야 할 대상이다.

해당 파일을 문서 편집기로 열어서 내용을 클립보드에 복사하자.

Github%20push%20pull%20ssh%20windows10/Untitled%207.png

2. github에 ssh 공개키를 등록하자.

Github%20push%20pull%20ssh%20windows10/Untitled%208.png

github페이지에서 계정의 Settings로 들어가자.

Github%20push%20pull%20ssh%20windows10/Untitled%209.png

왼쪽 메뉴에서 SSH and GPG keys를 클릭하자.

Github%20push%20pull%20ssh%20windows10/Untitled%2010.png

New SSH key 를 클릭하자.

Github%20push%20pull%20ssh%20windows10/Untitled%2011.png

Title에는 ssh를 설명하는 내용을 적어주고.

key에는 아까 생성하고 클립보드에 복사한 ssh 공개키를 붙여넣자.

그리고 Add SSH key 버튼을 누르면 끝!

Github%20push%20pull%20ssh%20windows10/Untitled%2012.png

위처럼 등록이 된다.

hexo 블로그를 github에 배포해서 동작이 되나 확인해보자.

Github%20push%20pull%20ssh%20windows10/Untitled%2013.png

잘 동작이 된다.

끝!!!

마무리

개발 pc에서 ssh키를 생성하고 github에 계정에 등록하면, github에 push, pull등을 할때 github 계정으로 push, pull하는 것이 아니라 이 ssh 키로 push, pull을 할 수 있다.

혹시 github push, pull 할 때 비밀번호 입력등이 귀찮은 경우, ssh 키 생성시 passphrase를 생략할 경우, 비밀번호를 생략해서 push, pull을 할 수 있다.

참고자료

[Ubuntu/Linux] ssh 공개키의 모든 것

GitHub SSH 키 생성 및 등록하여 사용하기

개요

얼마 전 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