diff --git a/app.js b/app.js
index 0fd3e42d11a9875ac5397049f08d329b161eedc4..2897b98d5444dfa081660e44c5a819b7ffdb59c2 100644
--- a/app.js
+++ b/app.js
@@ -10,6 +10,7 @@ dotenv.config();
 
 const meetingRouter = require('./routes/meeting');
 const participantRouter = require('./routes/participant');
+const myScheduleRouter = require('./routes/mySchedule');
 const { sequelize } = require('./models');
 
 const app = express();
@@ -50,6 +51,7 @@ app.use(
 
 app.use('/meetings', meetingRouter);
 app.use('/meetings/:meetingId/participants', participantRouter);
+app.use('/meetings/:meetingId/my/schedules', myScheduleRouter);
 
 app.use((req, res, next) => {
   const error = new Error(`There is no router. ${req.method} ${req.url}`);
diff --git a/controllers/schedule.js b/controllers/schedule.js
new file mode 100644
index 0000000000000000000000000000000000000000..56067f5d0b13da499397876b33fe0b0da2c6a18d
--- /dev/null
+++ b/controllers/schedule.js
@@ -0,0 +1,41 @@
+const { Schedule, sequelize } = require('../models');
+const { getLoggedInParticipantId } = require('../middlewares/auth');
+const SchedulesResponse = require('../dto/response/schedulesResponse');
+const { createScheduleAlreadyExistError } = require('../errors/scheduleErrors');
+
+async function validateScheduleNotExist(participantId) {
+  const numOfSchedules = await Schedule.count({
+    where: {
+      ParticipantId: participantId,
+    },
+  });
+  if (numOfSchedules > 0) {
+    throw createScheduleAlreadyExistError();
+  }
+}
+
+exports.createMySchedules = async (req, res, next) => {
+  const participantId = getLoggedInParticipantId(req, res, next);
+  const { availableSchedules } = req.body;
+  try {
+    await validateScheduleNotExist(participantId);
+
+    const schedules = await sequelize.transaction(async (transaction) =>
+      Promise.all(
+        availableSchedules.map((availableSchedule) =>
+          Schedule.create(
+            {
+              availableDate: availableSchedule.availableDate,
+              availableTimes: availableSchedule.availableTimes,
+              ParticipantId: participantId,
+            },
+            { transaction },
+          ),
+        ),
+      ),
+    );
+    return res.json(SchedulesResponse.from(schedules));
+  } catch (error) {
+    return next(error);
+  }
+};
diff --git a/dto/response/schedulesResponse.js b/dto/response/schedulesResponse.js
new file mode 100644
index 0000000000000000000000000000000000000000..db96a75f85e9c0048b1ccf1de9bc9c7f943f3a1c
--- /dev/null
+++ b/dto/response/schedulesResponse.js
@@ -0,0 +1,15 @@
+const ScheduleResponse = require('./scheduleResponse');
+
+class SchedulesResponse {
+  constructor(schedules) {
+    this.schedules = schedules;
+  }
+
+  static from(schedules) {
+    return new SchedulesResponse(
+      schedules.map((schedule) => ScheduleResponse.from(schedule)),
+    );
+  }
+}
+
+module.exports = SchedulesResponse;
diff --git a/errors/scheduleErrors.js b/errors/scheduleErrors.js
new file mode 100644
index 0000000000000000000000000000000000000000..29ab8f8d043fdc5734a12169d8096a23bd6dd177
--- /dev/null
+++ b/errors/scheduleErrors.js
@@ -0,0 +1,7 @@
+exports.createScheduleAlreadyExistError = () => {
+  const error = new Error(
+    '기존에 저장한 스케줄이 존재합니다. 기존 스케줄 데이터를 삭제한 후 다시 시도하거나, 수정하기 API를 사용해주세요.',
+  );
+  error.status = 409;
+  return error;
+};
diff --git a/middlewares/auth.js b/middlewares/auth.js
new file mode 100644
index 0000000000000000000000000000000000000000..81884a2752c8824b12b69bfbf554fb61498c089a
--- /dev/null
+++ b/middlewares/auth.js
@@ -0,0 +1,28 @@
+function parseParticipantData(req, res, next) {
+  let participantData = null;
+  if (req.signedCookies.participantData) {
+    participantData = JSON.parse(req.signedCookies.participantData);
+  }
+  if (!participantData) {
+    const error = new Error('인증 권한이 없습니다.');
+    error.status = 401;
+    return next(error);
+  }
+  return participantData;
+}
+
+exports.isAuthenticated = (req, res, next) => {
+  const participantData = parseParticipantData(req);
+  if (participantData.meetingId !== req.params.meetingId) {
+    const error = new Error('접근 권한이 없습니다.');
+    error.status = 401;
+    next(error);
+    return;
+  }
+  next();
+};
+
+exports.getLoggedInParticipantId = (req, res, next) => {
+  const participantData = parseParticipantData(req, res, next);
+  return participantData?.participantId;
+};
diff --git a/middlewares/index.js b/middlewares/index.js
deleted file mode 100644
index 27afea007237bd0628d988f5599ec83906b6998c..0000000000000000000000000000000000000000
--- a/middlewares/index.js
+++ /dev/null
@@ -1,13 +0,0 @@
-exports.isAuthenticated = (req, res, next) => {
-  let participantData = null;
-  if (req.signedCookies.participantData) {
-    participantData = JSON.parse(req.signedCookies.participantData);
-  }
-  if (!participantData || participantData.meetingId !== req.params.meetingId) {
-    const error = new Error('접근 권한이 없습니다.');
-    error.status = 401;
-    next(error);
-    return;
-  }
-  next();
-};
diff --git a/routes/meeting.js b/routes/meeting.js
index 7763ca50e73f19460992430c8fb9b9337005eaeb..956df300ce4eb0d0b4a4444bee35f3c0a6419f9b 100644
--- a/routes/meeting.js
+++ b/routes/meeting.js
@@ -1,5 +1,5 @@
 const express = require('express');
-const { isAuthenticated } = require('../middlewares/index');
+const { isAuthenticated } = require('../middlewares/auth');
 const {
   createMeeting,
   entry,
diff --git a/routes/mySchedule.js b/routes/mySchedule.js
new file mode 100644
index 0000000000000000000000000000000000000000..20991dbdd65cf1833be185e2795e291d5de0d83b
--- /dev/null
+++ b/routes/mySchedule.js
@@ -0,0 +1,9 @@
+const express = require('express');
+const { isAuthenticated } = require('../middlewares/auth');
+const { createMySchedules } = require('../controllers/schedule');
+
+const router = express.Router({ mergeParams: true });
+
+router.post('/bulk', isAuthenticated, createMySchedules);
+
+module.exports = router;