diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/CreateNoticeRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/CreateNoticeRequest.kt
new file mode 100644
index 0000000..5c48a40
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/CreateNoticeRequest.kt
@@ -0,0 +1,10 @@
+package kr.co.vividnext.sodalive.notice
+
+data class CreateNoticeRequest(
+    val title: String,
+    val content: String
+) {
+    fun toEntity(): ServiceNotice {
+        return ServiceNotice(title, content)
+    }
+}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt
new file mode 100644
index 0000000..aa35bbf
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/GetNoticeResponse.kt
@@ -0,0 +1,13 @@
+package kr.co.vividnext.sodalive.notice
+
+data class GetNoticeResponse(
+    val totalCount: Int,
+    val noticeList: List<NoticeItem>
+)
+
+data class NoticeItem(
+    val id: Long,
+    val title: String,
+    val content: String,
+    val date: String
+)
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNotice.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNotice.kt
new file mode 100644
index 0000000..6800fff
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNotice.kt
@@ -0,0 +1,15 @@
+package kr.co.vividnext.sodalive.notice
+
+import kr.co.vividnext.sodalive.common.BaseEntity
+import javax.persistence.Column
+import javax.persistence.Entity
+
+@Entity
+data class ServiceNotice(
+    @Column(nullable = false)
+    var title: String,
+    @Column(columnDefinition = "TEXT", nullable = false)
+    var content: String,
+    @Column(nullable = false)
+    var isActive: Boolean = true
+) : BaseEntity()
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeController.kt
new file mode 100644
index 0000000..f1f7921
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeController.kt
@@ -0,0 +1,38 @@
+package kr.co.vividnext.sodalive.notice
+
+import kr.co.vividnext.sodalive.common.ApiResponse
+import org.springframework.data.domain.Pageable
+import org.springframework.security.access.prepost.PreAuthorize
+import org.springframework.web.bind.annotation.DeleteMapping
+import org.springframework.web.bind.annotation.GetMapping
+import org.springframework.web.bind.annotation.PathVariable
+import org.springframework.web.bind.annotation.PostMapping
+import org.springframework.web.bind.annotation.PutMapping
+import org.springframework.web.bind.annotation.RequestBody
+import org.springframework.web.bind.annotation.RequestMapping
+import org.springframework.web.bind.annotation.RestController
+
+@RestController
+@RequestMapping("/notice")
+class ServiceNoticeController(private val service: ServiceNoticeService) {
+    @PostMapping
+    @PreAuthorize("hasRole('ADMIN')")
+    fun createNotice(@RequestBody request: CreateNoticeRequest) = ApiResponse.ok(
+        service.save(request),
+        "등록되었습니다."
+    )
+
+    @PutMapping
+    @PreAuthorize("hasRole('ADMIN')")
+    fun updateNotice(@RequestBody request: UpdateNoticeRequest) = ApiResponse.ok(
+        service.update(request),
+        "수정되었습니다."
+    )
+
+    @DeleteMapping("/{id}")
+    @PreAuthorize("hasRole('ADMIN')")
+    fun deleteCoin(@PathVariable id: Long) = ApiResponse.ok(service.delete(id), "삭제되었습니다.")
+
+    @GetMapping
+    fun getNoticeList(pageable: Pageable, timezone: String) = ApiResponse.ok(service.getNoticeList(pageable, timezone))
+}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt
new file mode 100644
index 0000000..10d28c2
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceNoticeService.kt
@@ -0,0 +1,66 @@
+package kr.co.vividnext.sodalive.notice
+
+import kr.co.vividnext.sodalive.common.SodaException
+import org.springframework.data.domain.Pageable
+import org.springframework.data.repository.findByIdOrNull
+import org.springframework.stereotype.Service
+import org.springframework.transaction.annotation.Transactional
+import java.time.ZoneId
+import java.time.format.DateTimeFormatter
+
+@Service
+@Transactional(readOnly = true)
+class ServiceNoticeService(private val repository: ServiceServiceNoticeRepository) {
+    @Transactional
+    fun save(request: CreateNoticeRequest): Long {
+        if (request.title.isBlank()) throw SodaException("제목을 입력하세요.")
+        if (request.content.isBlank()) throw SodaException("내용을 입력하세요.")
+
+        val notice = request.toEntity()
+        return repository.save(notice).id!!
+    }
+
+    @Transactional
+    fun update(request: UpdateNoticeRequest) {
+        if (request.id <= 0) throw SodaException("잘못된 요청입니다.")
+        if (request.title.isNullOrBlank() && request.content.isNullOrBlank()) {
+            throw SodaException("수정할 내용을 입력하세요.")
+        }
+
+        val notice = repository.findByIdOrNull(request.id)
+            ?: throw SodaException("잘못된 요청입니다.")
+
+        if (!request.title.isNullOrBlank()) notice.title = request.title
+        if (!request.content.isNullOrBlank()) notice.content = request.content
+    }
+
+    @Transactional
+    fun delete(id: Long) {
+        if (id <= 0) throw SodaException("잘못된 요청입니다.")
+        val notice = repository.findByIdOrNull(id)
+            ?: throw SodaException("잘못된 요청입니다.")
+
+        notice.isActive = false
+    }
+
+    fun getNoticeList(pageable: Pageable, timezone: String): GetNoticeResponse {
+        val totalCount = repository.getNoticeTotalCount()
+        val noticeList = repository.getNoticeList(pageable)
+            .asSequence()
+            .map {
+                val createdAt = it.createdAt!!
+                    .atZone(ZoneId.of("UTC"))
+                    .withZoneSameInstant(ZoneId.of(timezone))
+
+                NoticeItem(
+                    it.id!!,
+                    it.title,
+                    it.content,
+                    createdAt.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
+                )
+            }
+            .toList()
+
+        return GetNoticeResponse(totalCount, noticeList)
+    }
+}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt
new file mode 100644
index 0000000..90d5a47
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/ServiceServiceNoticeRepository.kt
@@ -0,0 +1,37 @@
+package kr.co.vividnext.sodalive.notice
+
+import com.querydsl.jpa.impl.JPAQueryFactory
+import kr.co.vividnext.sodalive.notice.QServiceNotice.serviceNotice
+import org.springframework.data.domain.Pageable
+import org.springframework.data.jpa.repository.JpaRepository
+import org.springframework.stereotype.Repository
+
+@Repository
+interface ServiceServiceNoticeRepository : JpaRepository<ServiceNotice, Long>, ServiceNoticeQueryRepository
+
+interface ServiceNoticeQueryRepository {
+    fun getNoticeTotalCount(): Int
+    fun getNoticeList(pageable: Pageable): List<ServiceNotice>
+}
+
+@Repository
+class ServiceNoticeQueryRepositoryImpl(private val queryFactory: JPAQueryFactory) : ServiceNoticeQueryRepository {
+    override fun getNoticeTotalCount(): Int {
+        return queryFactory
+            .select(serviceNotice.id)
+            .from(serviceNotice)
+            .where(serviceNotice.isActive.isTrue)
+            .fetch()
+            .size
+    }
+
+    override fun getNoticeList(pageable: Pageable): List<ServiceNotice> {
+        return queryFactory
+            .selectFrom(serviceNotice)
+            .where(serviceNotice.isActive.isTrue)
+            .offset(pageable.offset)
+            .limit(pageable.pageSize.toLong())
+            .orderBy(serviceNotice.id.desc())
+            .fetch()
+    }
+}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/notice/UpdateNoticeRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/notice/UpdateNoticeRequest.kt
new file mode 100644
index 0000000..c3da07d
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/notice/UpdateNoticeRequest.kt
@@ -0,0 +1,7 @@
+package kr.co.vividnext.sodalive.notice
+
+data class UpdateNoticeRequest(
+    val id: Long,
+    val title: String? = null,
+    val content: String? = null
+)