diff --git a/src/router/index.js b/src/router/index.js
index 21b2f13764fc21f7eaa54e93dd7520d5e2946c23..4285289019a827f5fe77cca44c1fe7a0dd02d720 100644
--- a/src/router/index.js
+++ b/src/router/index.js
@@ -38,6 +38,11 @@ const routes = [
     name: 'ScheduleList',
     component: () => import('@/views/ScheduleList.vue'),
   },
+  {
+    path: '/schedule/create',
+    name: 'ScheduleCreate',
+    component: () => import('../views/ScheduleCreate.vue'),
+  },
   {
     path: '/trainee',
     name: 'TraineeList',
diff --git a/src/views/ScheduleCreate.vue b/src/views/ScheduleCreate.vue
new file mode 100644
index 0000000000000000000000000000000000000000..946c15d580313ffac03fb1931a7241e5e4bbec13
--- /dev/null
+++ b/src/views/ScheduleCreate.vue
@@ -0,0 +1,123 @@
+<template>
+  <div class="schedule-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>
+        <program-field
+          :program.sync="schedule.program"
+        ></program-field>
+        <trainer-field
+          :trainer.sync="schedule.trainer"
+        ></trainer-field>
+        <v-text-field
+          label="최대 예약 가능 인원"
+          v-model="schedule.maxTrainee"
+        ></v-text-field>
+        <date-time-field
+          :datetime.sync="schedule.startAt"
+        ></date-time-field>
+      </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="createSchedule"
+        >
+          <v-icon
+            left
+          >
+            mdi-content-save
+          </v-icon>
+          저장
+        </v-btn>
+      </v-card-actions>
+    </v-card>
+  </div>
+</template>
+
+<script>
+import APISetting from '@/settings/api';
+import DateTimeField from '@/components/DateTimeField.vue';
+import ProgramField from '@/components/ProgramField.vue';
+import TrainerField from '@/components/TrainerField.vue';
+
+export default {
+  name: 'ScheduleCreate',
+
+  components: {
+    DateTimeField,
+    ProgramField,
+    TrainerField,
+  },
+
+  data: () => ({
+    isProcessing: false,
+    error: {
+      isError: false,
+      message: '',
+    },
+    schedule: {
+      program: {
+        title: '',
+      },
+      trainer: {
+        name: '',
+      },
+      maxTrainee: '',
+      startAt: '',
+    },
+  }),
+
+  methods: {
+    createSchedule() {
+      this.error.isError = false;
+      this.error.message = '';
+      this.isProcessing = true;
+
+      fetch(APISetting.endpoints.schedule.list, APISetting.settings.post(this.schedule))
+        .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('/schedule');
+        })
+        .catch((e) => {
+          this.error.message = e.message;
+          this.error.isError = true;
+        })
+        .finally(() => {
+          this.isProcessing = false;
+        });
+    },
+    cancel() {
+      this.$router.push('/schedule');
+    },
+  },
+};
+</script>