개발 관련/Vue

[vue.js] axios를 통해 프로그레스바를 만들어보자!(feat.onUploadProgress)

Hago하고 2021. 6. 5. 01:38
반응형

우리가 자주 보는 ui중, 업로드 중에 몇 퍼센트가 업로드가 되었는지 확인할 수 있는 ui가 있다.

진행바라고도 하는데, 해당 부분을 하기 위해 부단히도 노력했다.

 

처음에는 통신API를 따로 폴더를 만들어서 관리했었다.

하지만 통신 API를 따로 만들어 둘 경우, onUploadProgress에서 퍼센트를 가져와서 값을 바인딩하는 과정에서 문제가 생겼다. 아마 api폴더의 index.js로 가면서 컨텍스트가 사라져 버려서 그런게 아닐까하는 생각이 있는데,

 

아무튼 그래서 전전긍긍하다가 api를 전부 vuex의 store로 옮기기로 했다.

이게 사이즈가 큰 프로젝트라면 다른 방법을 찾아봐야겠지만, 우선 통신관련 api는 3개 밖에 없었기에, api를 store의 actions에서 관리하고, 진행도인 퍼센트를 mutation을 통해 바로 state에 저장하는 방법을 사용하기로 했다.

 

해당 이유는 vuex의 이벤트 사이클을 확인하도록 하자. Actions를 거쳐, Mutations를 지나, State로 가야한다. Actions에서 State를 건들 수 있는 방법은 현재로서는 없다. 무조건 Mutations에 State와 연결해줄 함수를 만들어 놔야한다.

출처 : https://medium.com/@sadickjunior/how-does-a-minimal-vuex-implementation-looks-like-find-out-c2c2e13619cb

 


 

우선 코드를 먼저 보도록 하겠다.

 

async UPLOAD({ commit }, data) {
	const response = await axios.post(url, data, {
		onUploadProgress: (progressEvent) => {
			let percentage = (progressEvent.loaded * 100) / progressEvent.total;
			let percentCompleted = Math.round(percentage);
			commit('setUploadPercent', percentCompleted);
		},
		header: {
			'Context-Type': 'multipart/form-data',
		}
	});
	return response;
},

onUploadProgress는 처음 구현해보는 것이었기 때문에 온갖 곳을 다 둘러봤다.

신기한 점은, 프로그레스바를 사용하기 위한 로직은 대부분 다 비슷하다는 것이었다.

 

axios는 통신할 때 파라미터가 정해져있다. 따로 설정값을 정하지 않을 때에는

axios.post(url, data);

위와 같은 식으로 간편하게 사용할 수 있다.

그리고, 조금 더 심화로 가게되면 config를 설정할 수 있다.

const config = {
	... //config관련 설정
}

axios.post(url, data, config);

우리는 이 config의 속성 중 onUploadProgress를 사용할 것이다.

header의 경우 파일을 전송하기 위해 multipart/form-data로 설정해주었다.

아마 파일을 전송할 사람이라면 헤더를 저렇게 바꿔줘야 정상적으로 넘어갈 것이라 생각한다.

 

그럼 다시 위에서 말한 부분을 보도록 하자

async UPLOAD({ commit }, data) {
	const response = await axios.post(url, data, {
		onUploadProgress: (progressEvent) => {
			let percentage = (progressEvent.loaded * 100) / progressEvent.total;
            //progressEvent.loaded는 현재까지 로드 된 수치를 나타내고
            //progressEvent.total은 전체 수치를 나타낸다.
			let percentCompleted = Math.round(percentage);
			commit('setUploadPercent', percentCompleted);
            //onUplodeProgress는 갱신될 때마다 해당 커밋을 수행한다.
            //console.log(percentCompleted);를 입력해보면 콘솔창에서 확인 가능하다.
		},
		header: {
			'Context-Type': 'multipart/form-data',
		}
	});
	return response;
},

(progressEvent.loaded * 100) / progressEvent.total은 전세계 만국 공통의 느낌이었다.

한국인 개발자 블로그를 가도 이렇게 계산하고, 미국도 이렇게, 일본도 이렇게 계산한다.

그러니 여러분도 이렇게 쓰자. (물론 변수명은 정하고 싶은 대로 정하면 된다.)

 

나는 해당 값을 구한 후, commit을 통해 setUploadPercent mutations를 통해 state에 저장하고,

컴포넌트에서 바로 {{ this.$store.state.uploadPercent }}를 이용해 값을 불러왔다.

 

아래는 컴포넌트의 예시다.

<Modal v-if="showModal" @close="showModal = false">
	<h3 slot="header">Progress</h3>
	<div slot="body">
		<b-progress :max=100>
			<b-progress-bar :value=this.$store.state.uploadPercent :label="`${ this.$store.state.uploadPercent }% `"></b-progress-bar>
		</b-progress>                
	</div>
</Modal>

나는 npm을 통해 bootstrap-vue를 설치했기 때문에 <b-progress>를 사용할 수 있었다.

해당 태그를 사용하기 위해서는 npm i bootstrap-vue를 통해 설치를 해준 후에,

위와 같이 바로 복사해서 값만 바꿔서 넣을 수도 있고,

 

부트스트랩 뷰 홈페이지 

 

BootstrapVue

Quickly integrate Bootstrap v4 components with Vue.js

bootstrap-vue.org

위의 홈페이지를 통해 사용하고 싶은 progress bar를 구할 수도 있다.

 

파란색 바 이외에도 많으니 취향껏 고르면 된다.

 

반응형