Vue.js JWT 토큰 발행 서비스 UI/UX 개발하기
이 블로그 포스트에서는 Vue.js 를 활용하여 JWT(JSON Web Token) 토큰 발행 서비스를 개발하는 방법에 대해 알아보겠습니다.
JWT는 인증 및 정보 교환을 위한 표준화된 방법으로, 클라이언트와 서버 간의 안전한 통신을 위한 중요한 요소입니다.
Vue.js 는 간편한 구문과 강력한 기능을 제공하여 Frontend 개발을 용이하게 합니다.
이번 포스트를 통해 Vue.js와 JWT를 함께 활용하여 보안성이 높은 웹 애플리케이션을 구축하는 방법에 대해 살펴보겠습니다.
목차
1. JWT 토큰이란?
2. Vue.js를 활용하는 장점
3. 개발 환경 설치 및 구성
3-1. Vue.js CLI 설치
3-2. Vue.js 프로젝트 생성 및 기본 설정
4. Vue.js 를 이용해 JWT 토큰 발행 서비스 UI/UX 개발
4-1. Header 입력 Form 개발
4-2. Payload 입력 Form 개발
4-3. Signature 입력 Form 개발
4-4. JWT 토큰 반환 Encoded Form 개발
4-5. Vue.js JWT 생성 페이지 개발
1. JWT 토큰이란?
JWT(JSON Web Token)은 클라이언트와 서버 간의 인증 및 정보 교환을 위한 표준화된 방법입니다. 이는 안전한 통신을 위해 사용되며, 토큰에는 사용자에 대한 정보와 함께 서명(signature)이 포함되어 있어 변조를 방지합니다.
JWT는 Header, Payload, Signature 세 가지 부분으로 이루어져 있습니다.
Header(헤더): JWT의 유형 및 해싱 알고리즘 정보가 담겨있는 부분입니다. 헤더는 JSON 형식으로 되어 있으며, 일반적으로는 다음과 같은 내용을 포함합니다.
{
"alg": "HS256",
"typ": "JWT"
}
여기서 “alg“는 토큰의 서명에 사용되는 해싱 알고리즘을 나타내며, “typ“은 토큰의 유형을 나타냅니다.
Payload(페이로드): 실제로 전달되는 정보가 담겨 있는 부분입니다. Payload는 클레임(claim)이라 불리는 Key-Value Pair들로 이루어져 있습니다. Claim은 세 가지 유형으로 나뉩니다.
- 등록된 클레임(Registered claims): 토큰에 대한 정보를 나타내는 표준적인 클레임들로, 예를 들면 토큰 발급 시간(iat), 토큰 만료 시간(exp) 등이 있습니다.
- 공개 클레임(Public claims): 사용자 정의 클레임으로, 충돌을 방지하기 위해 URI 형식으로 네임스페이스를 정의합니다.
- 비공개 클레임(Private claims): 사용자 정의 클레임으로, 토큰 발행자와 소비자 간의 약속된 클레임입니다. 이들은 서로 공유된 비밀 키를 사용하여 사용자 지정 데이터를 안전하게 전송합니다.
Signature(서명): 서명은 Header와 Payload의 조합을 함께 Base64로 인코딩한 후, 지정된 알고리즘과 Secret Key를 사용하여 생성됩니다. 서명을 통해 토큰이 변조되지 않았음을 검증할 수 있습니다.
JWT는 토큰 기반의 인증을 구현할 때 주로 사용되며, 클라이언트가 로그인 후 서버로부터 발급받은 토큰을 이용하여 인증된 요청을 보낼 수 있습니다. 이러한 방식으로 JWT는 무상태(stateless)한 통신을 가능하게 하며, 확장성과 보안성을 높여줍니다.
2. Vue.js를 활용하는 장점
Vue.js는 간편하고 효율적인 프론트엔드 개발을 가능하게 하는 JavaScript 프레임워크입니다. JWT 토큰 발행 서비스 개발에 Vue.js를 활용하면 다음과 같은 장점을 얻을 수 있습니다.
- 간편한 문법: Vue.js 는 직관적이고 간결한 문법을 가지고 있습니다. HTML, CSS, JavaScript를 모두 포함하는 단일 파일 컴포넌트 형식을 사용하여 구조화된 코드를 작성할 수 있습니다. 이로써 코드의 가독성을 높이고 유지보수를 용이하게 합니다.
- 반응성(Reactivity): Vue.js 는 데이터의 변경을 감지하고 자동으로 화면을 업데이트하는 반응성 시스템을 제공합니다. 이는 데이터와 UI 간의 강력한 바인딩을 가능하게 하며, 복잡한 상태 관리를 간소화합니다.
- 컴포넌트 기반 아키텍처: Vue.js는 컴포넌트 기반 아키텍처를 채택하여 UI를 작은 독립적인 조각으로 나눌 수 있습니다. 각 컴포넌트는 재사용 가능하며, 관련된 로직과 스타일을 캡슐화하여 코드의 재사용성과 유지보수성을 향상시킵니다.
- 유연성과 확장성: Vue.js는 다른 프레임워크 및 라이브러리와 쉽게 통합되며, 기존 프로젝트에 적용하기도 용이합니다. 필요한 기능을 선택적으로 추가할 수 있는 플러그인 시스템을 제공하여 프로젝트의 요구 사항에 맞게 확장성을 보장합니다.
- 성능: Vue.js는 가볍고 빠르며, 가상 DOM(Virtual DOM)을 활용하여 효율적인 UI 렌더링을 지원합니다. 또한, 빠른 초기 로딩과 캐싱 기능을 통해 사용자 경험을 최적화합니다.
- 문서화와 커뮤니티: Vue.js는 풍부한 공식 문서와 활성화된 커뮤니티를 가지고 있습니다. 빠르게 성장하는 생태계와 다양한 리소스를 통해 학습과 지원을 받을 수 있습니다.
기존 JavaScript 프레임워크와 비교하면 다음과 같은 장점을 가집니다.
| 비교 항목 | Vue.js | Angular | React |
|---|---|---|---|
| 학습 난이도 | 쉬움 | 어려움 | 보통 |
| 개발 속도 | 빠름 | 느림 | 보통 |
| 코드 유지 관리 | 용이 | 어려움 | 보통 |
| 커뮤니티 활성도 | 활발 | 활발 | 활발 |
| 라이브러리 풍부도 | 풍부 | 풍부 | 풍부 |
| UI 프레임워크 | Vuetify, BootstrapVue | Material Design, Bootstrap | Material UI, Bootstrap |
이러한 장점들로 인해 Vue.js는 프로젝트를 빠르게 개발하고 관리하는 데 매우 유용한 도구로 폭넓게 활용되고 있습니다.
이는 마이크로서비스 아키텍처 (Microservice Architecture) 를 설계할 때, JavaScript 프레임워크로 Vue.js를 채택하여 애자일 방법론을 실현할 수 있습니다.
3. 개발 환경 설치 및 구성
3-1. Vue.js CLI 설치
먼저, Vue.js 개발 환경을 설치해야 합니다. 다음 명령어를 사용하여 Vue CLI를 설치합니다.
npm install -g @vue/cli
Vue CLI는 Vue.js 애플리케이션을 빠르고 쉽게 시작할 수 있도록 도와주는 명령줄 인터페이스입니다. Vue CLI는 다음과 같은 기능을 제공합니다.
- 새로운 프로젝트 생성: Vue CLI는 다양한 템플릿을 사용하여 새로운 Vue.js 프로젝트를 쉽게 생성할 수 있도록 합니다.
- 개발 서버 실행: Vue CLI는 개발 서버를 실행하여 웹 브라우저에서 Vue.js 애플리케이션을 실시간으로 미리 볼 수 있도록 합니다.
- 빌드 및 배포: Vue CLI는 Vue.js 애플리케이션을 빌드하여 프로덕션 환경에 배포할 수 있도록 합니다.
- 단위 테스트: Vue CLI는 Jest를 사용하여 Vue.js 애플리케이션의 단위 테스트를 수행할 수 있도록 합니다.
- End to End 테스트: Vue CLI는 Cypress를 사용하여 Vue.js 애플리케이션의 End to End 테스트를 수행할 수 있도록 합니다.
3-2. Vue.js 프로젝트 생성 및 기본 설정
Vue CLI를 설치한 후, 새로운 프로젝트를 생성합니다.
vue create vue-jwt-authentication
이 명령어는 vue-jwt-authentication라는 이름의 새 프로젝트를 생성합니다. 프로젝트 폴더에는 다음과 같은 파일과 폴더가 생성됩니다.
- package.json: 프로젝트의 의존성을 정의하는 파일입니다.
- README.md: 프로젝트에 대한 설명 파일입니다.
- public: 프로젝트의 Root 폴더입니다.
- src: 애플리케이션의 소스 코드를 포함하는 폴더입니다.
- node_modules: 프로젝트의 의존성 라이브러리를 포함하는 폴더입니다.
생성한 Vue.js 프로젝트에 들어가 필요한 라이브러리를 설치합니다.
cd vue-jwt-authentication
npm install axios
Vue CLI는 다양한 명령을 제공하여 Vue.js 애플리케이션 개발을 간편하게 합니다. 다음은 Vue CLI에서 사용할 수 있는 주요 명령입니다.
- vue serve: 개발 서버를 실행합니다.
- vue build: 애플리케이션을 빌드합니다.
- vue test: 단위 테스트를 실행합니다.
- vue e2e: 엔드 투 엔드 테스트를 실행합니다.
이제 Vue.js 프론트엔드 개발을 시작할 준비가 되었습니다.
4. Vue.js 를 이용해 JWT 토큰 발행 서비스 UI/UX 개발
JWT 토큰은 Header, Payload, Signature 세 가지 값으로 이루어집니다. 이러한 값을 Input Form을 통해 axios를 거쳐 백엔드 서버로 전달하고 생성된 JWT 토큰을 Encoded Form에 나타내 사용자에게 값을 반환해야 합니다.
다음은 Vue.js 프로젝트의 기본 구조입니다.

JWT 토큰 생성에 필요한 Header, Payload 및 Signature 입력 Form을 컴포넌트화 하여 개발할 것이기 때문에 components 폴더를 작업 영역으로 구성합니다.
4-1. Header 입력 Form 개발
JWT 발급을 위한 Header Form의 Template 태그를 작성합니다.
<template>
<h5 slot="header" class="title">Header</h5> <!-- 헤더 제목 -->
<div class="row">
<div class="col-md-12 pr-md-1">
<p class="oneh">유효한 Header를 작성하세요.</p> <!-- 사용자에게 유효한 Header 작성 안내 -->
<pre> {{ header }}</pre> <!-- 현재 Header 정보 표시 -->
</div>
</div>
</template>
<script> 태그 내에 Header Form에 들어갈 Data를 작성합니다.
<script>
export default {
props: {
// 부모 컴포넌트로부터 전달받은 모델 객체
model: {
type: Object,
default: () => {
return {};
},
},
},
data() {
return {
// 초기 Header 데이터
header: {
alg: "HS256",
typ: "JWT",
},
};
},
};
</script>

4-2. Payload 입력 Form 개발
JWT 발급을 위한 Payload Form의 Template 태그를 작성합니다.
<template>
<h5 slot="header" class="title">Payload</h5> <!-- 페이로드 제목 -->
<div class="row">
<div class="col-md-12 pr-md-1">
<p class="oneh">Token의 데이터를 작성하세요.</p> <!-- 사용자에게 페이로드 작성 안내 -->
<textarea v-model="payloadData.payload" class="form-control" id="" cols="30" rows="10"></textarea> <!-- 페이로드 입력란 -->
</div>
</div>
</template>
사용자가 payloadData v-model에 값을 입력 후, 부모 컴포넌트로 넘겨주기 위한 코드를 <script> 태그 내에 작성합니다.
<script>
export default {
props: {
// 부모 컴포넌트로부터 전달받은 모델 객체
model: Object,
},
data() {
return {
// 페이로드 데이터 초기화 (부모 컴포넌트로부터 받은 값이 없을 경우 빈 객체로 초기화)
payloadData: this.model.payloadData || {},
};
}
};
</script>

4-3. Signature 입력 Form 개발
JWT 발급을 위한 Payload Form의 Template 태그를 작성합니다.
<template>
<h5 slot="header" class="title">Signature</h5> <!-- 시그니처 제목 -->
<div class="row">
<div class="col-md-12 pr-md-1">
<p class="oneh">인증된 Signature를 작성하세요.</p> <!-- 사용자에게 시그니처 작성 안내 -->
<textarea class="form-control" id="" cols="30" rows="10" placeholder=""></textarea> <!-- 시그니처 입력란 -->
</div>
</div>
</template>
JWT 생성에 필요한 Signature 값을 부모 컴포넌트로 넘겨주기 위한 코드를 <script> 태그 내에 작성합니다.
<script>
export default {
props: {
// 부모 컴포넌트로부터 전달받은 모델 객체
model: {
type: Object,
default: () => {
return {};
},
},
},
};
</script>

4-4. JWT 토큰 반환 Encoded Form 개발
Header, Payload, Signature 값을 토대로 발급된 JWT 발급를 사용자에게 보여주기 위한 위한 Encoded Form과 해당 Form에 속해 있는 JWT 생성 버튼의 Template 태그를 작성합니다.
<template>
<h5 slot="header" class="title">Encoded</h5> <!-- 인코딩된 데이터 제목 --> <div class="row">
<div class="col-md-12">
<!-- 인코딩된 데이터를 표시하고 사용자 입력을 받는 TextArea -->
<textarea :value="encodedData" @input="$emit('generateToken', $event)" label="JWT Token" class="encodedHeight" cols="30" rows="10"></textarea>
</div>
</div>
<!-- 토큰 생성 버튼 -->
<button slot="footer" type="primary" fill @click="requestTokenGeneration">GENERATE</button>
</template>
Token 생성 메소드와 Encoded된 JWT 토큰을 표시하기 위한 코드를 <script> 태그 내에 작성합니다.
<script>
export default {
props: {
// 부모 컴포넌트로부터 전달받은 모델 객체와 인코딩된 데이터
model: Object,
encodedData: String
},
data() {
return {
};
},
methods: {
// 토큰 생성 요청을 부모 컴포넌트로 전달하는 메서드
requestTokenGeneration() {
this.$emit('generateToken');
}
}
};
</script>

4-5. Vue.js JWT 생성 페이지 개발
<script> 태그 내에 컴포넌트화된 각 Form들과 axios 라이브러리를 Import 합니다.
import EditHeaderForm from "./EditHeaderForm";
import EditPayloadForm from "./EditPayloadForm";
import EditSignatureForm from "./EditSignatureForm";
import EditEncodedForm from "./EditEncodedForm";
import axios from 'axios';
export default {
components: {
EditHeaderForm,
EditPayloadForm,
EditSignatureForm,
EditEncodedForm
},
JWT 생성을 위한 페이지를 개발합니다. Template 태그 내에 컴포넌트로 개발된 JWT 생성을 위한 Form을 불러옵니다.
<template>
<div class="row">
<!-- 헤더, 페이로드, 시그니처를 편집하는 폼들을 포함하는 열 -->
<div class="col-md-6">
<edit-header-form></edit-header-form> <!-- 헤더 편집 폼 -->
<edit-payload-form :model="model"></edit-payload-form> <!-- 페이로드 편집 폼 -->
<edit-signature-form></edit-signature-form> <!-- 시그니처 편집 폼 -->
</div>
<!-- 인코딩된 데이터를 보여주는 폼을 포함하는 열 -->
<div>
<edit-encoded-form :encodedData="model.encodedData" @generateToken="generateToken"></edit-encoded-form> <!-- 인코딩된 데이터 편집 폼 -->
</div>
</div>
</template>
<script> 태그에 axios를 통해 POST 요청을 보낼 Data를 선언합니다. Header, Payload, Signature, Encoded 데이터는 각 폼에 정의되어 있습니다.
data() {
return {
// 모델 객체 초기화
model: {
// 초기 데이터 구조
header: {
alg: "HS256",
typ: "JWT",
},
payloadData: {
payload: ''
},
verify: {
secretKey: "your-256-bit-secret-key-here"
},
encodedData: ''
},
};
},
<script> 태그 내에 JWT 생성 로직이 동작할 Methods를 작성합니다.
methods: {
generateToken() {
// Payload가 비어있는지 확인
if (!this.isPayloadEmpty()) {
const header = this.model.header;
const payload = this.model.payloadData;
const verify = this.model.verify;
// 유효한 JWT 생성 API를 가진 Backend 서버의 Endpoint로 변경
axios.post('http://foo.bar.example.com/jwt_issued', {
header: header,
payload: payload,
verify: verify
})
.then(response => {
console.log(response)
this.model.encodedData = response.data;
})
.catch(error => {
console.error('Error:', error);
alert('서버와 통신 중 오류가 발생했습니다.');
});
} else {
alert('Payload 값을 입력하세요.');
}
},
payloadChanged(payload) {
this.model.payloadData.payload = payload;
},
isPayloadEmpty() {
return this.model.payloadData.payload.trim() === '';
}
},
};

GENERATE 버튼을 클릭할 시 입력값을 Backend 서버로 보내 성공적으로 JWT 토큰이 생성된 것을 확인할 수 있습니다.

NGINX Plus를 사용한 Vue.js 성능 향상 방안은 다음과 같이 요약할 수 있습니다:
- 정적 파일 캐싱: NGINX를 사용해 정적 파일의 캐시 설정을 최적화하여 브라우저 로드 시간을 단축합니다.
- Gzip 압축: NGINX에서 Gzip 압축을 활성화하여 전송되는 파일 크기를 줄여 네트워크 대역폭 사용을 최적화합니다.
- 로드 밸런싱: NGINX를 로드 밸런서로 사용하여 서버 간의 트래픽을 분산시켜 서버 부하를 줄입니다.
- SSL/TLS 설정: NGINX에서 SSL/TLS 설정을 최적화하여 보안 및 성능을 개선합니다.
- 리버스 프록시: NGINX를 리버스 프록시로 사용하여 백엔드 서버의 요청을 처리하고, 캐시와 보안 기능을 추가로 제공합니다.
NGINX Plus를 통한 성능 향상을 경험을 하고 싶으시면 아래 폼으로 문의해주세요.
댓글을 달려면 로그인해야 합니다.