간단한 Web 프로젝트를 Spring Boot로 만들었는데

이상하게 Tomcat에 War로 올리면 404 에러로 경로를 못찾는 현상이 발생했다.

 

덕분에 몇시간을 날렸는데 이유는 간단했다..

 

 

Spring Boot의 Main 클래스에 SpringBootServletInitializer를 상속받지 않아서였다.

 

일반적인 Spring Framework에서는 Web.xml에 DispatcherServlet을 등록하는 작업이 필요했다.

Servlet 3.0에서는 web.xml이 없이도 배포가 가능 해졌는데 Apache Tomcat 7부터 지원을 한다.

 

web.xml의 역할을 WebApplicationinitializer 인터페이스를 구현하여 프로그래밍으로 ServletContext를 구현할 수 있도록 바뀐것이다.

SpringBootServletInitializer는 WebApplicationinitializer의 구현체이다. 

SpringBootServletInitializer를 이용하여 WebApplicationContext를 생성하여 Servlet Context에 추가할 수 있다.

 

나 같은 경우에는 프로젝트에 web.xml도 없었고, WebApplicationinitializer를 구현한 SpringBootServletInitializer도 없었기 때문에 Tomcat에서 URL의 요청을 받아드릴수가 없었던 것이다..

 

SpringBootServletInitializer를 상속 한다는건 결국 Tomcat과 같은 Servlet Container 환경에서 Spring Boot Application을 동작 가능 하도록 Web Application Context를 구성한다는 의미이다.!

 

나와 같은 삽질은 다른 사람들은 하지 않았으면....

RHEL 기반인 CentOS7에 postgreSQL을 설치하는 포스팅이다.

 

이전에 포스팅한 LXD에 올린 Centos7 컨테이너로 진행할 예정인데 일반적인 환경과 크게 다를건 없을것 같다.

 

 

1. http://yum.postgresql.org/ 에 접속해보면 설치가능한 버전과 지원하는 OS를 확인할 수 있다.

 

2. 저장소를 설치

-> sudo yum install https://download.postgresql.org/pub/repos/yum/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-3.noarch.rpm 

 

3. 설치가능한 패키지 검색

-> sudo yum list postgres*

 

3. PostgreSQL 9.6 버전 패키지 설치

-> sudo yum install postgresql96-server postgresql96-contrib

 

4. DB 생성

-> sudo /usr/pgsql-9.6/bin/postgresql96-setup initdb

 

5. PostgreSQL 시작

-> sudo systemctl restart postgresql-9.6

or

-> sudo service postgresql-9.6 start

 

6. 부팅시 자동 시작되게 설정

-> sudo systemctl enable postgresql-9.6 

 

 

이렇게 하면 PostgreSQL 서버를 설치하고 구동하는게 끝났다.

netstat -tnlp 명령어를 쳐서 아래와 같이 5432 포트로 서버가 구동되어있는걸 확인하면 끝.


[root@vm1 data]# netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      309/sshd
tcp        0      0 0.0.0.0:5432            0.0.0.0:*               LISTEN      427/postmaster
tcp6       0      0 :::22                   :::*                    LISTEN      309/sshd
tcp6       0      0 :::5432                 :::*                    LISTEN      427/postmaster

 

접속 해보고 싶다면 psql 명령어를 이용해서 접속할 수 있다.

-> sudo -u postgres psql

참고로 psql 접속 종료 명령어는 \q

 

이제 생성한 DB를 외부에서도 접속 가능하게 설정을 수정해줘야 하는데 vi에디터로 몇 줄 고쳐주면 된다.

 

6. 외부접속 허용하기 

-> cd /var/lib/pgsql/9.6/data/

-> vi pg_hba.conf

 

스크린샷처럼 맨 하단 라인에 아래의 내용을 추가한다

 host    all     all     0.0.0.0/0       password

 

그리고서 저장 후 vi를 종료 (:wq)

 

이제 마지막으로 postgresql.conf 파일을 수정

-> vi postgresql.conf

? 명령어를 사용해서 listen 검색 후 listen_addresses = '*' 로 수정한다. (주석 제거)

 

마찬가지로 저장 후 vi 종료

 

 

Orange Ade로 리눅스에 올린 PostgreSQL을 접속해보니 잘된다. 

 

혹시 위의 설정까지 했는데 안된다면 리눅스의 방화벽을 해제하길..!!

LXC와 LXD 둘중 뭐로할까 고민을 했는데

회사에서 쓰고있는 LXD를 이용하기로 결정했다.

 

검색해보면 LXD보다는 LXC 문서가 많아서 걱정이 됬는데 잘 정리된 글을 보고 따라하니 한방에 성공.

나중에 까먹지 않기 위해서 블로그에 정리하는 글이다.

 

참조한 문서는 

https://www.cyberciti.biz/faq/how-to-set-up-and-use-lxd-on-centos-linux-7-x-server/

 

How to Set Up and Use LXD on CentOS Linux 7.x Server - nixCraft

Explains how to set up and use LXD on CentOS Linux 7.x server and create or configure your first operating system level virtualization.

www.cyberciti.biz

 

Step 1 – CentOS 7 업데이트

sudo yum update
sudo reboot // 난 리붓안함

 

Step 2 –  on CentOS 7에 EPEL 저장소 설정

sudo yum install epel-release
sudo yum update

 

Step 3 – CentOS 리눅스에서 COPR 저장소를 활성화 및 구성하는 방법

sudo yum install yum-plugin-copr

sudo yum copr enable ngompa/snapcore-el7

 

Step 4 – LXD 설치

sudo yum install snapd
sudo systemctl enable --now snapd.socket

 

Step 5 – LXD용 CentOS Linux 커널 구성


grubby --args="user_namespace.enable=1" --update-kernel="$(grubby --default-kernel)"
grubby --args="namespace.unpriv_enable=1" --update-kernel="$(grubby --default-kernel)"
sudo sh -c 'echo "user.max_user_namespaces=3883" > /etc/sysctl.d/99-userns.conf'
sudo reboot

Step 6 – LXD를 CentOS에 설치


sudo snap search lxd

sudo snap install lxd
sudo ln -s /var/lib/snapd/snap /snap

 

설치 확인하는법:
snap list
snap services // 이거할때 데몬에러뜸 하지만 무시

// 여기까지 진행 후 Reboot으로 시스템 재부팅

Step 7 – LXD 설정


sudo usermod -a -G lxd vivek
newgrp lxd
id

 

// LXC 서버 확인 (생성된 컨테이너를 확인할 수 있다. 하지만 지금은 초기라 List에 뜨는게 없을꺼임)
lxc list

 

[root@localhost 아무개]# lxc image list images:
+--------------------------------------+--------------+--------+----------------------------------------------+---------+-----------+-------------------------------+
|                ALIAS                 | FINGERPRINT  | PUBLIC |                 DESCRIPTION                  |  ARCH   |   SIZE    |          UPLOAD DATE          |
+--------------------------------------+--------------+--------+----------------------------------------------+---------+-----------+-------------------------------+
| alpine/3.6 (3 more)                  | d3416fd3f3e3 | yes    | Alpine 3.6 amd64 (20190528_13:00)            | x86_64  | 3.17MB    | May 28, 2019 at 12:00am (UTC) |
+--------------------------------------+--------------+--------+----------------------------------------------+---------+-----------+-------------------------------+
| alpine/3.6/arm64 (1 more)            | cc9107640c99 | yes    | Alpine 3.6 arm64 (20190528_13:02)            | aarch64 | 3.07MB    | May 28, 2019 at 12:00am (UTC) |
+--------------------------------------+--------------+--------+----------------------------------------------+---------+-----------+-------------------------------+

 

// LXC Storage 생성 (컨테이너를 생성하기위한 스토리지 생성단계)
lxd init

[root@localhost 아무개]# lxd init
Would you like to use LXD clustering? (yes/no) [default=no]: 
Do you want to configure a new storage pool? (yes/no) [default=yes]: 
Name of the new storage pool [default=default]: 
Name of the storage backend to use (btrfs, ceph, dir, lvm) [default=btrfs]: lvm
Create a new LVM pool? (yes/no) [default=yes]: 
Would you like to use an existing block device? (yes/no) [default=no]: 
Size in GB of the new loop device (1GB minimum) [default=15GB]: 
Would you like to connect to a MAAS server? (yes/no) [default=no]: 
Would you like to create a new local network bridge? (yes/no) [default=yes]: 
What should the new bridge be called? [default=lxdbr0]: 
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: 
Would you like LXD to be available over the network? (yes/no) [default=no]: 
Would you like stale cached images to be updated automatically? (yes/no) [default=yes] 
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: 

 

[root@localhost 아무개]# lxc storage list        // 생성된 스토리지 확인
+---------+-------------+--------+--------------------------------------------+---------+
|  NAME   | DESCRIPTION | DRIVER |                   SOURCE                   | USED BY |
+---------+-------------+--------+--------------------------------------------+---------+
| default |             | lvm    | /var/snap/lxd/common/lxd/disks/default.img | 1       |
+---------+-------------+--------+--------------------------------------------+---------+

 

Step 8 – 첫번째 컨테이너 생성하기

// 아래의 명령어를 사용하면 설치할수 있는 컨테이너의 List가 출력됨(무수히 많음)

lxc image list images:  // 전체 리스트
$ lxc image list images: | grep -i centos  // Centos 리스트
$ lxc image list images: | grep -u ubuntu // Ubuntu 리스트

 

첫번째 컨테이너 생성하는 방법

 


lxc launch images:{distro}/{version}/{arch} {container-name-here}

lxc launch images:{운영체제}/{버전}/{비트?} {컨테이너 이름}
Let us see some examples to create and start containers from various Linux distro images as per your needs.

 

[root@localhost 아무개]# lxc launch images:centos/7/amd64 test
Creating test
Starting test   

CentOS7 리눅스 생성 방법

lxc launch images:centos/7/amd64 cenots-db  

Ubuntu 리눅스 생성 방법

lxc launch images:ubuntu/xenial/amd64 ubuntu-nginx

Fedora 리눅스 생성 방법

lxc launch images:fedora/28/amd64 fedora27-c1

 

LXD의 명령어들


lxc list // 생성된 컨테이너 목록


[root@localhost 아무개]# lxc list

+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| NAME |  STATE  |         IPV4          |                     IPV6                     |    TYPE    | SNAPSHOTS |
+------+---------+-----------------------+----------------------------------------------+------------+-----------+
| test | RUNNING | 10.14.12.13 (eth0) | fd42:e47e:ef8a:90b:216:3eff:fee0:867b (eth0) | PERSISTENT |           |

+------+---------+-----------------------+----------------------------------------------+------------+-----------+

 


시작 종료 재부팅 방법
lxc start 컨테이너명     // 시작
lxc stop 컨테이너명     // 종료
lxc restart 컨테이너명  // 재시작

 

제거 or 삭제

lxc delete 컨테이너명   // 삭제


컨테이너 정보 가져오기
lxc info 컨테이너명      // 정보

 

컨테이너에 접속하기
lxc exec 컨테이너명 bash

[root@localhost 아무개]# lxc exec test bash
[root@test ~]#

 

 

 

※ 본 블로그를 제외한 다른곳에서의 공유를 금합니다.

 

 

안녕하세요

대항해시대 런처를 배포합니다.

2019-07-08일 1.0.6 버전의 런처를 배포합니다.

 

프로그램에 등록되는 계정 정보는 런쳐가 위치해있는 폴더의 login.ini에 기록됩니다.

비밀번호가 암호화 되지 않기에 개인 PC에서만 사용해주시기 바랍니다.

테스트를 많이 안해보았기에 버그가 존재할 수 있습니다.

사용시 아래 사항을 유의해주세요

 

※ 실행이 안될 경우

 - Internet Explorer가 실행 중 인지 확인 해주세요.

 - 실행중인 Internet Explorer가 있다면 종료해주세요. (작업관리자를 실행해서도 실행중인 프로세스 목록에 IE가 있는지도 확인후 있다면 죽여주세요)

 

1) 비밀번호 틀림으로 인한 계정 잠금 주의

 - 현재 계정 아이콘을 더블 클릭하면 로그인이 1회 진행됩니다. (반복해서 진행되지 않습니다.)

 

2) login.ini 파일 보안

 - 비밀번호가 암호화 되지 않으므로 개인 pc에서만 사용해주세요

 

3) Netmarble, Daum 로그인 URL

 - 기본으로 넷마블(http://dho.netmarble.net/main.asp), 다음(https://logins.daum.net/accounts/signinform.do)으로 설정 되어있습니다. 

 - 로그인이 안된다면 URL이 정확한 URL인지 확인해 주세요.

 

4) 'MSVCR120_CLR0400.dll이 없어 프로그램을 시작할 수 없습니다'

 - 사용하는 PC의 OS에 위의 DLL파일이 없어서 생기는 현상입니다.

 - 해당 DLL 파일을 다운로드 받으셔서 system32 폴더로 옮겨주세요. (자세한건 구글링)

 

5) Netmarble 계정은 안전키 기능 지원

 - 기능은 추가하였으나,, 간혈적으로 안되거나 실행이 안되는 경우가 있습니다.

 - 다음 버전에서 보안토록 하겠습니다.

 

 

다음 버전에서 추가 및 개선될 사항은 댓글로 남겨주시면 감사하겠습니다.

다음 버전에서 추가할 기능은 아래와 같습니다. (예정)

 

 

광고 한번씩 클릭해주시면 제작자에게 많은 도움이 됩니다 :D

 

 

대항해시대 런쳐(v1.0.6).zip
0.64MB

 

 

---------------------------- v1.0.6 (2019-07-06)

1) 서버 URL 사용 기능 추가 

 - 서버로부터 받는 URL 정보 이용

2) 로그파일 생성

3) 로그인 실패 유형 추가

 

---------------------------- v1.0.5 (2019-07-03)

1) 버전 체크 기능 추가

 - 클라이언트 구동시 서버와 버전 체크 기능 추가 (통신을 위한 dll 추가)

 - Client : 최신 버전정보, 로그인 URL 정보(다음, 넷마블), 다운로드 URL 정보 등

 - Server : Client IP, MAC 주소 정보 (사용 통계를 위한 정보 수집)

 

---------------------------- v1.0.4 (2019-06-04)

1) 런처 실행 옵션 추가

 - 게임 실행 / 홈페이지 로그인(출석체크) 기능이 추가

 - 홈페이지 로그인을 설정하면 홈페이지로 자동 로그인된 뒤 Internet Explorer가 자동으로 실행

 - 출석체크 버튼을 클릭하면 사용자가 지정한 URL로 이동

 - 설정 -> 실행 탭에서 수정 가능

2) 게임 실행전 실행중인 Internet Explorer를 종료시키는 기능 추가

 - 안전키 기능을 제외한 일반적인 로그인시 실패되는 현상중 원인을 꼽을 수있는게 실행중인 Internet Explorer가 있을경우 입니다.  Netmarble같은 경우에는 IE가 실해중이라면 이전 로그인한 계정의 Session이 남아있기에 새롭게 로그인시 실패할 수 있습니다. 

 - 미연에 방지하고자 게임실행시 실행중인(Background 포함) 프로세서중 IE가 있을경우 삭제할 것인가를 묻는 경고창 추가

3) Daum 계정의 보호조치 확인 기능 추가

 - 게임실행시 로그인이 실패될 경우 Daum계정의 보호조치가 걸려있다면 경고창으로 사용자에게 알려주는 기능 추가

4) 버그 수정

 

---------------------------- v1.0.3 (2019-05-26)

1) 넷마블 안전키 로그인 기능 추가(불안전함)

2) 설정 화면에서 안전키 정보 입력 가능

3) 로그인 로직 수정

4) 런처 실행 상태 추가

5) 잘못된 로그인 정보 출력


---------------------------- v1.0.1 (2019-05-16)

1) 넷마블 로그인 기능 추가

2) 설정 화면에서 계정 추가/수정/삭제 기능 추가

2-1) 넷마블/다음 접속 URL 수정 기능 추가

3) UI 수정 (아이콘 및 디자인)

4) 버그 수정

 

---------------------------- v0.0.1 (2019-05-08)

1) 다음 로그인 기능 추가

 

 

'취미 > 대항해시대 온라인' 카테고리의 다른 글

[대항해시대] 대항해시대 런처(v1.0.6)  (34) 2019.05.08
대항해시대 다클 가이드  (19) 2018.08.17
  1. 찰리b라운 2019.05.16 00:29

    오 굳

  2. 2019.05.18 07:52

    아이디 정보 넣고 저장 한 후에 실행했을떼.. 아무일도 안일어납니다. 에러매시지도 안나오는데.. 안되는 이유를 찾을려면 어떻게 해야 할까요?

    • 루우지 2019.05.18 14:58 신고

      1) URL 정보가 정확한지
      2) 비밀번호가 정확한지 혹은 비밀번호 변경 페이지가 뜨는건 아닌지
      3) 안전키가 설정되어있는건 아닌지

      한번 확인해주시겠어요?

    • 루우지 2019.05.18 14:58 신고

      추가적으로 넷마블/다음 모든 계정이 실행이 안되시는건가용?

  3. 냐옹이 2019.05.18 23:40

    넷마블 안전키도 만들어 주시면 정말 감사할꺼같아요

  4. 꽃순언니 2019.05.22 11:09 신고

    다운로드 언제 다시 가능할까요? +.+

  5. 냐옹이 2019.05.23 17:51

    안녕하세요
    런처를 아주 감사한 마음으로 잘쓰고 있는데요
    이번에 새로운 버전으로 만들어 주실때
    외부로그인<<아이콘을 클릭하면 게임이 바로실행되기
    내부로그인<<아이콘을 클릭하면 홈피에서만 로그인이 되기

    이거 두개다 가능하게 해주시면 안될까요?
    출석체크 이벤트할때 내부로그인 가능이 있으면 좋드라구요

    혹시 가능하신다면 부탁드릴께요~~

    • 루우지 2019.05.23 21:07 신고

      피드백 감사합니다~~

      말씀해주신 기능은 확인해보고 기능추가 목록에 올리겠습니다
      다만 언제까지 추가하겠단 말은 못드리겠지만 인지하고 있도록 하겠습니다~~

  6. 댕댕이 2019.05.24 18:25

    런처 필요 합니다 ㅠ

    • 루우지 2019.05.25 22:01 신고

      기능 추가하고 올릴랬는데 시간이 없어서.. 기다리게 해드렸네요 ㅠ

  7. 에릴 2019.05.30 13:41

    런처 만들어주셔서 감사해요.

    그런데 제 컴퓨터에서만 그런 것인지는 모르겠지만
    다음 로그인이 아예 되지를 않네요..
    url도 여러번 체크했고 아이디 비밀번호 모두 정확히 기입했으나
    계속 계정 정보가 틀렸다고 떠요.
    사용자 정의 url로 로그인 주소를 바꾸면 프로그램이 실행이 되지 않고 있구요.

    그리고 넷마블의 경우는 로그인 성공으로 게임 실행중 멘트까지는 뜨지만
    실제 게임이 실행되지는 않고 실행 중만 계속 뜹니다.

    만드시느라 고생하시고 계신데 혹 이럴 때는 어찌해야 할지..
    관리자 권한으로 실행도 해보고 아이디 비밀번호 매번 수정하지만 안되네요 ㅠㅠ
    꼭 작동시키고 싶습니다! ㅠㅠ

    • 루우지 2019.05.30 23:54 신고

      어험.. 혹시 다음 계정들만 구런 현상이 나나요 아니면 넷마블 계정들도 동일하게 실행이 안돼나요?

  8. 냐옹이 2019.05.30 23:01

    안녕하세요
    런처 만드신다고 정말 수고많으셨어요
    그런데 게임접속중 실행중까지는 뜨는데
    게임이 실행이 안될때가 많아요
    10번 실행하면 1번2번 게임이 실행됩니다
    만드신분한테 감놔라 배놔라 하는거 같아서 아주 죄송한마음이지만
    런처를 잘 쓰고싶은마음에 글남겨요~

    • 루우지 2019.05.30 23:56 신고

      피드백 감사합니다 넷마블 다음 구분 없이 실행이 잘 안되시나요? 업무가 많아 매일 야근이라 평일이나 주말에도 요즘 시간이 안나 개발을 거의 못하구 있네요 최대한 빨리 보완하도록 하겠습니다

  9. 냐옹이 2019.05.31 00:59

    넷마블은 아예 접속이 안되구요
    다음은 어쩌다 접속이 됩니당
    바쁘실텐데
    시간나실때 천천히 만들어주세요
    아시다시피
    이겜이 세월아 내월아하면서
    즐기는거라ㅋ
    급할게 없습니다
    일할신다고 바쁘신와중에도
    런처도 만들어주시고
    정말감사합니다ㅋㅋ

  10. 2019.07.01 04:27

    비밀댓글입니다

  11. 대항쥭돌 2019.07.03 15:07

    감사합니다. 복받으실거임

  12. 다음 2019.07.30 12:38

    안녕하세요! 정말 잘 사용하고 있습니다. 그런데 넷마블 아이디는 모두 정상 작동하는데 다음은 로그인이 안되네요 ㅜㅜ 정말 별별 방법 다해봤는데 다음 아이디로 접속이 안됩니다. 개발하시는데 도움이 되실까 하여 댓글 남깁니다. 만들어주셔서 감사합니다!

    • 루우지 2019.07.30 15:28 신고

      안녕하세요 하단의 진행상황이 어디까지 진행되고 안되는지 확이닝 될까요?

    • 다음 2019.08.06 08:46

      로그인 결과 확인중 에서
      [Daum]
      계정 정보가 올바르지 않습니다
      이렇게 나옵니다

  13. 루우지 2019.08.06 09:29 신고

    일단 입력한 비밀번호가 정확한지 확인 해주시고, 실제로 login.ini 파일에 해당 계정부분의 pw 항목을 확인해주세요. 실제 비밀번호와 동일하게 입력되어있는지(공백이 있다면 삭제해주시고)확인 해주시고 안되어있다면 해당 파일안에서 직접 수정 해보시고 시도해주세요.

  14. 대항대항 2019.08.09 18:36

    안녕하세요 런처 잘 사용하고 있습니다 감사합니다.
    근데 저도 다음에서 로그인이 진행되지 않고 있습니다. 아마 확실하진 않지만 이번 업데이트후 이벤트 정보 페이지가 새로 생겨서인듯 싶습니다. 혹시 수정이 가능한지 확인해주시면 감사하겠습니다.
    프로그램 만들어주신점 다시 한번 감사드립니다!

    • 루우지 2019.08.10 01:56 신고

      현재 배포중인 런처를 통해 다음 로그인을 시도해보았는데 정상적으로 동작중이네요.
      혹시 서버 URL을 건드셨나요?https://logins.daum.net/accounts/signinform.do?url=http://dho.game.daum.net/main.asp 으로 설정되어있는지 확인 부탁드리며 아래의 상태값이 어떻게 출력되는지도 확인 부탁드리겠습니다~

    • 대항대항 2019.08.11 01:33

      올려주신 링크로 바꾸고 이벤트창을 '오늘 열지않기' 로 하였더니 잘됩니다^^
      접속불가시 'game start' 부분에서 진행이 안됐었습니다. 감사드립니다~

  15. 후예 2019.09.16 17:39

    [2019-09-16 오후 5:37:48] [GameStart] : Find IFRAME
    [2019-09-16 오후 5:37:48] 80020101 오류가 발생하여 작업을 완료할 수 없습니다.

    라고 로그에 뜨면서 접속이 안되는데 이유가 뭘까요?

    • 후예 2019.09.16 17:41

      다음은 또 로그인이 되네요 ㅋㅋ; 넷마블만 안됩니다.

    • 루우지 2019.09.17 15:51 신고

      간혈적으로 일어나는 현상인가요?

  16. sangboogie 2019.09.17 15:50

    안녕하세요.

    배포해주신 대항런처 유용하게 쓰고 있어 감사의 말씀 드립니다.

    한 가지 문의드릴게 있는데요.

    다음 로그인의 경우..제가 다음 계정을 카카오계정이랑 통합시켜놔서 그런지 다음은 로그인이 안되더라구요.

    카카오계정 로그인 주소로 URL을 변경하면 런처가 먹통이되서 작동이 되질 않구요.

    카카오계정으로 통합했을 경우에는 런처 사용이 불가능한가요?

    아니면 다른 해결방법이 있는지 궁금해서 댓글남깁니다.

    항상 감사합니다.

    • 루우지 2019.09.17 15:52 신고

      카카오 계정의 로그인 기능은 추가되어있지 않습니다 추후에 추가하도록 하겠습니다

혼자 집에서 심심풀이로 만드는게 있는데 프론트에서 서버로 보내는 요청이 실패가 되는 현상이 발생했다.

 

크롬 콘솔을 보니 cross 어쩌고 저쩌고..

 

왜그런지 찾아보니 보안상의 이유로 스크랩트 내에서 HTTP요청을 SOP(Same-Origin Policy)로 막는 현상이 있었다.

 

SOP는 두 Origin간에 프로토콜, 포트, 호스트가 같아야 동일 Origin으로 간주하는데

 

예를 들어서 서버가 https://luji.tistory.com/ 주소를 사용중이고 Client에서 보내는 요청이 

1) https://luji.tistory.com/post  일 경우에는 성공

2) http://luji.tistory.com/post  일 경우에는 실패 (프로토콜이 다름 https / http)

3https://luji.tistory.com:8080/post  일 경우에는 실패(포트가 다름)

4https://www.luji.tistory.com/post  일 경우에는 실패(호스트가 다름)

 

이런 경우에 SOP정책에 의해 실패된다

 

그렇담 해결방법은 클라이언트에서 JSONP를 사용하거나 서버에서 CORS를 이용하여 해결 가능하다.

 

Spring Boot에서 CORS를 이용한 방법

1) Controller 개별 지정

@CrossOrigin
@GetMapping("/q")
String getTest(int test) throws Exception {
return testService.test(test);
}

 

2) 전역으로 지정

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
}

 

티스토리에 플러그인을 적용하지 않아서 코드가 더러운데 나는 WebConfig.java를 생성하여 addCorsMappings를 오버라이드하는 방식으로 전역파일로 따로 빼서 addMapping에 경로를 지정해서 사용중이다.





이 디스크에 Windows를 설치할 수 없습니다. 선택한 디스크가 GPT 파티션 스타일입니다.


윈도우 설치시 디스크 포맷후 해당 디스크에 윈도우를 설치할때 위의 에러가 발생할 수 있다.

당황하지 말고 아래의 방법대로 따라하면 설치 가능함!


1) Shift + F10 을 눌러 CMD창을 실행한다.


2) 이제부터는 아래의 명령어를 타이핑한다.


[1] c:

[2] diskpart

[3] list disk

 - 위 명령어를 치면 현제 disk들의 목록이 나온다. 포맷하고자하는 디스크의 번호를 선택한다.

[4] select disk 번호

[5] clean

 - DiskPart에서 디스크를 정리했습니다. <- 출력되면 성공

[6] exit (두번 쳐서 cmd창까지 종료)


3) 위의 명령어를 다 수행했으면 컴퓨터를 리부팅시키고 다시 포맷을 진행하면 된다.





IntelliJ 스프링부트 그래들로 생성하기

이번에는 IntelliJ IDE에서 Spring Boot Project를 Gradle로 생성하는 방법을 설명해보겠습니다. IntelliJ가 처음이신 분들에게 도움이 되실꺼라 생각이 되면서 저도 잊어먹지 않기 위해(정말 간단하지만..) 글로 남겨 놓을려고 합니다.





1) Create New Project 클릭





2) Spring Initializr 클릭




3) Project Metadata 설정 (Type에서 Gralde Project 선택)





4) Gradle에 추가할 디펜던시 선택







5) 임포트 설정 Gradle 




6) Gradle Build 중..



끝~

Vuex란?

Vuex는 Vue.js 애플리케이션에서 상태 관리 패턴을 지원하는 라이브러리이다. 애플리케이션 내부의 모든 컴포넌트들이 공유하는 집중화된 상태 정보 저장소 역할을 하며 상태 변경을 투명하게 할 수 있다. 각 컴포넌트가 공유하는 상태 데이터는 전역에서 저장소(store)객체를 통해서 관리한다. 이와 같은 방식으로 자식으로 또 그 자식으로 props를 이용해 속성을 계속해서 전달하지 않아도 되고 상태 데이터를 변경하기 위해 부모 콤포넌트로 이벤트를 발생시키지 않아도 된다. 


Vuex를 사용하는 이유

1. 중앙 집중화된 상태 정보 관리가 필요할때

2. 상태 정보가 변경되는 상황과 시간을 추적하고 싶을때

3. 컴포넌트에서 상태 정보를 안전하게 접근하고 싶을때

위의 그림을 보면 화살표가 한방향으로만 흘러간다. "단방향 데이터 흐름"이라는 용어를 쓰는데 전체적인 처리 흐름은 다음과 같다.


1) 컴포넌트가 액션을 일으킨다.(버튼 클릭 이벤트 같은)

2) 액션에서는 외부 API를 호출한 뒤 그 결과를 이용해 변이(mutation)을 일으킨다.

3) 변이에서는 액션의 결과를 받아 상태를 설정한다. 이단계는 추적할 수 있기 때문에 vue.js Dev Tool을 이용하면 상태 변경의 내역을 모두 확인할 수 있다.

4) 변이에 의해 변경된 상태는 다시 컴포넌트에 바인딩되어 화면을 갱신한다.


위의 그림에서 점선으로 표시된 영역이 Vuex 저장소(store) 객체 영역이다. 저장소가 상태(State:데이터), 변이(Mutation), 액션(Action)을 모두 관리한다. 저장소는 애플리케이션의 상태를 중앙집중화하여 관리한는 컨테이너이며 일반적인 전역 객체와는 달리 저장소의 상태를 직접 변경하지 않는다. 반드시 변이를 통해서반 변경한다.


주의할점은 변이의 목적은 상태의 변경이라는 것이다. 상태의 변경과 관련이 없는 작업이 변이 내부에서 수행되지 않도록 해야한다. 또한 변이는 동기적인 작업이다. 비동기 처리는 변이를 통해서 수행되지 않는다. 변이 내부에서 비동기적 처리를 수행해도 애플리케이션의 기능은정상적으로 작동될 수 있지만 사후 스냅샷을 캡쳐한 후에 나중에 상태가 변경되기 때문에 변이에 의해 데이터가 어떻게 변경되었는지를 추적할 수 없게 된다.





상태와 변이

상태(state)와 변이(muation)은 Vues 저장소(store) 내부의 핵심 요소이다. 상태는 애플리케이션에서 관리해야 할 중요한 데이터이며, 변이는 상태를 변경하는 함수들을 보유하고 있는 객체이다. 전역에서 Vue.user(Vuex) 코드의 실행으로 애플리케이션 내부의 모든 컴포넌트가 저장소의 상태, 변이 객체에 접근할 수 있다. 반드시 변이를 통해서반 변경되도록 해야한다. 



Vuex 라이브러리 다운로드

yarn add vuex 

OR 

npm install -save vuex



export default {
ADD_TODO: "addTodo",
DONE_TOGGLE: "doneToggle",
DELETE_TODO: "deleteTodo"
}

[src/Constant.js]




import Vue from 'vue';
import Vuex from 'vuex';
import Constant from '../Constant'
Vue.use(Vuex)

const store = new Vuex.Store({
state: {
todolist: [
{ todo: "영화보기", done: false },
{ todo: "주말 산책", done: true },
{ todo: "ES6 학습", done: false },
{ todo: "주말 야구장", done: false },
]
},
mutations: {
[Constant.ADD_TODO]: (state, payload) => {
if (payload.todo !== "") {
state.todolist.push({ todo: payload.todo, done: false })
}
},
[Constant.DONE_TOGGLE]: (state, payload) => {
state.todolist[payload.index].done =
!state.todolist[payload.index].done
},
[Constant.DELETE_TODO]: (state, payload) => {
if (payload.todo !== "") {
state.todolist.splice(payload.index, 1)
}
}
}
})

export default store;

[src/store/index.js]


Vuex를 전역에서 사용할 수 있도록 4행의 Vue.use(Vuex) 코드를 미리 작성해야한다. 또한 state, mutation 정보를 전달하여 Vuex.Store 객체를 생성한다. 이 예제에서는 List 컴포넌트가 보유하던 상태 데이터를 저장소가 관리하도록 했다.


"모든 컴포넌트의 상태 데이터를 Vuex로 관리할 필요는 없다"


하나의 컴포넌트 내부에서만 사용되는 상태이거나 중요하지 않은 상태이면 Vuex 저장소에 관리할 필요는 없다. Vuex가 유용한 경우는 여러 컴포넌트가 상태 데이터를 공유하는 경우이다.


변이(mutation) 객체의 메소드들은 첫번째 인자가 상태(state)이다. 두번째 인자 payload는 변이에 필요로 하는 데이터 타입이다. addTodo 작업의 경우는 todolist 데이터에 새로운 todo를 추가하기 때문에 두번재 인자 payload를 통해서 todo를 전달한다. 만약 변이를 일으킬 때 필요한 인자가 여러 개라면 payload를 객체 형태로 전달하면 된다.


이제 src/main.js를 수정해서 vue인스턴스를 생성할 때 store 객체를 전달한다. 아래의 코드를 작성하면 각 자식 컴포넌트에서 저장소(Store) 객체를 this.$store으로 접근할 수 있게된다.


import Vue from 'vue'
import TodoList from './components/TodoList.vue'
import store from './store'

Vue.config.productionTip = false

new Vue({
store,
render: h => h(TodoList)
}).$mount('#app')

[src/main.js]


이렇게 작성하면 Vuex를 사용하는 기본적인 셋팅은 끝났다. 기존에 작성한 todolist 의 list.vue 파일을 vuex를 이용하는 방법을 아래와 같이 수정하겠다.



<script tpye="text/javascript">
import Constant from '../Constant'

export default {
name: 'List',
computed: {
todolist() {
return this.$store,state.todolist
}
},
methods: {
checked: function(done) {
if (done) return {
checked: true
};
else return {
checked: false
}
},
doneToggle: function(id) {
this.$store.commit(Constant.DONE_TOGGLE, {id:id})
},
delete: function(id) {
this.$store.commit(Constant.DELETE_TODO, {id:id})
}
}
}
</script>


위의 소스를보면 List.vue 파일에는 로컬 데이터가 없다. 저장소(store) 객체가 Vue 인스턴스에 주입되었기 때문에 this.$store.state와 같이 저장소의 상태(state)에 접근할 수 있다. 이것을 속성처럼 이용할 수 있도록 하기 위해 계산형 속성(Computed Property)를 사용한다. 


화면에서 일어나는 이벤트를 받아 처리하는 메서드에서 변이(mutation)을 일으키기 위해서 this.$store.commit() 메서드를 호출한다. this.$store.commit() 메서드의 첫 번째 인자는 변이의 이름이다. 변이에 전달할 인자는 payload 인자를 이용하면 된다. 변이의 이름은 단순한 문자열이기 때문에 오타를 내기 쉽다. 그래서 위에 작성한 Constant.js와 같은 상수를 만들어 사용할 것을 권장하는 것이다.




헬퍼 메서드

이전 까지는 계산형 속성으로 this.$store.state를 직접 리턴하는 코드를 작성했고, 메서드에서도 변이를 직접 커밋하는 코드를 작성했는데 이와 같은 방법은 조금 불편한다.


이러한 불편함을 덜어주기 위해 mapState, mapMutations와 같은 컴포넌트 바인딩 헬퍼 메서드를 제공한다. 이 밖에도 mapGetters, mapActions 메서드도 있다.


<template>
<ul id="todolist">
<li v-for="a in todolist" :key="a.id" :class="checked(a.done)"
@click="doneToggle(a.id)">
<span>{{a.todo}}</span>
<span v-if="a.done">(완료)</span>
<span class="close" @click.stop="deleteTodo({id:a.id})">
&#x00D7;</span>
</li>
</ul>
</template>
<script tpye="text/javascript">
import Constant from '../Constant'
import { mapState, mapMuations } from 'vuex'

export default {
name: 'List',
computed: mapState(['todolist']),
methods: {
checked: function(done) {
if (done) return {
checked: true
};
else return {
checked: false
}
},
...mapMuations([
Constant.DELETE_TODO,
Constant.DONE.TOGGLE
])
}
}
</script>



Getter

게터는 저장소 수주느이 계산형 속성이라고 말할 수 있다. 컴포넌트에서 계산형 속성이 필수가 아니듯 게터 또한 저장소 내에서 필수로 사용하는 것ㅇ느 아니다. 하지만 적절하게 사용하면 컴포넌트에서 코드의 작성이 편리해진다. 












Action

'Vue.js' 카테고리의 다른 글

[Vue.js] Vuex를 이용한 상태 관리 (store, mutation, getter)  (0) 2018.12.23
[Vue.js] axios 서버통신  (0) 2018.12.22
[Vue.js] Vue CLI(GUI)  (0) 2018.12.18
[Vue.js] Component  (0) 2018.12.18
[Vue.js] Event 처리  (0) 2018.12.17
[Vue.js] Vue instance (뷰 인스턴스)  (0) 2018.12.16

axios를 이용한 서버통신

서버와 통신하기 위한 라이브러리는 fetch, superagent, axios 등이 있으며 Vue.js 플러그인으로 개발된 vue-resource라는것도 존재하나 Vue.js 창시자인 에반 유는 axios를 사용할 것을 권장하고 있다고 한다.


서비스 API

S네트워크 사용에 제약이 따를 경우 로컬에서 실행할 수 있는 API코드를 다운로드하여 실행하는 연락처 서비스 API이다.


다운로드 >> https://github.com/STEPANOWON/CONTACTSVC



[저수준 API]

axios(config)

axios(url, config]


[각 메서드별 별칭]

axios.get(url[, config])

axios.delete(url[, config])

axios.psot(url[, data[, config])

axios.put(url[, data[, config])

axios.head(url[, config])

axios.options(url[, config])



axios 사용법


yarn add axios 


Or


npm install --save axios






axios 프로젝트 생성



1) vue cli로 프로젝트 생성

vue create contactsapp

2) axios 추가 

yarn add axios OR npm install --save -axios

3) http proxy 설정

Vue CLI가 생성하는 프로젝트 템플릿 코드에서는 약간의 설정 파일만 작성하면 웹팩 개발서버를 이용해 프로시 서버 기능을 사용할 수 있다. 프로젝트 최상위 디렉토리에 vue.config.js파일을 생성하고 아래의 코드를 작성한다.

module.exports = {
devServer: {
proxy: {
'/api': {
target: 'http://localshot:3000',
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}


이렇게 하면 개발용 서버에 /api/contacts를 요청하게되면 http://localshot:3000/contacts로 요청일 전달 도니다.  만약 위의 서비스 API 서버를 로컬에서 실행하지 않는다면 위의 target 값을 http://sample.bmaster.kro.kr 으로 지정하면 된다.




<template>
<div id="app">
<div class="container">
<div class="form-group">
<button @click="fetchContacts">1페이지 연락처 조회</button>
</div>
<div class="form-group">
<input type="text" v-model="name"
placeholder="이름을 입력합니다"/>
<input type="text" v-model="tel"
placeholder="전화번호를 입력합니다"/>
<input type="text" v-model="address"
placeholder="주소 입력합니다"/>
<button @click="addContact">연락처 1건 추가</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<button @click="fetchContactOne">연락처 1건 조회</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<input type="text" v-model="name"
placeholder="이름을 입력합니다"/>
<input type="text" v-model="tel"
placeholder="전화번호를 입력합니다"/>
<input type="text" v-model="address"
placeholder="주소 입력합니다"/>
<button @click="updateContact">수정</button>
</div>
<div class="form-group">
<input type="text" v-model="no"/>
<input type="file" ref="photofile" name="photo"/>
<button @click="changePhoto">파일 변경</button>
</div>
</div>
<span>JSON 출력</span>
<div id="result" class="container">
<xmp> {{ result }} </xmp>
</div>
</div>
</template>

<script>
import axios from 'axios';

export default {
name : "app",
data() {
return {
no: 0,
name: '',
tel: '',
address: '',
result: null
}
},
methods : {
fetchContacts : function() {

},

addContact : function() {

},

fetchContactOne : function() {

},

updateContact : function() {

},

deleteContact : function() {

},

changePhoto : function() {

}
}
}
</script>

<style>
@import url("http://cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.css");
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osz-font-smoothing: grayscale;
text-align: center;
color : #2c3e50;
margin-top : 60px;
}

.container {
border: solid 1px gray;
padding: 10px;
margin-bottom: 10px;
text-align: left;
}

#result {
text-align: left;
padding: 20px;
border: solid 1px black;
}

.form-group {
border: dashed 1px gray;
padding: 5px 5px 5px 20px;
}
</style>

[src/AppAxiosTest.vue]




import Vue from 'vue'
//import App from './App.vue'
import App from './AppAxiosTest.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App),
}).$mount('#app')

[src/main.js]




axios 요청 방법

axios 저수준 API를 이용하는 예제이다. 아래의 코드를 fetchContact메서드에 작성한다.


fetchContacts : function() {
axios({
method: 'GET',
url : '/api/contacts',
params : {
page : 1,
pagesize : 5
}
}).then((response) => {
console.log(response);
this.result = response.data;
}).catch((ex)=> {
console.log("ERR!!!!! : ", ex)
})
},

[ 저수준 axios 메소드 작성법 ]



axios 저수준 메서드의 특징은 모든 전달값을 config 객체로 전달한다는 특징이 있다. Promise 객체는 요청이 성공적이라면 then이 호출되며 요청이 실패하면 catch가 호출된다. 저수준 메서드가 아닌 별칭 메서드 get을 이용하여 fetchContactOne을 작성하겠다.



fetchContactOne : function() {
axios.get('/api/contacts/' + this.no)
.then((response) => {
console.warn(response);
this.result = response.data
})
},

[GET]



POST 메서드에서는 주로 axios.post(url, data, config) 형태를 주로 사용한다. 다음은 addContact 에 POST를 이용해 작성해본 코드이다.



addContact : function() {
axios.post('/api/contacts',
{ name:this.name, tel:this.tel, address:this.address }
).then(response => {
console.warn(response)
this.result = response.data
this.no = response.data.no
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[POST]



updateContact : function() {
axios.put('/api/contacts/' + this.no,
{ name:this.name, tel:this.tel, address:this.address }
).then(response => {
console.warn(response)
this.name = '';
this.tel = '';
this.address = '';
this.result = response.data
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[PUT]



deleteContact : function() {
axios.delete('/api/contacts/' + this.no)
.then(response => {
console.warn(response)
this.result = response.data
}).catch((ex) => {
console.warn("ERROR!!!!! : ",ex)
})
},

[DELETE]



파일 업로드 기능도 axios로 구현하기 위해서는 위에 작성한 <input tpye="file" ../> 필드를 직접 참조해야한다. 해당 태그에 보면 ref="photofile" 이라고 ref 옵션을 사용한걸 볼 수 있다. 


changePhoto : function() {
var data = new FormData();
var file = this.$ref.photofile.files[0]
data.append('photo', file)

axios.post('/api/contacts' + this.no + '/photo', data)
.then(response => {
console.warn(response)
this.result = response.data
this.no = response.data.no
}).catch((ex) => {
console.warn("ERROR!!!!! : ", ex)
})
}

[File 전송]



FormData 객체를 생성하고 this.$ref.photofile과 같이 ref 옵션을 이용해 파일 필드를 직접 참조할 수 있다. 이 필드의 값을 FormData 객체에 추가한뒤 서버로 요청하게 된다.




Vue Instance 내부에서 axios 이용하기

Vue 인스턴스 내부에서 axios를 이용하기 위해 Vue.prototype에 axios를 추가하면 간단하게 사용 할 수있다. main.js에 아래의 내용을 추가한다.


import Vue from 'vue'
//import App from './App.vue'
import App from './AppAxiosTest.vue'
import axios from '.axios'

Vue.prototype.$axios = axios;
Vue.config.productionTip = false

new Vue({
render: h => h(App),
}).$mount('#app')

[src/main.js]


이렇게 작상하면 Vue 인스턴스 내부에서는 axios를 따로 improt하지 않아도 this.$axios를 이용해서 사용할 수 있다. AppAxiosTest.vue 파일의 fetchContactone 메서드는 아래와 같이 변경할 수 있다.


fetchContactOne : function() {
this.$axios.get('/api/contacts/' + this.no)
.then((response) => {
this.result = response.data
})
},




axios 사용 시 주의 사항

axios를 사용하면서 then() 처리를 할 때는 ECMAScript6의 화살표 함수를 사용할 것을 권장한다. 데이터를 수신한 후에 Vue 인스턴스 내부의 데이터를 변경해야 하는 경우가 있는데 데이터 옵션을 액세스하기 위해서는 this 객체가 Vue인스턴스를 참조할 수 있어야 한다. then() 내부에서 화살표 함수를 하용하지 않으면 this가 vue 인스턴스를 참조하지 않기 때문에 밖에서 별도의 변수에 this를 할당한 후에 클로저 방식으로 접근해야 하는 불편함이 발생한다. 

















'Vue.js' 카테고리의 다른 글

[Vue.js] Vuex를 이용한 상태 관리 (store, mutation, getter)  (0) 2018.12.23
[Vue.js] axios 서버통신  (0) 2018.12.22
[Vue.js] Vue CLI(GUI)  (0) 2018.12.18
[Vue.js] Component  (0) 2018.12.18
[Vue.js] Event 처리  (0) 2018.12.17
[Vue.js] Vue instance (뷰 인스턴스)  (0) 2018.12.16

Vue CLI

Vue CLI는 Vue.js 애플리케이션을 빠르게 개발할 수 있는  관련된 기능을 모두 제공하는 Vue.js 개발 도구이자 시스템이다. 개발자들에게 표준화된 개발의 기준선을 제공하고 정해진 틀 속에서 개발이 가능하면서도 기본 제공되거나 제 3자가 제공하는 다양한 플러그인과 프리셋을 로딩하여 프로젝트의 초기 설정과 개발을 손쉽게 할 수 있도록 도와준다. 따라서 개발자가 프로젝트 구성을 설정하는데 드는 노력을 줄이고 개발에 좀더 집중할 수 있도록한다.






1. Vue CLI 구성요소

1) CLI : @vue/cli

컴퓨터 내부 어디에서나 실행할 수 있도록 npm을 이용해 전역에 설치하며 터미널창에서 vue 명령어를 실행할 수있도록 한다. vue 명령어로 수행할 수 있는 기능은 다음과 같다.


- 새로운 Vue 애플리케이션 프로젝트를 생성할 수 있음

- vue 단일 파일 컴포넌트를 설정 없이 실행하여 테스트할 수 있음

- GUI 환경으로 프로젝트를 생성하거나 관리할 수 있음



2) CLI : @vue/cli-service

CLI 서비스는 프로젝트가 생성될 때 개발 의존성으로 설치되는 구성요소이다. CLI 서비스의 내부는 웹펙(webpack)과 웹팩 개발 서버(webpack-dev-server) 기반으로 작성되어 있다. CLI 서비스를 이용해 수행할 수 있는 기능은 다음과 같다


- 프로젝트를 웹팩 개발 서버 기반으로 구동 가능

- 프로젝트 소스코드를 리소스를 빌드하고 번들링할 수 있음

- 프로젝트의 코드를 테스트할 수 있음



3) CLI 플러그인

CLI 플러그인은 Vue CLI로 생성된 프로젝트 추가적인 기능을 제공하는 npm 패키지이다. CLI도구를 이용해 프로젝트를 생성할 때 추가할 플러그인을 선택할 수 있으며, 프로젝트가 생성된 이후에도 vue add 명령어를 이용해 플러그인을 추가할 수 있다. 또한 CLI 플러그인은 기본적으로 제공되는 것도 있지만 누구나 플러그인을 만들어 제공할 수 있다.


대표적인 CLI 플러그인 

router

vuex

vue-cli-plugin-vuetify



Vue CLI를 설치하기 위해서 npm 패키지 매니저를 이용해 전역 수준으로 설치한다.


npm install -g @vue/cli (windows)

sudo npm install -g @vue/cli (mac)





2. 프로젝트 생성과 기본 사용법

Vue CLI를 이용해 프로젝트를 생성할 때는 vue create 명령어를 사용한다.


vue create [프로젝트명]


vue create 명령어로 프로젝트를 생성할 때 몇 단계릐 절차를 거친다. 첫 단계는 프리셋을 포함하는 단계이다. default로 하면 babel, eslint 프러그인만 포함된다. 


(생성 화면)


프리셋과 플러그인을 선택하는 질문들이 나온다 알아서 셋팅해주고 마무리하면 된다.


(CLI로 프로젝트를 생성 완료한 모습)





생성한 프로젝트의 구조를 VSCode로 실행해보면 위의 사진과 같다.


src : 개발자가 작성하는 소스 코드를 배치하는 디렉터리

assets -> 여러가지 자원 정보들이 저장되는곳, 이 디렉터리에 저장한 파일을 Vue 캠포넌트에서 사용하는 경우 빌드 과정에서 자원으로 인식되어 배포버전을 만들어낼때 함께 배포된다.

components -> Vue 컴포넌트를 작성하기 위한 디렉터리. 하지만 꼭 Vue 컴포넌트가 이 디렉토리로만 들어가는것은 아니다.


public : 배포 버전을 빌드할 때 필요한 파일


node_modules : app 개발과 배포에 필요한 npm 패키지들이 저장되는 디렉터리


dist : 작성한 앱 코드를 빌드하여 만든 배포 버 저장하는 디렉터리. Vue 컴포넌트들은 모두 js 파일로 트랜스파일되어 몇 개의 js 파일로 번들링되고 난독화하여 저장한다.





vue-cli-service는 vue CLI 설치 시에 프로젝트 단위로 설치되느니 실행 명령어이다. vue-cli-service의 사용 방법은 다음과 같다.


vue-cli-service [command] [options]

command 

1) serve : 웹팩 개발 서버를 이용해 프로젝트 코드를 실행한다.실행 도중 소스코드가 변경되고 저장되면 즉시 브라우져에 화면이 반영된다.

2) build : 빌드하여 배포 버전의 소스 코드를 새엉하여 지정 디렉터리에 저장한다. 빌드된 버전의 코드가 저장되는 기본 경로는 dist 디렉터리이다.

3) lint : eslint 기능을 이용해 코드의 표준화되지 않은 부분을 검사하고 교정한다.

4) inspect 현재 프로젝트의 웹팩 설정 정보를 보여준다.


option

1) --open : 서버 시작시 브라우져가 같이 실행

2) --copy : 서버 시작시 URL 주소가 클립보드에 복사

3) --host : 호스트 주소 설정 (default : 0.0.0.0 localhost)

4) --port :  포트 설정 (default : 8080)

etc..


만일 개발 서버를 구동하면서 웹 브라우져를 자동으로 열고 싶다면 --open 옵션을 추가해주면된다. package.json 파일의 script 옵션에 server 값을 다음과 같이 변경하면 npm run serve만으로도 간단히 실행할 수 있다.

"name": "test1",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve --open --port 3000",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},

(프로젝트 내부의 package.json의 script 부분)


이제 실행을 해보자. vs

VSCode의 터미널에 npm run serve 입력


(정상 실행된모습)

자동으로 웹브라우져가 실행되면서 결과가 나오면 성공적이다.




3. 플러그인

Vue CLI를 이용해 생성한 프로젝트는 크게 서비스와 플러그인으로 구성되어 있다. 서비스는 하나이지만 플러그인은 여러 개를 선택할 수있다. 대부분의 플러그인들의 이름은 @vue/cli-plugin으로 시작한다. 플러그인을 이용하면 프로젝트의 웹팩 구성을 변경하고 명령이나 기능을 추가한느 작업을 선택적으로 할 수 있다.


Vue.CLI의 기본 프리셋으로 프로젝트를 생성하면 @Vue/cli-plugin-babel, @Vue/cli-plugin-eslint의 두 가지 플러그인이 설치된다. 추가하고 싶은 플러그인 이있다면 다음의 명령어로 추가하면된다


vue add [플러그인]


채표적인 플러그인중 하나인 vuex, rotuer를 설치해보자 


vue add router



이제 다시 npm run serve를 실행하여 정상적으로 설치되었는지 확인해보자



home과 about 페이지가 정상적으로 동작한다. 




3. vue.config.js

vue CLI의 내부는 웹팩이라는 모듈 번들러 도구를 이용하도록 만들어져있다. 하지만 CLI 서비스는 모두 캡슐화되어 있기 때문에 내부의 웹펙에 대해 웹펙 설정 파일을 이용해 직접 설정할 수 없다. 대신 웹팩 설정을 위해 vue.config.js라는 파일을 프로젝트 내부에 작성한다.


나중에 axios를 이용한 http 통신을 할때 웹팩 개발 서버의 proxy를 설정하기 위해 여기를 수정할 것 이다.




4. Vue CLI GUI 도구

Vue CLI는 명령창이나 터미널 창을 이용해 프로젝트를 생성하고 관리할 수 있지만 브라우져를 통해

GUI 도구를 이용할 수 있다.


프로젝트를 생성하기 위한 기본 디렉터리를 하나 만들고 명령창이나 터미널을 열어 해당 디렉토리로 이동한다. 그리고 나서 vue ui 명령어를 실행하면 아래와 같은 화면이 뜰껏이다.


(VSCode 터미널에서 폴더 생성후 vue ui 실행한 모습)



(실행하면 웹브라우져가 구동된다)




(하단의 새 프로젝트를 만들어보세요 클릭)



(폴더와 프로젝트명 설정후 다음버튼 클릭)



(기본 디폴트 프리셋 선택후 프로젝트 만들기 클릭)


(Vue Project가 대쉬보드 형태로 확인할 수 있다. 작업 목록 클릭)





(Serve 선택후 시작을 누르면 애플리케이션이 구동된다)


스크린샷에서 보이는것처럼 단순히 실행만 할 수 있는게 아니라 각종 통계정보가 같이 나온다.








'Vue.js' 카테고리의 다른 글

[Vue.js] Vuex를 이용한 상태 관리 (store, mutation, getter)  (0) 2018.12.23
[Vue.js] axios 서버통신  (0) 2018.12.22
[Vue.js] Vue CLI(GUI)  (0) 2018.12.18
[Vue.js] Component  (0) 2018.12.18
[Vue.js] Event 처리  (0) 2018.12.17
[Vue.js] Vue instance (뷰 인스턴스)  (0) 2018.12.16

+ Recent posts