티스토리 뷰

현재 프론트엔드 프로젝트 구조

이미 내가 라우터를 추가한 후에 프로젝트 구조이다.

  • assets : .css나 .png 같은 UI 관련 리소스들이 들어간다.
  • components : 여기에 바로 화면 내부에 들어갈 html 템플릿과 vue.js 함수들이 들어간다.
  • router : vue.js의 라우팅 정보가 들어간다.
  • main.js : 이 Vue 앱을 초기화 시키는 자바스크립트이다.
  • App.vue : 이 앱의 기본(디폴트) 템플릿이라고 생각하면 된다.
  • index.js : vue-router를 이용해 경로를 설정하는 자바스크립트이다.
  • Todo.vue : ToDoItem 관련 로직을 넣을 컴포넌트이다.

 

컴포넌트는 Vue.js에서 재사용 할 수 있는 단위이다. html 페이지 하나를 컴포넌트 하나라고 생각하면 쉽다.

 

  • Todo.vue
<template>
  <div class="todo">
    오늘 해야 할  일
    {{toDoItems}}
  </div>
</template>

<script>
export default{
  name: 'todo-items',
  data: () => {
    return{
      toDoItems: ['1. 밥 먹기', '2. 잠 자기']
    }
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2{
  font-weight: normal;
}
/* h3 {
  margin: 40px 0 0;
} */
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #35495E;
}
</style>

위 코드 결과

 

라우터는 경로를 설정해주는 역할을 한다.

브라우저에서 보면 /products, /contacts 같이 슬래시를 사용해 경로를 지정해줄 수 있다.

vue-router라는 패키지를 이용해 손쉽게 라우팅 할 수 있다.

 

이 작업을 스프링 부트와 비교하자면 @RequestMapping(value = "/todo")를 해줬던 작업과 비슷하다. 스프링에서는 해당 경로로 리퀘스트가 들어오면 어떤 함수를 실행시켰는데 마찬가지로 라우터도 해당 경로로 누군가 접근하면 그 경로에 필요한 컴포넌트를 이어줄 것이다.

 

  • router/index.js
    여기서 잠깐! vue2와 vue3에서의 라우터 사용 방법이 다르다.
    나는 3에 맞게 바꿔주었다.
// 경로 설정을 원하는 컴포넌트를 import 한다.
import Todo from '@/components/Todo'
// import { transformVNodeArgs } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router'

// 실제 경로 설정
// 아래 path부터 차례대로 설명
// http://localhost:8080/ 으로 누가 들어오면
// 위 경로에 ToDo 라는 이름 붙이고
// ToDo.vue 라는 컴포넌트를 이어줘라 <router-view></router-view>에 
const routes = [
    {
        path: '/',
        name: 'Todo',
        component: Todo
    },    
]

export const router = createRouter({
    history: createWebHashHistory(process.env.BASE_URL),
    routes
})

export default router

 

  • App.vue
<template>
  <!-- <img alt="Vue logo" src="./assets/logo.png"> -->
  <!-- <HelloWorld msg="Welcome to To Do Demo App"/> -->
  <div id="App">
    <header>
      <span>To Do List</span>
    </header>
    <main>
      <router-view></router-view>
    </main>
  </div>
</template>

<script>

export default {
  name: 'App'
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

 

  • main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'

createApp(App).use(router).mount('#app')

이렇게 하면 

결과가 뜬다.

index.js에서 컴포넌트를 부르고 http://localhost:8080/으로 호출하면 그 컴포넌트로 라우팅 해준다.

App.vue에서 <router-view><router-view/>를 써서 해당 컴포넌트를 부른다.

 

이런 흐름을 확인하기 위해서 About.vue를 하나 더 만들어보겠다.

 

  • About.vue
<template>
    <div class="about">
        {{msg}}
    </div>
</template>

<script>
export default{
    name: 'about-app',
    data: () => {
        return {
            msg: '개발 중인 To Do 어플입니다.'
        }
    }
}
</script>

<style>
h1, h2{
    font-weight: normal;
}

ul{
    list-style-type: none;
    padding: 0;
}

li{
    display: inline-block;
    margin: 0 10px;
}

a{
    color: #35495E;
}
</style>

원래는 export default에서 name을 about으로 했는데, eslint를 써서 자꾸 에러가 났다.

about-app으로 해결완료

컴포넌트를 만들어주고 index.js에서 라우팅 해주면 된다.

 

이제 라우터 쓰는 흐름은 어느 정도 익혔다.

 

Axios을 이용해 API 콜 하기

이제 Axios라는 것을 이용해서 스프링 부트의 API 콜을 해본다.

 

Axios 설치

실행 중인 to-do-frontend 앱을 종료하고 터미널을 이용해 to-do-frontend 앱의 프로젝트 디렉토리로 들어간다.

나는 npm run serve로 실행해서 ide terminal에서 ctrl+C를 이용해 프로젝트 종료 후 mac terminal에서 디렉토리로 들어갔다.

프로젝트 디렉토리에서 패키지 설치

이후 다시 프로젝트를 실행한다.

그 다음 스프링 부트 앱도 실행시켜야 하는데 둘 다 8080 포트로 실행을 하도록 되어있기 때문에 포트가 겹치는 문제가 발생할 것이다. 그래서 스프링 부트 앱의 포트를 임의로 변경해준다.

8081으로 변경해준 후 실행하면 된다.(나중에는 이 스프링부트 앱을 도커로 실행시켜봐야겠다.)

 

Todo.vue에서 GET API Call하기

이제 to-do-frontend 앱에서 Todo.vue를 수정해보겠다.

 

  • Todo.vue
<template>
  <div class="todo">
    오늘 해야 할  일
    <ul v-if="todoItems && todoItems.length">
      <li v-for="todoItem of todoItems" v-bind:key="todoItem.id">
        {{todoItem.title}}
      </li>
    </ul>
  </div>
</template>

<script>
import axios from 'axios'

export default{
  name: 'todo-items',
  data: () => {
    return{
      todoItems: [] //toDoItems를 빈 리스트로 초기화
    }
  },
  created () {
    axios.get('http://127.0.0.1:8081/todo/') //http://localhost:8081/todo/ get call
    .then(response => {
      this.todoItems = response.data.map(r => r.data)
    })
    .catch(e => {
      console.log('get call 도중 error : ', e) //에러가 나는 경우 콘솔 출력
    })
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2{
  font-weight: normal;
}
/* h3 {
  margin: 40px 0 0;
} */
ul {
  list-style-type: none;
  padding: 0;
}
li {
  display: inline-block;
  margin: 0 10px;
}
a {
  color: #35495E;
}
</style>

설명을 해보자면, 먼저 response인 toDoItems 리스트를 초기화해주고, http 콜을 통해 data를 얻은 것을 toDoItems에 매핑한다.

에러가 생기면 에러를 콘솔에 출력하도록 한다.

toDoItems는 위 템플릿에서 v-if를 통해 만약 존재하고 길이가 있으면 v-for을 통해 toDoItems를 toDoItem으로 넘겨받아 제목을 하나씩 리스트로 출력한다.(그리고 v-for 쓰러면 key 값이 필요하다고 에러나서 v-bind:key 추가해줬다.)

 

이렇게 하면 제대로 되어야 할 것 같지만 실상은 에러난다.

바로 CORS!!!

CORS(Cross Origin Resource Sharing)

보안을 위해 만들어진 정책

스프링 부트 어플리케이션 도메인이 다른 어플리케이션으로부터의 요청을 거부했다는 뜻이다.

즉, localhost:8080 -> localhost:8081/todo/로 접근해 요청하는데 도메인(포트)가 다르기 때문에 보안상 이를 허락하지 않는다는 뜻이다.

 

이를 해결하기 위해서 스프링 부트에서 설정을 해주겠다.

 

  • config/WebConfig.java
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry){
        registry.addMapping("/**")
                .allowedOrigins("http://127.0.0.1:8080")
                .allowedOrigins("http://localhost:8080");
    }
}

위 코드를 보면 해당 url들은 요청이 들어오면 허락하겠다고 하는 설정을 한 것이다.

어플리케이션을 재실행한다.

제대로 나온다. 저 영어는 내가 이전에 만들어놓은 아이템 제목이다.

리스트 목록을 보고자 하나 더 넣어보겠다.

postman으로 POST 해서 데이터 하나 더 넣는다.

 

li 썼는데 왜 수평으로 뜨지..? 이거는 나중에 해결해보겠다.

어쨌든 이렇게 하면 일단은 끝이다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/04   »
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
글 보관함