IT/development

[Vue.js] ajax로 데이터 조회 예제(feat. axios)

알 수 없는 사용자 2023. 7. 23. 16:19
반응형

Vue.js에서 ajax로 서버에서 데이터 받아와서 테이블에 뿌리는 간단한 예제

cli 환경 기반이라 npm install로 vue.js cli를 설치해야 함(미리 설치한 상태라 동영상에는 설치과정 누락됨)

 npm install -g @vue/cli

cli 설치 후 vue create 프로젝트명으로 cli 기반 vue 프로젝트 생성

vue create vue-test1(생성할 프로젝트명)

아래 명령어로 node.js 런타임을 실행해서 페이지를 띄움

npm run serve

페이지를 띄운 순간부터 vue.js는 데이터가 변경되는 순간 실시간으로 반영한다.

mounted(DOM 그린 다음 실행되는 함수) 부분에 console.log() 찍어보면 렌더링을 다시 하는게 보인다.

(이놈도 React처럼 가상 DOM을 만들어서 변경된 부분만 다시 렌더링한다고 함)

반영되는게 매우 부드럽다.

소스코드(App.vue)

<!-- 화면 관련 코드는 이곳에 -->
<template>
  
  <h2>vue.js test</h2>

  <table>  
    <thead>
      <th>번호</th>
      <th>제목</th>
      <th>내용</th>
      <th>작성자</th>
      <th>등록일</th>
    </thead>    
    <!-- 서버에서 받아온 데이터인 result가 있으면 for문 돌려서 그림(:key는 반드시 설정해줘야 함) -->
    <tbody v-if="result.length > 0">
      <tr v-for="item in result" :key="item.no">
        <td>{{ item.no }}</td>
        <td>{{ item.title }}</td>
        <td>{{ item.content }}</td>
        <td>{{ item.userId }}</td>  
        <td>{{ item.regDate }}</td>
      </tr>   
    </tbody>
    <!-- 데이터가 없으면 데이터 없음 표시 -->
    <tbody v-else>
      <tr>
        <td colspan="6"><strong>데이터가 없습니다.</strong></td>
      </tr>
    </tbody>
  </table>

</template>



<!-- script 관련 코드는 이곳에 -->
<script>
// ajax 통신하기 위한 lib import
import axios from 'axios';

export default {
  name: 'App',
  //데이터는 다 여기서 세팅(state)
  data() {
    return {
      result: [], //ajax에서 데이터 받아와서 저장할 array
    }
  },  
  //DOM 로드 후 데이터 받아오도록 설정
  mounted: function() {
      axios.get ('http://localhost:9090/api/board') //게시글 조회하는 간단한 api(springBoot로 tomcat을 이미 띄워 놓은 상태)
        .then(response => {
          //ajax로 가져온 데이터를 this.result에 치환(vue.js에서 this는 Vue 인스턴스 자체를 의미함(new Vue({...})로 만든 인스턴스), this를 붙이지 않으면 인스턴스의 object를 찾지 못함)
          this.result = response.data.list;
        console.log(response.data.list);
      })    
        .catch(error => { 
        console.log(error);//주석할 경우 에러 발생(error을 가져왔는데 사용하지 않았다는..에러)
      })
    console.log("page load"); //화면 재 렌더링 할 때마다 로그 찍힘
  },    
  //컴포넌트 사용할 경우 이곳에 작성
  components: {
  }
}
</script>

<!-- css 관련 코드는 이곳에 -->
<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
}
</style>

아직 Vue.js 입문 단계라 공부할게 더 많긴 하지만 느낀점은 실시간 렌더링이라 그런지 기존에 template engine인 thymeleaf와 javascript로 페이지 그리는 것보다 코드가 많이 깔끔하다.

그리고 import한 자원(lib, component 등)을 사용하지 않을 경우 'import한 자원' is defined but never used

이런식으로 에러가 발생한다.

※ 최초 서버에 API 호출 시 CORS(Cross-Origin Resource Sharing)에러가 발생한다.

서버에서는 상태코드 200으로 정상적으로 데이터를 return 했지만 브라우저에서 에러가 발생한다.

보안상 이유로 페이지가 로드된 출처 외에 다른 출처의 리소스에 접근하는 걸 브라우저가 막는 정책이라고 함

브라우저가 출처를 구분하는 건 3가지(프로토콜, 호스트, 포트)이고 1개라도 다르면 다른 출처로 인식한다.

내 경우는 localhost:8080에서 페이지를 호출 했기 때문에 localhost:9090(API Server)의 리소스에 접근하는 걸 막음(포트가 달라서 다른 출처로 인식)

때문에 서버와 ajax로 통신 하기 위해선 서버에서 따로  "Access-Control-Allow-Origin"을 해줘야 한다.

내 경우는 서버는 springBoot였기에 2가지 방법 중(config, yml 방식) Configuration에 설정했고 설정을 해 준 다음에는 테이블에 데이터가 잘 그려졌다.(서버 설정 후 동영상 촬영)

package study.dev.thboard3.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addRedirectViewController("/", "/board/list");
    }
	
    //아래부분 추가
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8080") // 클라이언트 도메인을 여기에 허용(vue.js에서의 runtime)
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowedHeaders("*")
                .allowCredentials(true);
    }
}

개인 공부한 내용을 기록한 공간이라 틀린 점이 있을 수 있으니 틀린점이 있을 경우 댓글 부탁드립니다.

반응형