본문 바로가기
spring/게시판

스프링 Rest CRUD 구현

by coie 2021. 4. 7.

어제 Spring으로 CRUD 만들고 시큐리티

적용하고 뭘 만들지....하다가

사람들이 Rest를 항상 이야기해서 Rest에

대해서 공부해봤습니다.

그 결과 오늘 하루 종일 해서 게시물 CRUD까지는 구현이 가능하게 돼서

이렇게 기록도 남기고 포스팅을 해봅니다.

 

먼저 기본 환경은

 Spring(legacy) | Java 8 | Oracle | Mybatis | Tomcat 9.0

ojdbc6.jar

이렇게입니다.

 

먼저 pom.xml

 

	<properties>
		<java-version>1.8</java-version>
		<org.springframework-version>5.0.8.RELEASE</org.springframework-version>
		<org.aspectj-version>1.6.10</org.aspectj-version>
		<org.slf4j-version>1.6.6</org.slf4j-version>
		<spring.security.version>4.1.3.RELEASE</spring.security.version>
	</properties>

	<dependencies>
		<!-- Spring -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
			<exclusions>
				<!-- Exclude Commons Logging in favor of SLF4j -->
				<exclusion>
					<groupId>commons-logging</groupId>
					<artifactId>commons-logging</artifactId>
				</exclusion>
			</exclusions>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-jdbc</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
			<version>${spring.security.version}</version>
		</dependency>



		<!-- AspectJ -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjrt</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>

		<!-- Logging -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>jcl-over-slf4j</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-log4j12</artifactId>
			<version>${org.slf4j-version}</version>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.15</version>
			<exclusions>
				<exclusion>
					<groupId>javax.mail</groupId>
					<artifactId>mail</artifactId>
				</exclusion>
				<exclusion>
					<groupId>javax.jms</groupId>
					<artifactId>jms</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jdmk</groupId>
					<artifactId>jmxtools</artifactId>
				</exclusion>
				<exclusion>
					<groupId>com.sun.jmx</groupId>
					<artifactId>jmxri</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>

		<dependency>
			<groupId>org.bgee.log4jdbc-log4j2</groupId>
			<artifactId>log4jdbc-log4j2-jdbc4</artifactId>
			<version>1.16</version>
		</dependency>

		<!-- @Inject -->
		<dependency>
			<groupId>javax.inject</groupId>
			<artifactId>javax.inject</artifactId>
			<version>1</version>
		</dependency>

		<!-- Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
			<scope>test</scope>
		</dependency>




		<!-- Servlet -->
		<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>4.0.1</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/javax.servlet.jsp-api -->
		<dependency>
			<groupId>javax.servlet.jsp</groupId>
			<artifactId>javax.servlet.jsp-api</artifactId>
			<version>2.3.3</version>
			<scope>provided</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.servlet/jstl -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- lombok -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-test</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<version>1.18.2</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis -->
		<!-- mybatis -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis</artifactId>
			<version>3.5.6</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
		<!-- spring과 연결 -->
		<dependency>
			<groupId>org.mybatis</groupId>
			<artifactId>mybatis-spring</artifactId>
			<version>2.0.6</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.12.1</version>
		</dependency>


		<dependency><!-- jackson -->
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.4.2</version>
		</dependency>

 

여기에서 mybatis나 기본 설정은 모두 되어있을 거라고 생각하고

중요한 거는 맨 밑의 2개

 

<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.12.1</version>
		</dependency>


		<dependency><!-- jackson -->
			<groupId>org.codehaus.jackson</groupId>
			<artifactId>jackson-mapper-asl</artifactId>
			<version>1.4.2</version>
		</dependency>

이 부분 입니다.

Rest에서는 xml이나 json 형식을 읽어오는데

난 그냥 ajax를 위해서 가져온 기본 설정이 Rest에서도 사용되는 것이다...

참고로 이 부분들이 없으면 오류가 계속 난다(경험....)

 

그다음 sql문

create table rest_board(
    bid number not null,
    btitle varchar2(100) not null,
    bcontent varchar2(2000) not null,
    bwriter varchar2(100) not null,
    PRIMARY KEY(bid)
);

create sequence rboa_seq start with 1 INCREMENT BY 1 NOCYClE NOCACHE;

commit;

insert into rest_board
values(rboa_seq.nextval,'테스트제목!','테스트 내용!!','admin');
insert into rest_board
values(rboa_seq.nextval,'테스트제목2','테스트 내용2!!','admin');
insert into rest_board
values(rboa_seq.nextval,'테스트제목3','테스트 내용3!!','admin');
insert into rest_board
values(rboa_seq.nextval,'테스트제목4','테스트 내용4!!','admin');
insert into rest_board
values(rboa_seq.nextval,'테스트제목5','테스트 내용5!!','admin');

commit;

select * from rest_board;

아직 회원 기능까지는 못해봐서

게시판에서 필요로 하는 최소한의 기능만 설정해뒀다.

 

boardmapper.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">
<mapper namespace="board">
	<insert id="writeboard" parameterType="kr.co.korea.beans.BoardBean">
		 insert into rest_board(bid,btitle,bcontent,bwriter)
		 values(rboa_seq.nextval,#{btitle},#{bcontent},#{bwriter})
	</insert>
	
	<select id="readboard" parameterType="Integer" resultType="kr.co.korea.beans.BoardBean">
		select bid,btitle,bcontent,bwriter 
		from rest_board	
		where bid=#{bid}	
	</select>
	
	<select id="getboardlist" resultType="kr.co.korea.beans.BoardBean">
		select bid,btitle,bcontent,bwriter 
		from rest_board
	</select>
	
	<update id="updateboard" parameterType="kr.co.korea.beans.BoardBean">
		update rest_board 
		set bcontent=#{bcontent},btitle=#{btitle} 
		where bid=#{bid}
	</update>
	
	<delete id="deletebaord" parameterType="Integer">
		delete from rest_board
		where bid=#{bid}
	</delete>
</mapper>

mapper는 기본적인 sql문으로 조합

 

그다음 BoardBean이다.

 

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class BoardBean {
	
	private int bid;
	private String btitle;
	private String bcontent;
	private String bwriter;
	
}

이번에 하면서 lombok을 사용했는데

진짜.... bean이 너무 깔끔하게 됐다.

보통은 @Data 하나만으로 해결한다고는 하는데

아직 공부를 하는 중이라 3개만 정의했다.

 

BoardDao

 

@Repository
public class BoardDao {

	@Autowired
	private SqlSessionTemplate sqltemp;
	
	public void writeboard(BoardBean boardbean) {
		sqltemp.insert("board.writeboard",boardbean);
	}
	
	public BoardBean readboard(int bid) {
		return sqltemp.selectOne("board.readboard",bid);
	}
	
	public List<BoardBean> getboardlist(){
		return sqltemp.selectList("board.getboardlist");
	}
	
	public void updateBoard(BoardBean boardbean) {
		sqltemp.update("board.updateboard",boardbean);
	}
	
	public void deleteBoard(int bid) {
		sqltemp.delete("board.deletebaord",bid);
	}
	
	
}
@Service
public class BoardService {

	@Autowired
	private BoardDao boarddao;
	
	public void writeboard(BoardBean boardbean,String username) {
		boardbean.setBwriter(username);
		boarddao.writeboard(boardbean);
	}
	
	public BoardBean readboard(int bid) {
		return boarddao.readboard(bid);
	}
	
	public List<BoardBean> getboardlist(){
		return boarddao.getboardlist();
	}
	
	public void updateBoard(BoardBean boardbean) {
		boarddao.updateBoard(boardbean);
	}
	
	public void deleteBoard(int bid) {
		boarddao.deleteBoard(bid);
	}
	
}

Dao와 Service는 기존 CRUD와 큰 차이가 없다.

 

그리고 중요한 마지막 Controller

@RestController
@RequestMapping("/board")
public class BoardController {

	private static final Logger logger = LoggerFactory.getLogger(BoardController.class);

	@Autowired
	private BoardService boardservice;

	@GetMapping("")
	public List<BoardBean> list() {
		logger.info("boardlist");
		
		List<BoardBean> list = boardservice.getboardlist();
		
		return list;
	}

	@GetMapping("/{bid}")
	public BoardBean read(@PathVariable int bid) {
		
		logger.info("boardread");
		
		BoardBean boardbean = boardservice.readboard(bid);
		return boardbean;
	}

	@PostMapping("")
	public void write(@RequestBody BoardBean boardbean) {
		logger.info("write");
		
		String username="admin";
		
		boardservice.writeboard(boardbean,username);
	}
	
	@PutMapping("/{bid}")
	public void updateok(@RequestBody BoardBean boardbean,@PathVariable int bid) {
		logger.info("updateok");
      			  boardbean.setBid(bid);
		boardservice.updateBoard(boardbean);
		
	}
	
	@DeleteMapping("/{bid}")
	public void delete(@PathVariable int bid) {
		logger.info("delete");
		boardservice.deleteBoard(bid);
	}
	
}

먼저 기존의 Controller와의 차이는

RestController이다.

전에 ajax를 이용한 댓글 부분에서 사용했는데

이게 Rest에서도 json, xml 값을 받으니까

이렇게 정의해주면 된다.

그리고 각각 정의되어있는 어노테이션이 다른데

눈에 익숙한 것도 있고 안 익숙한 것도 있다. 

 

@GetMapping select할 경우 사용(list,상세보기의 경우)
@PostMapping insert(글 작성,회원 가입)
@PutMapping update(전부 수정)
@PatchMapping update(일부 수정)
@DeleteMapping delete(삭제)

여기서 본인이 사용할 부분을 골라서 사용하면 된다.

그런데 여기서 mapping의 value를 보면 자연스럽게 의문이 생긴다

우리가 흔히 알고 있던 것에서는

<c:url value="/board/update? bid=${bid}"/>이런 식으로

작성을 해서 mapping에서도 /update를 넣어주고

읽는 그런 방식을 했다.

그런데 Rest에서는 방식이 다르다.

기본적으로 get, post, put, delete로 각 구분이 가능하다는 점.

그리고 누가 봐도 추측이 가능해야 하다는 것이다.

예를 들어 내가 짠 Controller에서 본다면

 

http://localhost:8077/board

를 본다면 아마 '아 특정 게시판을 보는 거구나'할 것이고

http://localhost:8077/board/1

'특정 게시판의 특정 게시물 즉 상세보기구나' 할 것이다.

(혼자서 작성하면서 이해한 거라서 틀릴 수 있습니다...)

 

이렇게 작성을 다 하면 이제 확인을 해봐야 하는데

먼저 Spring legacy이므로 톰캣을 먼저 실행시켜준다. 

그 후 이 클립에서 Run As가 아닌

 

chrome.google.com/webstore/detail/postman/fhbjgbiflinjbdggehcddcbncdddomop?hl=ko

 

Postman

POSTMAN CHROME IS DEPRECATED DOWNLOAD THE UPDATED POSTMAN NATIVE APPS Postman Chrome is deprecated and is missing essential, new…

chrome.google.com

postman을 설치해줍니다.

이것은 간단하게 자신이 짠 코드가 정확히 작동을 해주는지 체크? 해주는 툴이다.

 

그리고 실행을 시킨 후에

확인을 해보면

 

1. get 전체 보기

2. get 상세 보기 

3.Post(insert)

여기서는 insert이므로 확인을 먼저 해야 합니다.

post 체크

url 체크

body체크

raw 체크

json체크 -> 기본으로 text가 되어있는데 Rest는 json이나 xml형식의 데이터만 이라는 것

text 하면 415 mediatype 오류 발생(경험....)

그리고 마지막에 send를 클릭해줍니다.

 

그리고 get으로 확인합니다.

참고로 bid는 sequence로 주고 있고

bwriter는 controller에서 임의로 지정했습니다.

 

4.put(update)

 

여기서는 자신이 수정할 게시물의 번호 bid를 정해주고

바꿀 내용을 작성해준 뒤 send를 클릭합니다.

 

5.Delete(delete)

2번 게시물을 삭제해주면

 

이와 같이 2번 게시물이 삭제된 것을 알 수 있습니다.

 

이렇게 하면 Spring으로

Rest Crud 구현이 가능합니다.

이제 이것을 view로 뿌리는 방법을 공부하고 다시 포스팅하겠습니다!

 

 

코드 

github.com/rwd117/Rest

'spring > 게시판' 카테고리의 다른 글

스프링 게시판 만들기 좋아요(2)  (0) 2021.04.24
스프링 게시판 좋아요 버튼  (0) 2021.04.24
스프링 시큐리티 예제  (0) 2021.04.07
스프링 이미지 업로드  (0) 2021.03.11
스프링 selectKey  (0) 2021.03.02