Vue.js 를 배워보자

Vue.js와 Axios로 데이터셋을 그리드로 로딩하고 클릭 시 Input Text에 자동 바인딩하기

_Blue_Sky_ 2025. 3. 4. 22:07
728x90
안녕하세요! 이번 포스트에서는 Vue.jsAxios를 활용해 서버에서 데이터셋을 가져와 그리드로 표시한 뒤, 그리드의 특정 행을 클릭했을 때 input text에 해당 데이터를 자동으로 바인딩하는 방법을 자세히 다뤄보겠습니다. 이 예제는 실무에서 자주 사용되는 데이터 관리 및 UI 연동 패턴을 보여줍니다. 아래에서 단계별로 설명하고, 전체 코드를 제공하겠습니다.
 

728x90
1. 프로젝트 설정
먼저, Vue 프로젝트를 생성하고 필요한 라이브러리를 설치해야 합니다. 아래 명령어를 사용해 기본 환경을 준비합니다.
 
# Vue CLI 설치 (미설치 시)
npm install -g @vue/cli

# 프로젝트 생성
vue create vue-axios-grid-example

# 프로젝트 폴더로 이동
cd vue-axios-grid-example

# Axios 설치
npm install axios

2. 기본 컴포넌트 구조
src/components 폴더에 DataGrid.vue라는 컴포넌트를 생성합니다. 이 컴포넌트에서 데이터 로딩, 그리드 표시, 클릭 시 바인딩 로직을 구현할 예정입니다.
 
ID Name Email
{{ item.id }} {{ item.name }} {{ item.email }}


 

<!-- src/components/DataGrid.vue -->
<template>
  <div>
    <!-- 데이터 그리드 -->
    <table border="1">
      <thead>
        <tr>
          <th>ID</th>
          <th>Name</th>
          <th>Email</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="item in gridData" :key="item.id" @click="selectRow(item)">
          <td>{{ item.id }}</td>
          <td>{{ item.name }}</td>
          <td>{{ item.email }}</td>
        </tr>
      </tbody>
    </table>

    <!-- 선택된 데이터를 바인딩할 입력 필드 -->
    <div style="margin-top: 20px;">
      <label>ID: </label>
      <input type="text" v-bind:value="selectedRow.id" readonly />
      <br />
      <label>Name: </label>
      <input type="text" v-bind:value="selectedRow.name" />
      <br />
      <label>Email: </label>
      <input type="text" v-bind:value="selectedRow.email" />
    </div>
  </div>
</template>

<script>
import axios from 'axios';

export default {
  name: 'DataGrid',
  data() {
    return {
      gridData: [], // 그리드에 표시할 데이터
      selectedRow: { id: '', name: '', email: '' }, // 선택된 행의 데이터
    };
  },
  mounted() {
    this.loadData(); // 컴포넌트가 마운트되면 데이터 로딩
  },
  methods: {
    // Axios로 데이터 가져오기
    loadData() {
      axios
        .get('https://jsonplaceholder.typicode.com/users') // 데모 API
        .then((response) => {
          this.gridData = response.data; // 응답 데이터를 gridData에 저장
        })
        .catch((error) => {
          console.error('데이터 로딩 실패:', error);
        });
    },
    // 행 클릭 시 호출되는 함수
    selectRow(item) {
      this.selectedRow = { ...item }; // 선택된 행의 데이터를 복사
    },
  },
};
</script>

<style>
table {
  width: 100%;
  max-width: 600px;
  margin-bottom: 20px;
}

th,
td {
  padding: 10px;
  text-align: left;
}

tr:hover {
  background-color: #f5f5f5;
  cursor: pointer;
}

input {
  margin: 5px 0;
  padding: 5px;
  width: 200px;
}
</style>

3. App.vue에서 컴포넌트 사용
App.vue에서 방금 만든 DataGrid.vue 컴포넌트를 불러와 사용합니다.
 
<!-- src/App.vue -->
<template>
  <div id="app">
    <h1>Vue.js Grid with Input Binding</h1>
    <DataGrid />
  </div>
</template>

<script>
import DataGrid from './components/DataGrid.vue';

export default {
  name: 'App',
  components: {
    DataGrid,
  },
};
</script>

<style>
#app {
  font-family: Arial, sans-serif;
  padding: 20px;
}
</style>

 
4. 코드 설명
데이터 로딩
  • axios.get: mounted 훅에서 https://jsonplaceholder.typicode.com/users라는 공개 API를 호출해 데이터를 가져옵니다. 가져온 데이터는 gridData 배열에 저장됩니다.
  • v-for: gridData를 반복 렌더링해 테이블 형식의 그리드를 생성합니다.
클릭 이벤트와 바인딩
  • @click: 테이블의 각 행(tr)에 클릭 이벤트를 추가하고, 클릭 시 selectRow 메서드가 호출됩니다.
  • selectRow(item): 클릭된 행의 데이터를 selectedRow 객체에 복사합니다. 얕은 복사({ ...item })를 사용해 원본 데이터가 수정되지 않도록 합니다.
  • v-bind:value: selectedRow의 속성(id, name, email)을 <input> 요소에 바인딩합니다. v-bind를 사용해 값이 반응형으로 업데이트됩니다.
스타일링
  • 간단한 CSS로 테이블과 입력 필드를 보기 좋게 꾸몄습니다. :hover를 사용해 행에 마우스를 올리면 배경색이 변하도록 설정했습니다.

5. 실행 방법
프로젝트를 실행하려면 다음 명령어를 입력하세요.
 
npm run serve
브라우저에서 http://localhost:8080에 접속하면 데이터 그리드와 입력 필드가 표시됩니다. 그리드의 행을 클릭하면 해당 데이터가 입력 필드에 자동으로 바인딩되는 것을 확인할 수 있습니다.

6. 추가 개선 아이디어
  • 양방향 바인딩: v-bind:value 대신 v-model을 사용하면 입력 필드에서 값을 수정할 수 있습니다.
  • 실제 API 연동: jsonplaceholder 대신 실제 백엔드 API를 연결해보세요.
  • 고급 그리드 라이브러리: ag-GridVue-Table 같은 라이브러리를 사용해 더 풍부한 기능을 추가할 수 있습니다.

결론
이 예제를 통해 Vue.js와 Axios로 데이터를 로딩하고, 클릭 이벤트를 통해 반응형으로 UI를 업데이트하는 방법을 배웠습니다. v-bind를 활용한 데이터 바인딩은 Vue의 핵심 기능 중 하나로, 간단하면서도 강력한 사용자 경험을 제공합니다. 질문이 있다면 댓글로 남겨주세요!
 
728x90