diff --git a/src/router/index.js b/src/router/index.js
index 752f8885038c3430b2960d65a90d3c0a8d07266b..02a5598926e42595eaaab6af2c7f0fd401e6105a 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -53,6 +53,11 @@ const routes = [
     name: 'TraineeList',
     component: () => import('@/views/TraineeList.vue'),
   },
+  {
+    path: '/trainee/create',
+    name: 'TraineeCreate',
+    component: () => import('@/views/TraineeCreate.vue'),
+  },
   {
     path: '/trainee/:id',
     name: 'TraineeDetail',
diff --git a/src/views/TraineeCreate.vue b/src/views/TraineeCreate.vue
new file mode 100644
index 0000000000000000000000000000000000000000..0bad6bb5beb7367e74f0384295178290f14587a4
--- /dev/null
+++ b/src/views/TraineeCreate.vue
@@ -0,0 +1,129 @@
+<template>
+  <div class="trainee-detail">
+    <v-row>
+      <v-col cols="12">
+        <v-card :loading="isProcessing">
+          <v-card-title>회원 등록</v-card-title>
+          <v-card-text>
+            <v-alert
+              v-if="error.isError"
+              dense
+              text
+              type="error"
+            >
+              {{ error.message }}
+            </v-alert>
+            <v-text-field
+              label="이메일"
+              v-model="trainee.email"
+            ></v-text-field>
+            <v-text-field
+              label="비밀번호"
+              type="password"
+              v-model="trainee.password"
+            ></v-text-field>
+            <v-text-field
+              label="이름"
+              v-model="trainee.name"
+            ></v-text-field>
+            <v-text-field
+              label="연락처"
+              v-model="trainee.phone"
+            ></v-text-field>
+            <v-menu
+              :close-on-content-click="false"
+              min-width="290px"
+              offset-y
+              v-model="showDatePicker"
+            >
+              <template v-slot:activator="{ on }">
+                <v-text-field
+                  label="생년월일"
+                  readonly
+                  v-model="trainee.birthDate"
+                  v-on="on"
+                ></v-text-field>
+              </template>
+              <v-date-picker
+                v-model="trainee.birthDate"
+                @input="showDatePicker = false"
+              ></v-date-picker>
+            </v-menu>
+          </v-card-text>
+          <v-card-actions>
+            <v-spacer></v-spacer>
+            <v-btn
+              color="error"
+              outlined
+              @click="cancel"
+            >
+              <v-icon left>mdi-delete</v-icon>
+              취소
+            </v-btn>
+            <v-btn
+              color="primary"
+              outlined
+              @click="createTrainee"
+            >
+              <v-icon left>mdi-content-save</v-icon>
+              저장
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </v-col>
+    </v-row>
+  </div>
+</template>
+
+<script>
+import APISetting from '@/settings/api';
+
+export default {
+  name: 'TraineeCreate',
+
+  data: () => ({
+    isProcessing: false,
+    error: {
+      isError: false,
+      message: '',
+    },
+    showDatePicker: false,
+    trainee: {
+      email: '',
+      password: '',
+      name: '',
+      phone: '',
+      birthDate: '',
+    },
+  }),
+
+  methods: {
+    createTrainee() {
+      this.error.isError = false;
+      this.error.message = '';
+      this.isProcessing = true;
+
+      fetch(APISetting.endpoints.trainee.list, APISetting.settings.post(this.trainee))
+        .then((res) => {
+          if ([201, 400, 500].includes(res.status)) return Promise.all([res.json(), res]);
+          throw new Error('알 수 없는 응답입니다.');
+        })
+        .then((values) => {
+          const [json, res] = values;
+          if (res.status !== 201) throw new Error(json.message);
+          this.$router.push('/trainee');
+        })
+        .catch((e) => {
+          this.error.message = e.message;
+          this.error.isError = true;
+        })
+        .finally(() => {
+          this.isProcessing = false;
+        });
+    },
+    cancel() {
+      this.$router.push('/trainee');
+    },
+  },
+};
+</script>
diff --git a/src/views/TraineeDetail.vue b/src/views/TraineeDetail.vue
index 4b9dbdca073d94678d8b5caffa62ce5738113c18..bfadb67561ce1f43738aaf90eede6ef5b8a4f591 100644
--- a/src/views/TraineeDetail.vue
+++ b/src/views/TraineeDetail.vue
@@ -1,99 +1,93 @@
 <template>
   <div class="trainee-detail">
-    <v-card
-      :loading="isProcessing"
-    >
-      <v-card-title>회원 정보</v-card-title>
-      <v-card-text>
-        <v-alert
-          v-if="error.isError"
-          dense
-          text
-          type="error"
-        >
-          {{ error.message }}
-        </v-alert>
-        <v-text-field
-          label="등록번호"
-          readonly
-          v-model="id"
-        ></v-text-field>
-        <v-text-field
-          label="이름"
-          v-model="trainee.name"
-        ></v-text-field>
-        <v-text-field
-          label="이메일"
-          v-model="trainee.email"
-        ></v-text-field>
-        <v-text-field
-          label="연락처"
-          v-model="trainee.phone"
-        ></v-text-field>
-        <v-menu
-          :close-on-content-click="false"
-          min-width="290px"
-          offset-y
-          v-model="showDatePicker"
-        >
-          <template
-            v-slot:activator="{ on }"
-          >
+    <v-row>
+      <v-col cols="12">
+        <v-card :loading="isProcessing">
+          <v-card-title>회원 정보</v-card-title>
+          <v-card-text>
+            <v-alert
+              v-if="error.isError"
+              dense
+              text
+              type="error"
+            >
+              {{ error.message }}
+            </v-alert>
             <v-text-field
-              label="생년월일"
+              label="등록번호"
               readonly
-              v-model="trainee.birthDate"
-              v-on="on"
+              v-model="id"
             ></v-text-field>
-          </template>
-          <v-date-picker
-            v-model="trainee.birthDate"
-            @input="showDatePicker = false"
-          ></v-date-picker>
-        </v-menu>
-        <v-text-field
-          label="등록 시각"
-          readonly
-          v-model="trainee.createdAt"
-        ></v-text-field>
-        <v-text-field
-          label="최종 수정 시각"
-          readonly
-          v-model="trainee.updatedAt"
-        ></v-text-field>
-      </v-card-text>
-      <v-card-actions>
-        <v-spacer></v-spacer>
-        <v-btn
-          color="error"
-          outlined
-          @click="deleteTrainee(id)"
-        >
-          <v-icon
-            left
-          >
-            mdi-delete
-          </v-icon>
-          삭제
-        </v-btn>
-        <v-btn
-          color="primary"
-          outlined
-          @click="updateTrainee(id)"
-        >
-          <v-icon
-            left
-          >
-            mdi-content-save
-          </v-icon>
-          저장
-        </v-btn>
-      </v-card-actions>
-    </v-card>
+            <v-text-field
+              label="이름"
+              v-model="trainee.name"
+            ></v-text-field>
+            <v-text-field
+              label="이메일"
+              v-model="trainee.email"
+            ></v-text-field>
+            <v-text-field
+              label="연락처"
+              v-model="trainee.phone"
+            ></v-text-field>
+            <v-menu
+              :close-on-content-click="false"
+              min-width="290px"
+              offset-y
+              v-model="showDatePicker"
+            >
+              <template v-slot:activator="{ on }">
+                <v-text-field
+                  label="생년월일"
+                  readonly
+                  v-model="trainee.birthDate"
+                  v-on="on"
+                ></v-text-field>
+              </template>
+              <v-date-picker
+                v-model="trainee.birthDate"
+                @input="showDatePicker = false"
+              ></v-date-picker>
+            </v-menu>
+            <v-text-field
+              label="등록 시각"
+              readonly
+              v-model="trainee.createdAt"
+            ></v-text-field>
+            <v-text-field
+              label="최종 수정 시각"
+              readonly
+              v-model="trainee.updatedAt"
+            ></v-text-field>
+          </v-card-text>
+          <v-card-actions>
+            <v-spacer></v-spacer>
+            <v-btn
+              color="error"
+              outlined
+              @click="deleteTrainee(id)"
+            >
+              <v-icon left>mdi-delete</v-icon>
+              삭제
+            </v-btn>
+            <v-btn
+              color="primary"
+              outlined
+              @click="updateTrainee(id)"
+            >
+              <v-icon left>mdi-content-save</v-icon>
+              저장
+            </v-btn>
+          </v-card-actions>
+        </v-card>
+      </v-col>
+    </v-row>
   </div>
 </template>
 
 <script>
+import moment from 'moment';
+
 import APISetting from '@/settings/api';
 
 export default {
@@ -111,8 +105,8 @@ export default {
       name: '',
       phone: '',
       birthDate: '',
-      updatedAt: '',
       createdAt: '',
+      updatedAt: '',
     },
   }),
 
@@ -139,7 +133,10 @@ export default {
           const [json, res] = values;
           if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
           if (res.status !== 200) throw new Error(json.message);
-          this.trainee = json.trainee;
+          const { trainee } = json;
+          trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss');
+          trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss');
+          this.trainee = trainee;
         })
         .catch((e) => {
           this.error.message = e.message;
@@ -164,7 +161,10 @@ export default {
           const [json, res] = values;
           if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
           if (res.status !== 200) throw new Error(json.message);
-          this.trainee = json.trainee;
+          const { trainee } = json;
+          trainee.createdAt = moment(trainee.createdAt).format('YYYY-MM-DD HH:mm:ss');
+          trainee.updatedAt = moment(trainee.updatedAt).format('YYYY-MM-DD HH:mm:ss');
+          this.trainee = trainee;
         })
         .catch((e) => {
           this.error.message = e.message;
@@ -183,7 +183,6 @@ export default {
         .then((res) => {
           if ([204, 404].includes(res.status)) return Promise.all([null, res]);
           if ([400, 500].includes(res.status)) return Promise.all([res.json(), res]);
-          // If response status is not equal to 204, 400, 404, or 500, go to catch.
           throw new Error('알 수 없는 응답입니다.');
         })
         .then((values) => {
diff --git a/src/views/TraineeList.vue b/src/views/TraineeList.vue
index dbde6e45a32105a67b613f4b2c2fe219f3d76ec2..4d1fc032ece32303994c9ad9283c716c5e913250 100644
--- a/src/views/TraineeList.vue
+++ b/src/views/TraineeList.vue
@@ -1,57 +1,80 @@
 <template>
   <div class="trainee-list">
-    <v-card>
-      <v-card-title>회원 목록</v-card-title>
-      <v-card-text>
-        <v-row
-          justify="end"
-        >
-          <v-col
-            cols="12"
-            sm="4"
-            md="3"
-            lg="3"
-            xl="2"
-          >
-            <v-text-field
-              append-icon="mdi-magnify"
-              clearable
-              label="회원 검색"
-              v-model="traineeList.searchKeyword"
-            ></v-text-field>
-          </v-col>
-        </v-row>
-        <v-data-table
-          :headers="traineeList.headers"
-          item-key="id"
-          :items="traineeList.data"
-          :loading="isProcessing"
-          loading-text="데이터를 불러오는 중입니다."
-          :search="traineeList.searchKeyword"
-          no-results-text="일치하는 회원을 찾지 못했습니다."
-        >
-          <template v-slot:item.action="{ item }">
-            <v-icon
-              small
-              class="mr-2"
-              @click="editTrainee(item.id)"
+    <v-row>
+      <v-col cols="12">
+        <v-card>
+          <v-card-title>회원 목록</v-card-title>
+          <v-card-text>
+            <v-row>
+              <v-col
+                align-self="center"
+                cols="12"
+                sm="8"
+                md="9"
+                lg="9"
+                xl="10"
+              >
+                <v-btn
+                  color="success"
+                  outlined
+                  @click="createTrainee"
+                >
+                  <v-icon left>
+                    mdi-plus
+                  </v-icon>
+                  새 회원 등록
+                </v-btn>
+              </v-col>
+              <v-col
+                cols="12"
+                sm="4"
+                md="3"
+                lg="3"
+                xl="2"
+              >
+                <v-text-field
+                  append-icon="mdi-magnify"
+                  clearable
+                  label="회원 검색"
+                  v-model="traineeList.searchKeyword"
+                ></v-text-field>
+              </v-col>
+            </v-row>
+            <v-data-table
+              :headers="traineeList.headers"
+              item-key="id"
+              :items="traineeList.data"
+              :loading="isProcessing"
+              loading-text="데이터를 불러오는 중입니다."
+              :search="traineeList.searchKeyword"
+              no-results-text="일치하는 회원을 찾지 못했습니다."
             >
-              mdi-pencil
-            </v-icon>
-            <v-icon
-              small
-              @click="deleteTrainee(item.id)"
-            >
-              mdi-delete
-            </v-icon>
-          </template>
-        </v-data-table>
-      </v-card-text>
-    </v-card>
+              <template v-slot:item.action="{ item }">
+                <v-icon
+                  small
+                  class="mr-2"
+                  @click="editTrainee(item.id)"
+                >
+                  mdi-pencil
+                </v-icon>
+                <v-icon
+                  small
+                  @click="deleteTrainee(item.id)"
+                >
+                  mdi-delete
+                </v-icon>
+              </template>
+            </v-data-table>
+          </v-card-text>
+        </v-card>
+      </v-col>
+    </v-row>
   </div>
 </template>
 
 <script>
+import moment from 'moment';
+
 import APISetting from '@/settings/api';
 
 export default {
@@ -81,6 +104,14 @@ export default {
           text: '연락처',
           value: 'phone',
         },
+        {
+          text: '생년월일',
+          value: 'birthDate',
+        },
+        {
+          text: '등록 시각',
+          value: 'createdAt',
+        },
         {
           text: '',
           value: 'action',
@@ -101,11 +132,14 @@ export default {
       fetch(APISetting.endpoints.trainee.list, APISetting.settings.get)
         .then((res) => {
           if (res.status === 200) return res.json();
-          // If response status is not equal to 200, go to catch.
           throw new Error('알 수 없는 응답입니다.');
         })
         .then((json) => {
           this.traineeList.data = json.trainees;
+          this.traineeList.data.forEach((trainee) => {
+            // eslint-disable-next-line no-param-reassign
+            trainee.createdAt = moment(trainee.createAt).format('YYYY-MM-DD HH:mm:ss');
+          });
         })
         .catch((e) => {
           this.error.message = e.message;
@@ -115,31 +149,34 @@ export default {
           this.isProcessing = false;
         });
     },
+    createTrainee() {
+      this.$router.push('/trainee/create');
+    },
     editTrainee(id) {
       this.$router.push(`/trainee/${id}`);
     },
     deleteTrainee(id) {
       this.error.isError = false;
       this.error.message = '';
+      this.isProcessing = true;
 
       fetch(APISetting.endpoints.trainee.detail(id), APISetting.settings.delete)
         .then((res) => {
           if (res.status === 204) return Promise.all([null, res]);
-          if ([204, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]);
-          // If response status is not equal to 204, 400, 404, 500, go to catch.
+          if ([400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]);
           throw new Error('알 수 없는 응답입니다.');
         })
         .then((values) => {
           const [json, res] = values;
-          // If trainee successfully deleted and response status is equal to 204,
-          // update trainee list.
           if (res.status === 204) return this.getTraineeList();
-          // Otherwise, go to catch.
           throw new Error(json.message);
         })
         .catch((e) => {
           this.error.message = e.message;
           this.error.isError = true;
+        })
+        .finally(() => {
+          this.isProcessing = false;
         });
     },
   },