To Do List 프로젝트
“Todo List - 할 일 목록 UI 만들기”
스타 좀 눌러주세요
백엔드 (SpringBoot)
데이터베이스
todo 테이블
CREATE TABLE `todo` (
`no` int NOT NULL AUTO_INCREMENT,
`name` text NOT NULL,
`status` int DEFAULT '0',
`reg_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`upd_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`no`)
) COMMENT='할일';
SQL
복사
프로젝트 구조
•
🖧 Server
◦
java▪
controller•
TodoController.java▪
dto•
Todo.java▪
service•
TodoService.java•
TodoServiceImpl.java▪
mapper•
TodoMapper.java◦
resources▪
main-package/mapper•
TodoMapper.xml▪
application.properties▪
mybatis-config.xml
◦
build.gradle코드 작업
1.
build.gradle2.
application.properties3.
mybatis-config.xml4.
main-package/mapper•
TodoMapper.xml5.
mapper•
TodoMapper.java6.
dto•
Todo.java7.
service•
TodoService.java•
TodoServiceImpl.java8.
controller•
TodoController.java
build.gradle
plugins {
id 'java'
id 'war'
id 'org.springframework.boot' version '3.1.6'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.joeun'
version = '0.0.1-SNAPSHOT'
java {
sourceCompatibility = '17'
}
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter:3.0.3'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.mybatis.spring.boot:mybatis-spring-boot-starter-test:3.0.3'
}
tasks.named('bootBuildImage') {
builder = 'paketobuildpacks/builder-jammy-base:latest'
}
tasks.named('test') {
useJUnitPlatform()
}
Plain Text
복사
application.properties
# 데이터 소스 - MySQL
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://127.0.0.1:3306/joeun?serverTimezone=Asia/Seoul&allowPublicKeyRetrieval=true&useSSL=false&autoReconnection=true&autoReconnection=true
spring.datasource.username=joeun
spring.datasource.password=123456
# Mybatis 설정
# Mybatis 설정 경로 : ~/resources/mybatis-config.xml
mybatis.config-location=classpath:mybatis-config.xml
# Mybatis 매퍼 파일 경로 : ~/메인패키지/mapper/**Mapper.xml
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml
Plain Text
복사
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"https://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<!-- 설정 -->
<settings>
<!-- 언더스코어 케이스인 컬럼을 카멜 케이스로 변환하는 설정 -->
<!-- board_no - boardNo -->
<setting name="mapUnderscoreToCamelCase" value="true"/>
</settings>
<!-- 타입 별칭 설정 -->
<typeAliases>
<!-- 테이블과 매핑할 DTO가 있는 패키지 경로 지정 -->
<package name="com.joeun.todo.dto"/>
</typeAliases>
</configuration>
XML
복사
main-package/mapper
•
TodoMapper.xml<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!-- namespace="매퍼 인터페이스 경로" -->
<mapper namespace="com.joeun.todo.mapper.TodoMapper">
<!-- 할일 목록 -->
<select id="list" resultType="Todo">
SELECT *
FROM todo
ORDER BY status ASC, no DESC
</select>
<!-- 할일 조회 -->
<select id="select" resultType="Todo">
SELECT *
FROM todo
WHERE no = #{no}
</select>
<!-- 할일 등록 -->
<insert id="insert">
INSERT INTO todo( name )
VALUES ( #{name} )
</insert>
<!-- 할일 수정 -->
<update id="update">
UPDATE todo
SET name = #{name}
,status = #{status}
,upd_date = now()
WHERE no = #{no}
</update>
<!-- 할일 삭제 -->
<delete id="delete">
DELETE FROM todo
WHERE no = #{no}
</delete>
<!-- last id -->
<select id="lastId" resultType="int">
select last_insert_id() id
</select>
<!-- 전체 할일 완료 -->
<update id="completeAll">
UPDATE todo
SET status = 1
,upd_date = now()
</update>
<!-- 전체 할일 삭제 -->
<delete id="deleteAll">
DELETE FROM todo
</delete>
</mapper>
XML
복사
mapper
•
TodoMapper.javapackage com.joeun.todo.mapper;
import java.util.List;
import org.apache.ibatis.annotations.Mapper;
import com.joeun.todo.dto.Todo;
@Mapper
public interface TodoMapper {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
복사
dto
•
Todo.javapackage com.joeun.todo.service;
import java.util.List;
import com.joeun.todo.dto.Todo;
public interface TodoService {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
복사
service
•
TodoService.javapackage com.joeun.todo.service;
import java.util.List;
import com.joeun.todo.dto.Todo;
public interface TodoService {
public List<Todo> list() throws Exception;
public Todo select(int no) throws Exception;
public int insert(Todo todo) throws Exception;
public int update(Todo todo) throws Exception;
public int delete(int no) throws Exception;
public int lastId() throws Exception;
public int completeAll() throws Exception;
public int deleteAll() throws Exception;
}
Java
복사
•
TodoServiceImpl.javapackage com.joeun.todo.service;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.joeun.todo.dto.Todo;
import com.joeun.todo.mapper.TodoMapper;
@Service
public class TodoServiceImpl implements TodoService {
@Autowired
private TodoMapper todoMapper;
@Override
public List<Todo> list() throws Exception {
return todoMapper.list();
}
@Override
public Todo select(int no) throws Exception {
return todoMapper.select(no);
}
@Override
public int insert(Todo todo) throws Exception {
int result = todoMapper.insert(todo);
if( result > 0 )
result = todoMapper.lastId();
return result;
}
@Override
public int update(Todo todo) throws Exception {
return todoMapper.update(todo);
}
@Override
public int delete(int no) throws Exception {
return todoMapper.delete(no);
}
@Override
public int lastId() throws Exception {
return todoMapper.lastId();
}
@Override
public int completeAll() throws Exception {
return todoMapper.completeAll();
}
@Override
public int deleteAll() throws Exception {
return todoMapper.deleteAll();
}
}
Java
복사
controller
•
TodoController.java[Extension] Spring Code Generator
꿀팁 : sp-crud
package com.joeun.todo.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin;
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;
import com.joeun.todo.dto.Todo;
import com.joeun.todo.service.TodoService;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@RestController
@CrossOrigin(origins = "*") // cors 허용
@RequestMapping("/todos")
public class TodoController {
@Autowired
private TodoService todoService;
@GetMapping()
public ResponseEntity<?> getAll() {
log.info("list...");
try {
List<Todo> todoList = todoService.list();
log.info("할 일 개수 : " + todoList.size());
return new ResponseEntity<>(todoList, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@GetMapping("/{id}")
public ResponseEntity<?> getOne(@PathVariable Integer id) {
log.info("select...");
log.info("id : " + id);
try {
Todo todo = todoService.select(id);
log.info("todo : " + todo);
return new ResponseEntity<>(todo, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PostMapping()
public ResponseEntity<?> create(@RequestBody Todo todo) {
log.info("insert...");
try {
int result = todoService.insert(todo); // 새로 생성된 no 를 응답
todo.setNo(result);
log.info("result : " + result);
if( result > 0 )
return new ResponseEntity<>(todo, HttpStatus.CREATED);
else
return new ResponseEntity<>(todo, HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@PutMapping()
public ResponseEntity<?> update(@RequestBody Todo todo) {
log.info("update...");
log.info(todo.toString());
try {
int result = 0;
// 전체 완료
if( todo.getNo() == -1 ) {
result = todoService.completeAll();
}
else {
result = todoService.update(todo);
}
if( result > 0 )
return new ResponseEntity<>("Update Result", HttpStatus.OK);
else
return new ResponseEntity<>("No Result", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
@DeleteMapping("/{id}")
public ResponseEntity<?> destroy(@PathVariable Integer id) {
log.info("delete...");
log.info("id : " + id);
try {
int result = 0;
// 전체 삭제
if( id == -1 ) {
result = todoService.deleteAll();
}
else {
result = todoService.delete(id);
}
if( result > 0 )
return new ResponseEntity<>("Destroy Result", HttpStatus.OK);
else
return new ResponseEntity<>("No Result", HttpStatus.OK);
} catch (Exception e) {
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
Java
복사
테스트
게시글 목록 [GET]
http://localhost:8080/boards
Plain Text
복사
게시글 조회 [GET]
http://localhost:8080/boards/1
Plain Text
복사
게시글 등록 [POST]
http://localhost:8080/boards
Plain Text
복사
게시글 수정 [PUT]
http://localhost:8080/boards
Plain Text
복사
게시글 삭제 [DELETE]
http://localhost:8080/boards/1
Plain Text
복사














