Typescript로 VueJS 프로젝트를 사용하는 방법을 알아봅니다.

Why Typescript?

왜 Typescript를 사용하느냐? 는 질문은, Typescript의 장점에 대해 구글링 해보면 많이 나오니, 두줄 정도로만 작성하겠습니다.

  • 자동완성을 통한 생산성 향상
  • 컴파일 레벨에서의 타입오류 검출로 인한 생산성 향상

물론, Typescript를 사용하면, 문법이 좀 더 장황해져서 타이핑이 늘어난다는 단점이 있겠으나, 위의 장점들이 이를 상쇄한다고 생각합니다.
Typescript를 사용하는 이유에 대해서는 훌륭한 글들이 많으니 참고하시면 좋을 것 같습니다.

사전 준비

pc 또는 mac에 nodejs와 npm이 설치 되어 있다는 전제 하에 진행합니다.

vue-cli 2 버전대에서는 Typescript를 지원하지 않았지만, 3버전대로 업그레이드 되면서, Typescript를 공식적으로 지원하기 시작했습니다.

기존에는 프로젝트 생성 후 수동으로 Typescript에 맞게 꾸며야만 했으나, vue cli 3 버전부터는 프로젝트 생성 시 옵션을 통하여 Typescript를 선택할 수 있어 많이 편해졌습니다.

터미널 (또는 CMD)창을 열어 아래 명령어를 입력하여 vue-cli를 설치 해 줍니다.

1
npm install -g @vue/cli

이제 간단히 vue cli 설치가 끝났습니다.

npm을 대신할 패키지 매니저 yarn도 설치 해줍니다.
(npm을 사용하실 분들은 설치하지 않으셔도 됩니다.)

1
npm install -g yarn

이제 콘솔에서 vue 명령어를 통해 vue cli를 호출할 수 있습니다.

1
vue --version

글 작성 시점의 최신 버전은 3.2.1이네요.

vue cli를 통해 프로젝트 생성

vue-cli를 통해 프로젝트를 생성하는것은 아주 쉽습니다.

터미널을 열고

1
vue ui

를 입력하여 브라우저를 통한 gui화면을 통해 뷰 프로젝트를 생성하고 관리할 수도 있습니다.

그러나, 터미널이 더 편한 개발자들도 많을 것 같습니다.
(속도도 더 빠르구요..)

1
vue create test-typescript-project

터미널에서 위 명령어를 입력합니다.

default(babel, eslint) 와 Manually select features 를 선택할 수 있습니다. 우리는 typescript를 사용할 것이기 때문에 Manually select features를 선택합니다.

선택한 후 프로젝트 구성에 맞는 옵션을 선택 합니다.

이번 샘플 프로젝트에서는 Babel, Typescript, Router, Vuex, CSS Pre-processors, Linter/Formatter만 선택하고 진행합니다.
(Unit Test나 E2E Testing은 제외합니다. 언제든 추후에 추가할 수 있습니다.)

babel은 js를 컴파일 하기 위한 녀석이라고 보면 되고, 두번째, Typescript가 핵심입니다.

Router는 라우팅 경로를 컨트롤하기 위한 vue 플러그인, Vuex는 상태관리를 위한 vue 플러그인이고,

CSS Pre-processors는 SCSS를 사용하기 위함, Linter/Formatter는 문법 검사 하는 녀석이라고 생각하면 됩니다. (더이상의 자세한 설명은 생략한다)

옵션들을 선택하고 Enter를 누르면, 아래와 같은 질문을 만나게 됩니다.

아래 첨부한 그림과 같이 선택해 줍니다.

모두 선택 한 후 또다시 Enter!!!

조금 기다린 후에, 아래와 같이 프로젝트가 완성 되었다는 메세지를 만날 수 있습니다.

터미널 하단에 성공적으로 프로젝트가 생성되었다는 메세지와 함께, 테스트 해볼 수 있는 명령어를 예시로 들어줍니다.

터미널에 그대로 입력해 봅니다.
로컬 개발 서버가 구동됩니다.

1
2
cd test-typescript-project
yarn serve

성공적으로 컴파일 되었다는 메세지와 함께
브라우저로 개발서버에 접속해 볼 수 있는 주소가 표시됩니다.

잘 작동되는것을 확인해 볼 수 있습니다.

다음 포스트에서는 대략적인 폴더 구조와 컴포넌트 구성을 해보겠습니다.
감사합니다.

Comment and share

Message broker

요즘 회사에서 새로운 시스템이 개발될 때, 레거시 시스템과의 연동이 많아지면서 Message broker 도입의 필요성에 대해 이야기 하고 있습니다. (조금 늦었지만..)

메세지 브로커 선택 시 어떤 브로커를 선택 하느냐 또한 중요한데요, 하자면 저희 회사에서는 Amazon MQ를 선택하게 되었습니다.

Amazon MQ는 지난 2018년7월부터 서울 리전에서도 사용 가능한 AWS 서비스 중 하나인데요, 내부적으로는 Apache Active MQ를 사용하도록 구성되어있습니다.

-Amazon MQ 장점

-구성이 쉽다 (유지보수 쉬움)

-가용성 (failover 지원)

-준수한 성능(22k건/초) (은 딱히 장점은 아닌듯 합니다)

-Amazon MQ 단점

-Rabbit MQ나 Apache Kafka에 비해서 상대적으로 떨어지는 인지도(레퍼런스가 덜 풍부함)

-Spring-cloud-stream 을 바로 사용할수 없음

서비스 선택 시 상세한 고려 사항은 https://stackshare.io/stackups/activemq-vs-kafka-vs-rabbitmq를 참고하셔도 됩니다.

Amazon MQ 선택시 마지막까지 고민하게 만들었던 부분은 spring-cloud-stream을 사용하여 구현할 수 없다는 점이었는데요, Spring-cloud-stream
을 사용하여 서비스를 구현하면 간단한 어노테이션 추가만으로도 구현이 가능했던 점이 아주 큰 장점이었거든요.

But, 찾아보니 Amazon MQ도 비슷한 난이도로 구현할 수 있는 방법이 있어 이를 구현하는 방법을 정리 차원에서 작성하고자 합니다. start!


Amazon console에서 Active MQ를 설정하는 방법은 건너뛰도록 하겠습니다.

  1. spring boot을 사용하여 Project를 생성

저는 spring-boot-devtools 정도만 추가 했습니다.(필요에 따라서는 lombok등도 추가 해주시면 됩니다..)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.2</version>
<scope>provided</scope>
</dependency>
  1. Maven pom.xml에 디펜던시 추가

activemq 관련 디펜던시를 추가해줍니다.

1
2
3
4
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-activemq</artifactId>
</dependency>
  1. application.properties에 설청값 셋팅
1
2
3
spring.activemq.broker-url=<broker-url>
spring.activemq.user=<user id>
spring.activemq.password=<password>
  1. 전달할 메세지 형태 클래스 Message.java를 추가 합니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.io.Serializable;

public class Message implements Serializable {

private static final long serialVersionUID = -1163890830946122942L;

private String id;
private String name;

public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
  1. 메세지를 생성해서 MQ에 보낼 producer 클래스와 소비하게 될 consumer 클래스를 추가 합니다.

Consumer.java

1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.jms.annotation.JmsListener;
import org.springframework.stereotype.Component;

@Component
public class Consumer {

@JmsListener(destination = "sample.queue")
public void receiveQueue(Message message) {
System.out.println(message.getId() + ", "+ message.getName());
}

}

Producer.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import javax.jms.Queue;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Component;

@Component
public class Producer {

@Autowired
private JmsMessagingTemplate jmsMessagingTemplate;

@Autowired
private Queue queue;

public void send(Message message) {
jmsMessagingTemplate.convertAndSend(queue, message);
}

}
  1. @SpringBootApplication클래스에 Bean 추가
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootApplication
public class JmstestApplication {

@Bean
public Queue queue() {
return new ActiveMQQueue("sample.queue");
}

public static void main(String[] args) {
SpringApplication.run(JmstestApplication.class, args);
}
}


  1. 마지막으로 test class를 작성 해줍니다.

    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
    import org.junit.Rule;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import org.springframework.boot.test.rule.OutputCapture;
    import org.springframework.test.context.junit4.SpringRunner;

    import static org.assertj.core.api.Assertions.assertThat;

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class JmstestApplicationTests {

    @Rule
    public OutputCapture outputCapture = new OutputCapture();

    @Autowired
    private Producer producer;

    @Test
    public void sendSimpleMessage() throws InterruptedException {

    //given
    Message msg = new Message();
    msg.setId("1");
    msg.setName("a message from JH");

    //when
    producer.send(msg);


    //then
    Thread.sleep(1000L);
    assertThat(outputCapture.toString().contains("1, a message from JH")).isTrue();
    }

    }
  2. 테스트 클래스를 실행해봅시다. 실행 전에 실행 환경 변수에 SERIALIZABLE_PACKAGES 설정값을 추가 해 주어야
    오류 메세지를 만나지 않고 pojo를 전송하고 받을 수 있게 됩니다. 보안 상 신뢰할 수 있는 패키지를 환경설정값에 넣어야만 하도록 되어있기 때문입니다.

    1
    -Dorg.apache.activemq.SERIALIZABLE_PACKAGES="<패키지 경로>"
  3. 테스트 클래스 실행 결과

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    . ____ _ __ _ _
    /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
    \\/ ___)| |_)| | | | | || (_| | ) ) ) )
    ' |____| .__|_| |_|_| |_\__, | / / / /
    =========|_|==============|___/=/_/_/_/
    :: Spring Boot :: (v2.0.5.RELEASE)

    2018-10-14 16:33:24.224 INFO 54635 --- [ main] c..jmstest.JmstestApplicationTests : Starting JmstestApplicationTests on TF-Mac-023ui-MacBook-Pro.local with PID 54635 (started by jeonghunKim in /Users/tf-mac-023/IdeaProjects/jmstest)
    2018-10-14 16:33:24.226 INFO 54635 --- [ main] c..jmstest.JmstestApplicationTests : No active profile set, falling back to default profiles: default
    2018-10-14 16:33:24.387 INFO 54635 --- [ main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6c1a5b54: startup date [Sun Oct 14 16:33:24 KST 2018]; root of context hierarchy
    2018-10-14 16:33:26.012 INFO 54635 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 2147483647
    2018-10-14 16:33:27.233 INFO 54635 --- [ActiveMQ Task-1] o.a.a.t.failover.FailoverTransport : Successfully connected to ssl://
    2018-10-14 16:33:27.350 INFO 54635 --- [ main] c..jmstest.JmstestApplicationTests : Started JmstestApplicationTests in 3.996 seconds (JVM running for 6.586)
    2018-10-14 16:33:27.600 INFO 54635 --- [ActiveMQ Task-1] o.a.a.t.failover.FailoverTransport : Successfully connected to ssl://
    1, a message from JH
    2018-10-14 16:33:28.961 INFO 54635 --- [ Thread-5] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6c1a5b54: startup date [Sun Oct 14 16:33:24 KST 2018]; root of context hierarchy
    2018-10-14 16:33:28.962 INFO 54635 --- [ Thread-5] o.s.c.support.DefaultLifecycleProcessor : Stopping beans in phase 2147483647

    Process finished with exit code 0

Comment and share

  • page 1 of 1

shockshot@naver.com

author.bio


author.job