diff --git a/src/views/TrainerCreate.vue b/src/views/TrainerCreate.vue
new file mode 100644
index 0000000000000000000000000000000000000000..8fbf9af34d8b9a4bcc8ae19f72bfdeb9bb6a1b90
--- /dev/null
+++ b/src/views/TrainerCreate.vue
@@ -0,0 +1,140 @@
+<template>
+  <div class="trainer-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="trainer.email"
+            ></v-text-field>
+            <v-text-field
+              label="비밀번호"
+              type="password"
+              v-model="trainer.password"
+            ></v-text-field>
+            <v-text-field
+              label="이름"
+              v-model="trainer.name"
+            ></v-text-field>
+            <v-text-field
+              label="닉네임"
+              v-model="trainer.nickname"
+            ></v-text-field>
+            <v-text-field
+              label="연락처"
+              v-model="trainer.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="trainer.birthDate"
+                  v-on="on"
+                ></v-text-field>
+              </template>
+              <v-date-picker
+                v-model="trainer.birthDate"
+                @input="showDatePicker = false"
+              ></v-date-picker>
+            </v-menu>
+            <v-textarea
+              auto-grow
+              label="소개"
+              v-model="trainer.bio"
+            ></v-textarea>
+          </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="createTrainer"
+            >
+              <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: 'TrainerCreate',
+
+  data: () => ({
+    isProcessing: false,
+    error: {
+      isError: false,
+      message: '',
+    },
+    showDatePicker: false,
+    trainer: {
+      email: '',
+      password: '',
+      name: '',
+      nickname: '',
+      phone: '',
+      birthDate: '',
+      bio: '',
+    },
+  }),
+
+  methods: {
+    createTrainer() {
+      this.error.isError = false;
+      this.error.message = '';
+      this.isProcessing = true;
+
+      fetch(APISetting.endpoints.trainer.list, APISetting.settings.post(this.trainer))
+        .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('/trainer');
+        })
+        .catch((e) => {
+          this.error.message = e.message;
+          this.error.isError = true;
+        })
+        .finally(() => {
+          this.isProcessing = false;
+        });
+    },
+    cancel() {
+      this.$router.push('/trainer');
+    },
+  },
+};
+</script>
diff --git a/src/views/TrainerDetail.vue b/src/views/TrainerDetail.vue
index d1248bf2f8ff7b6cbeb1e9b3e3506f45a8e810c9..d76de2aa4f1e2a958f61d9d54bc7a352a031a55b 100644
--- a/src/views/TrainerDetail.vue
+++ b/src/views/TrainerDetail.vue
@@ -1,88 +1,102 @@
 <template>
   <div class="trainer-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="trainer.name"
-        ></v-text-field>
-        <v-text-field
-          label="이메일"
-          v-model="trainer.email"
-        ></v-text-field>
-        <v-text-field
-          label="연락처"
-          v-model="trainer.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="trainer.birthDate"
-              v-on="on"
+              v-model="id"
             ></v-text-field>
-          </template>
-          <v-date-picker
-            v-model="trainer.birthDate"
-            @input="showDatePicker = false"
-          ></v-date-picker>
-        </v-menu>
-        <v-text-field
-          label="등록 시각"
-          readonly
-          v-model="trainer.createdAt"
-        ></v-text-field>
-        <v-text-field
-          label="최종 수정 시각"
-          readonly
-          v-model="trainer.updatedAt"
-        ></v-text-field>
-      </v-card-text>
-      <v-card-actions>
-        <v-btn
-          color="error"
-          outlined
-          @click="deleteTrainer(id)"
-        >
-          삭제
-        </v-btn>
-        <v-btn
-          color="primary"
-          outlined
-          @click="updateTrainer(id)"
-        >
-          저장
-        </v-btn>
-      </v-card-actions>
-    </v-card>
+            <v-text-field
+              label="이메일"
+              v-model="trainer.email"
+            ></v-text-field>
+            <v-text-field
+              label="이름"
+              v-model="trainer.name"
+            ></v-text-field>
+            <v-text-field
+              label="닉네임"
+              v-model="trainer.nickname"
+            ></v-text-field>
+            <v-text-field
+              label="연락처"
+              v-model="trainer.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="trainer.birthDate"
+                  v-on="on"
+                ></v-text-field>
+              </template>
+              <v-date-picker
+                v-model="trainer.birthDate"
+                @input="showDatePicker = false"
+              ></v-date-picker>
+            </v-menu>
+            <v-textarea
+              auto-grow
+              label="소개"
+              v-model="trainer.bio"
+            ></v-textarea>
+            <v-text-field
+              label="등록 시각"
+              readonly
+              v-model="trainer.createdAt"
+            ></v-text-field>
+            <v-text-field
+              label="최종 수정 시각"
+              readonly
+              v-model="trainer.updatedAt"
+            ></v-text-field>
+          </v-card-text>
+          <v-card-actions>
+            <v-spacer></v-spacer>
+            <v-btn
+              color="error"
+              outlined
+              @click="deleteTrainer(id)"
+            >
+              <v-icon left>mdi-delete</v-icon>
+              삭제
+            </v-btn>
+            <v-btn
+              color="primary"
+              outlined
+              @click="updateTrainer(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 {
@@ -102,8 +116,8 @@ export default {
       phone: '',
       birthDate: '',
       bio: '',
-      updatedAt: '',
       createdAt: '',
+      updatedAt: '',
     },
   }),
 
@@ -130,6 +144,9 @@ export default {
           const [json, res] = values;
           if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
           if (res.status !== 200) throw new Error(json.message);
+          const { trainer } = json;
+          trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
+          trainer.updatedAt = moment(trainer.updatedAt).format('YYYY-MM-DD HH:mm:ss');
           this.trainer = json.trainer;
         })
         .catch((e) => {
@@ -148,13 +165,16 @@ export default {
       fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.put(this.trainer))
         .then((res) => {
           if (res.status === 404) return Promise.all([null, res]);
-          if ([200, 400, 404, 500].includes(res.status)) return Promise.all([res.json(), res]);
+          if ([200, 400, 500].includes(res.status)) return Promise.all([res.json(), res]);
           throw new Error('알 수 없는 응답입니다.');
         })
         .then((values) => {
           const [json, res] = values;
           if (res.status === 404) throw new Error('존재하지 않는 데이터입니다.');
           if (res.status !== 200) throw new Error(json.message);
+          const { trainer } = json;
+          trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
+          trainer.updatedAt = moment(trainer.updatedAt).format('YYYY-MM-DD HH:mm:ss');
           this.trainer = json.trainer;
         })
         .catch((e) => {
@@ -173,8 +193,7 @@ export default {
       fetch(APISetting.endpoints.trainer.detail(id), APISetting.settings.delete)
         .then((res) => {
           if ([204, 404].includes(res.status)) 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, or 500, go to catch.
+          if ([400, 500].includes(res.status)) return Promise.all([res.json(), res]);
           throw new Error('알 수 없는 응답입니다.');
         })
         .then((values) => {
diff --git a/src/views/TrainerList.vue b/src/views/TrainerList.vue
index 9fa71204f395da080d4050aba67dada587d349ad..0142173224a5c8c14c73d4c73d9f7d4afe06f557 100644
--- a/src/views/TrainerList.vue
+++ b/src/views/TrainerList.vue
@@ -1,57 +1,78 @@
 <template>
   <div class="trainer-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="trainerList.searchKeyword"
-            ></v-text-field>
-          </v-col>
-        </v-row>
-        <v-data-table
-          :headers="trainerList.headers"
-          item-key="id"
-          :items="trainerList.data"
-          :loading="isProcessing"
-          loading-text="데이터를 불러오는 중입니다."
-          :search="trainerList.searchKeyword"
-          no-results-text="일치하는 트레이너를 찾지 못했습니다."
-        >
-          <template v-slot:item.action="{ item }">
-            <v-icon
-              small
-              class="mr-2"
-              @click="editTrainer(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="createTrainer"
+                >
+                  <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="trainerList.searchKeyword"
+                ></v-text-field>
+              </v-col>
+            </v-row>
+            <v-data-table
+              :headers="trainerList.headers"
+              item-key="id"
+              :items="trainerList.data"
+              :loading="isProcessing"
+              loading-text="데이터를 불러오는 중입니다."
+              :search="trainerList.searchKeyword"
+              no-results-text="일치하는 트레이너를 찾지 못했습니다."
             >
-              mdi-pencil
-            </v-icon>
-            <v-icon
-              small
-              @click="deleteTrainer(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="editTrainer(item.id)"
+                >
+                  mdi-pencil
+                </v-icon>
+                <v-icon
+                  small
+                  @click="deleteTrainer(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 {
@@ -86,8 +107,8 @@ export default {
           value: 'phone',
         },
         {
-          text: '소개',
-          value: 'bio',
+          text: '등록 시각',
+          value: 'createdAt',
         },
         {
           text: '',
@@ -109,11 +130,15 @@ export default {
       fetch(APISetting.endpoints.trainer.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.trainerList.data = json.trainers;
+          const { trainers } = json;
+          trainers.forEach((trainer) => {
+            // eslint-disable-next-line no-param-reassign
+            trainer.createdAt = moment(trainer.createdAt).format('YYYY-MM-DD HH:mm:ss');
+          });
+          this.trainerList.data = trainers;
         })
         .catch((e) => {
           this.error.message = e.message;
@@ -123,31 +148,34 @@ export default {
           this.isProcessing = false;
         });
     },
+    createTrainer() {
+      this.$router.push('/trainer/create');
+    },
     editTrainer(id) {
       this.$router.push(`/trainer/${id}`);
     },
     deleteTrainer(id) {
       this.error.isError = false;
       this.error.message = '';
+      this.isProcessing = true;
 
       fetch(APISetting.endpoints.trainer.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 trainer successfully deleted and response status is equal to 204,
-          // update trainer list.
           if (res.status === 204) return this.getTrainerList();
-          // Otherwise, go to catch.
           throw new Error(json.message);
         })
         .catch((e) => {
           this.error.message = e.message;
           this.error.isError = true;
+        })
+        .finally(() => {
+          this.isProcessing = false;
         });
     },
   },