SpringBoot + ES6 + React 기반 보일러플레이트 소스

|

SpringBoot/ES6/React 기반으로 개발시 기반 소스로 바로 사용할 수 있는 보일러플레이트입니다.
해당 소스에는 간단한 React 샘플이 포함되어 있습니다.

소스를 직접 확인하고 싶으시면 다음 주소에서 확인하시기 바랍니다.

GitHub URL : https://github.com/jistol/boilerplate-boot-es6

Specification

  1. Backend
    • SpringBoot 2.0.0.RELEASE (Spring MVC, Embedded Tomcat, Thymeleaf)
  2. Frontend Builder
    • Package manager : npm
    • Bundler : webpack
  3. ES6 Package
    • babel
    • react
    • jquery
    • bootstrap
    • sass
    • webpack-dev-server

Setup & Run

Git 설치 및 소스 다운로드

Git 설치주소 : https://git-scm.com/downloads

소스 다운로드

$ git clone "https://github.com/jistol/boilerplate-boot-es6.git" boilerplate-boot-es6.git

npm 설치 및 초기화

npm은 Node.js를 설치시 같이 설치 가능합니다.

Node.js 설치주소 : https://nodejs.org/en/

설치 후 ROOT폴더에서 아래 명령어를 통해 초기화를 실행합니다.

$ npm install

위 명령어를 실행하면 node_modules 폴더가 생기면서 package.json에 포함된 라이브러리들이 다운로드 됩니다.

Backend 서버 실행

Gradle 빌드를 통해 WAR파일을 생성하여 직접 실행 가능하나 SpringBoot를 실행 할 수 있는 Gradle Task 명령으로 실행하여 서버를 기동할 수 있습니다.
Gradle Wrapper가 소스에 포함되어 있으므로 별도의 설치 과정없이 아래와 같이 실행 가능합니다.

$ ./gradlew bootRun

서버는 기본적으로 8080 포트로 접근 가능합니다.

ES6 소스 변환 및 Frontend Dev서버 실행

일반적으로 ES6를 지원하는 브라우저에서 실행하거나 babel을 통해 호환 가능한 소스로 빌드 후 실행할 수 있는데, 본 소스는 후자의 케이스로 실행하도록 샘플이 작성되어 있습니다.
변환은 아래와 같이 package.json에 npm 명령을 통해 실행 할 수 있도록 정의되어 있습니다.

...
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "npm run build-js",
    "build-js": "./node_modules/.bin/webpack --config webpack.config.babel.js",
    "dev": "NODE_ENV='local' ./node_modules/.bin/webpack-dev-server"
  },
...

변환 실행은 아래와 같이 실행가능합니다.

$ npm run build

또한 빠른 개발을 위해 변경사항을 바로 반영하기 위해서 webpack-dev-server를 실행 할 수 있습니다.
webpack-dev-server에 대한 정의는 webpack.config.babel.js 파일의 아래 부분에서 확인 가능하며 NODE_ENV 값이 ‘local’ 일 경우에만 동작하도록 설정되어 있습니다.

...
    if (process.env.NODE_ENV == 'local') {
        let url = `localhost`,
            protocol = `http`,
            devPort = 8090,
            proxyPort = 8080,
            demoEntry = {
            };

        config.entry = Object.assign({}, demoEntry, config.entry);

        config.devtool = 'inline-source-map';
        config.devServer = {
            inline: true,
            hot: true,
            historyApiFallback: true,
            host: url,
            port: devPort,
            proxy: {
                "!/dist/js/**": `${protocol}://${url}:${proxyPort}`,
                secure: false,
                changeOrigin: true,
            }
        };

        Object.keys(config.entry).forEach(key => {
            config.entry[key].push(`react-hot-loader/patch`);
            config.entry[key].push(`webpack-dev-server/client?${protocol}://${url}:${devPort}`);
            config.entry[key].push('webpack/hot/only-dev-server');
        });

        config.plugins.push(new webpack.HotModuleReplacementPlugin());
    }
...    

아래 명령을 통해 실행 할 수 있습니다.

$ npm run dev

webpack-dev-server를 사용하기 위해서는 8090 포트로 접근하여야 합니다.

서버 기동후 아래 URL로 접속하면 index 페이지를 볼 수 있으며 링크 클릭시 간단한 React 샘플 예제를 확인 할 수 있습니다.

URL : http://localhost:8090

index page

react sample

Spring MVC 생명주기

|

Spring 처음 접할때 공부하고 정형화된 틀 안에서 쓰다보니 어떤 구조로 동작하는지 잊고 쓰다가 한 번 소스까서 보면서 정리해봅니다. 특히 정말 SpringBoot 기반으로 개발을 하니깐 DispatchServlet 조차 처음 보는것 같더군요.

MVC Structure

다른 웹페이지 자료들을 보면 좀 모양새가 다른데 소스 기준으로 정리하다보니 이런 구조로 그렸네요.

요청 순서

  1. 요청받은 Request로부터 실행할 Controller 추출을 위해 HandlerMapping 을 통해 실행할 Handler및 Interceptor를 전달

  2. Interceptor의 preHandle을 실행

  3. HandlerAdapter에 Handler를 전달하여 해당 Controller의 Argument매핑및 Method Invoke 실행하고 결과를 ModelAndView 형태로 반환

  4. Interceptor의 postHandle을 실행

  5. Resolver를 통해 실제 보여줄 View를 렌더링하여 Response에 Write

  6. Interceptor의 afterCompletion 을 실행

Git Branch remove/delete (local/origin)

|

Local환경과 Remote환경의 Branch를 삭제하는 방법입니다.

Local Branch Remove

  • $ git branch -d [branch_name]
$ git branch -d feature-47
Deleted branch feature-47 (was 8b6cd3b).

Remote Branch Remove

  • $ git push -d [remote_name] [branch_nane]
$ git push -d origin feature-54
To https://xxxx.xxxx.xxx/v1/repos/xxxxx
 - [deleted]         feature-54

참고

How do I delete a Git branch both locally and remotely? : https://stackoverflow.com/questions/2003505/how-do-i-delete-a-git-branch-both-locally-and-remotely

Git Tag

|

Docker Redmine + Mysql 설치 및 Plugin 설치하기

|

ITS로 Redmine을 사용하려 간단히 세팅해보려 Docker기반으로 설정해보았습니다.
DockerHub에 있는 library/redmine - Docker Hub를 이용하고 DB는 Mysql을 사용하도록 세팅하는 과정을 적었습니다.

과정을 정리하긴 하였지만 bundler 오류가 발생하면 Container가 다운되고 다시 올라오지 못하는 현상이 종종 발생하오니 백업을 잘 하시기 바랍니다.

docker 생성

Link : https://hub.docker.com/_/redmine/

아래와 같이 image를 다운 받습니다.

$ docker pull redmine mysql

매번 docker run을 작성하기도 귀찮고 redmine / mysql 컨테이너를 각각 올리기 귀찮기 때문에 docker-compose를 이용하여 만들도록 하겠습니다.

# docker-compose.yml
version: '3.1'

services:
     redmine:
          image: redmine
          restart: always
          container_name: redmine
          ports:
               - 3000:3000
          environment:
               REDMINE_DB_MYSQL: db
               REDMINE_DB_PASSWORD: redmine
               REDMINE_DB_DATABASE: redmine
               REDMINE_DB_ENCODING: utf8
#               REDMINE_NO_DB_MIGRATE: true
     db:
          image: mysql
          restart: always
          ports:
              - 3306:3306
          environment:
               MYSQL_ROOT_PASSWORD: redmine
               MYSQL_DATABASE: redmine
          command:
               - --character-set-server=utf8mb4
               - --collation-server=utf8mb4_unicode_ci

추후 외부에서 접근하여 DB를 export하기 위한 용도로 3306포트를 열어두었으며 DATABASE 인코딩을 UTF-8로 사용하기 위해 추가 command 설정으르 하였습니다.
restart=always로 설정한 이유는 redmine보다 db가 먼저 뜰 경우 redmine이 죽어버리기 때문에 db가 정상으로 올라올떄까지 재시도하도록 하였습니다.
위와 같이 파일을 만든후 docker-compose명령어를 이용하여 실행합니다.

$ docker-compose up -d

정상 실행되면 아래와 같이 프로세스가 실행되는 것을 확인가능합니다.

$ docker ps -a
 CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
 e6491c0d5747        mysql               "docker-entrypoint..."   17 minutes ago      Up 17 minutes       0.0.0.0:3306->3306/tcp   redmine_db_1
 32eb215b34af        redmine             "/docker-entrypoin..."   17 minutes ago      Up 16 minutes       0.0.0.0:3000->3000/tcp   redmine

Redmine 플러그인 설치

ITS기능을 하기에 기본 Redmine은 좀 불편한 면이 있기 때문에 몇몇 플러그인을 설치해보록 하겠습니다.(무료만…)

설치과정에서 컨테이너 내부에 접속해 command를 날려야 합니다. 컨테이너에 접속하는 방법은 아래와 같습니다.

$ docker exec -it redmine bash

플러그인을 설치하기 앞서 사전에 필요한 모듈들을 설치하도록 합니다.

docker:redmine$ apt-get update
docker:redmine$ apt-get install -y unzip vim

Redmine 플러그인 설치 가이드는 Redmine - Plugins를 참고하시면 됩니다.
각 플러그인 설치후 Redmine을 재시작해야 반영됩니다.

Issue Template Plugin

Issue등록시 기본 템플릿을 지정할 수 있는 Plugin입니다. 공식 링크는 아래와 같습니다.

Link : https://github.com/akiko-pusu/redmine_issue_templates

설치방법은 아래와 같습니다.

docker:redmine$ cd ${REDMINE_ROOT}
docker:redmine$ git clone https://github.com/akiko-pusu/redmine_issue_templates.git plugins/redmine_issue_templates
docker:redmine$ rake redmine:plugins:migrate RAILS_ENV=production

Check List Plugin

Issue등록시 체크해야하는 사항이 있을때 같이 등록할 수 있는 Plugin입니다. 공식 링크는 아래와 같습니다.

Link : https://www.redmineup.com/pages/plugins/checklists

redmineup의 plugin은 직접 파일을 다운로드 받아 Redmine 컨테이너에 복사하고 unzip을 이용하여 plugin하위에 풀어야 합니다.

CheckList - Download

Light Version을 다운받아 아래와 같이 설치를 진행합니다.

$ docker cp ~/own_path/redmine_checklists-3_1_10-light.zip redmine_redmine_1:/usr/src/redmine/plugins/
$ docker exec -it redmine_redmine_1 bash
docker:redmine$ cd ${REDMINE_ROOT}
docker:redmine$ unzip plugins/redmine_checklists-3_1_10-light.zip -d plugins/
docker:redmine$ bundle install
docker:redmine$ rake redmine:plugins:migrate RAILS_ENV=production

Redmine Agile Plugin

가장 범용적으로 많이 쓰는 애자일 Plugin입니다. 공식 링크는 아래와 같습니다.

Link : https://www.redmineup.com/pages/plugins/agile

파일을 다운로드 받아 Redmine 컨테이너에 복사하고 unzip을 이용하여 plugin하위에 풀어야 합니다.

Redmine Agile Plugin - Download

Light Version을 다운받아 아래와 같이 설치를 진행합니다.

$ docker cp ~/own_path/redmine_agile-1_4_5-light.zip redmine_redmine_1:/usr/src/redmine/plugins/
$ docker exec -it redmine_redmine_1 bash
docker:redmine$ cd ${REDMINE_ROOT}
docker:redmine$ unzip plugins/redmine_checklists-3_1_10-light.zip -d plugins/
docker:redmine$ bundle install
docker:redmine$ rake redmine:plugins:migrate RAILS_ENV=production

Issue Charts Plugin

이슈별 통계치를 그래프로 보여주는 플러그인입니다.

Link : https://github.com/masweetman/issue_charts

설치 방법은 아래와 같습니다.

docker:redmine$ cd ${REDMINE_ROOT}
docker:redmine$ git clone https://github.com/masweetman/issue_charts.git plugins/issue_charts
docker:redmine$ bundle install
docker:redmine$ rake redmine:plugins:migrate RAILS_ENV=production

Redmine 테마 설치

classic 테마는 식상하니 심플한 테마를 하나 설치하도록 하겠습니다.
대부분의 테마설치방식은 비슷하고 어렵지 않기 때문에 아래 예제를 기반으로 다른 맘에드는 테마를 설치하셔도 됩니다.

Redmine gitmike theme

무료 테마중 인기있는 gitmike를 설치해보겠습니다. 공식 링크는 아래와 같습니다.

Link : https://github.com/makotokw/redmine-theme-gitmike

설치 방법은 아래와 같습니다.

docker:redmine$ cd ${REDMINE_ROOT}/public/themes
docker:redmine$ git clone https://github.com/makotokw/redmine-theme-gitmike.git gitmike

설치후 관리자(admin)으로 로그인하여 [관리 > 설정 > 표시방식] 에서 테마를 gitmike로 선택 후 저장하면 바로 적용됩니다.

Gitmike - Theme Setting

Git 저장소연결

SVN연결은 간편하게 되는 반면 GIT연결은 Local에 bare저장소가 같이 존재해야한다는 단점이 있습니다.
설정할 내용이 간단하지 않아 Redmine + Git Remote 연동 링크를 참고하여 연결하면 됩니다.

그 외 설정

Issue등록시 일반 Text로는 너무 딱딱하고 Richable Editor를 설치하기도 별로여서 기본적으로 Redmine에서 제공하는 Markdown 에디터를 사용하도록 하겠습니다.

관리자(admin)으로 로그인하여 [관리 > 설정 > 일반] 에서 본문형식을 markdown으로 변경합니다.
그리고 ISSUE를 등록해보면 본문내용을 markdown형식으로 사용 가능해집니다.

Setting - markdown

참고

Allow setting CHARACTER SET for the database : https://github.com/docker-library/mysql/pull/14
Redmine - Plugins : http://www.redmine.org/projects/redmine/wiki/Plugins
Redmine 시작/중지/재시작 : https://zetawiki.com/wiki/%EB%A0%88%EB%93%9C%EB%A7%88%EC%9D%B8_%EC%8B%9C%EC%9E%91/%EC%A4%91%EC%A7%80/%EC%9E%AC%EC%8B%9C%EC%9E%91