[Spring Boot] 09. MyBatis 설정 및 회원관리 게시판 제작하기

하림·2024년 8월 29일

Spring

목록 보기
4/16
post-thumbnail

1. MyBatis

1.1 MyBatis

MyBatis는 Java 객체와 SQL 문 사이에서 자동으로 매핑을 지원하는 ORM(Object Relational Mapping) 프레임워크입니다. 이를 통해 Java 코드에서 SQL을 직접 작성하지 않고도 데이터베이스와 상호 작용할 수 있게 해줍니다.


1.2 MyBatis의 특징

MyBatis는 다음과 같은 특징이 있습니다.

  • JDBC 작업 간소화: MyBatis는 JDBC를 사용하여 관계형 데이터베이스에 액세스하는 작업을 캡슐화하여 중복 작업을 줄이고 간소화합니다.
  • SQL 분리: SQL 쿼리를 XML 파일 형식의 매퍼(mapper)로 관리하여 프로그램 코드와 분리합니다.
  • 자동 매핑: SQL 쿼리 실행 결과를 Java 객체에 자동으로 매핑해 줍니다.
  • 빠른 개발: 코드의 간결함과 자동화된 매핑을 통해 개발 속도와 생산성을 향상시킵니다.
  • 사용 편의성: 기존 JDBC에 비해 사용이 간편하며 학습 부담이 적습니다.

1.3 Mybatis의 아키텍처

MyBatis의 아키텍처는 기존 JDBC 프로그래밍과 차이가 있습니다. 기존 JDBC 프로그래밍에서는 Repository(DAO)에서 직접 JDBC API를 통해 데이터베이스에 접근했습니다. 하지만 MyBatis를 사용할 경우, Repository와 JDBC API 사이에 MyBatis가 위치하여 더 편리한 데이터베이스 접근을 제공합니다.


1.4 Mybatis의 Mapper

DAO 클래스를 사용하면 SQL문을 수정할 때마다 클래스를 다시 컴파일해야 하고, SQL문을 한 곳에서 통합 관리하기 어렵습니다. MyBatis는 Mapper를 통해 SQL문을 Java 코드로부터 완전히 분리하여 SQL문에 대한 통합 관리를 가능하게 합니다. Mapper는 XML 형식의 문서로 작성되며, 이를 통해 SQL문을 독립적으로 관리할 수 있습니다.


1.5 Mapper의 Doctype

<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">




2. 프로젝트 생성 및 설정

2.1 프로젝트 생성 및 의존성 설정하기

프로젝트를 생성하는 방법은 다음과 같습니다.

  1. 메뉴에서 File > New > Spring Starter Project 를 선택합니다.
  2. 프로젝트 생성창이 뜨면 프로젝트를 설정합니다.
  3. 생성할 프로젝트에 필요한 의존성을 설정합니다. MyBatis Framework를 사용하기 위해 필요한 의존성은 다음과 같습니다: Spring Web, Lombok, JDBC API, Oracle Driver, Mybatis Framework

프로젝트 생성이 완료되었습니다.


2.2 JSP 설정 및 기본 프로젝트 구성하기

JSP 설정과 기본 프로젝트 구성 방법에 대해서는 이 링크를 참조하세요.




3. 회원관리 게시판 제작을 위한 MyBatis 설정

3.1 소스코드 작성하기

프로퍼티 파일에 값을 설정합니다. 다음과 같이 resources/application.properties 파일을 작성합니다.

# Mybatis Mapper의 위치 설정 (src/main/resource 하위에 폴더 생성)
# mybatis.mapper 하위의 모든 폴더에 존재하는 xml 파일을 매퍼로 사용하겠다는 선언
mybatis.mapper-locations=classpath:mybatis/mapper/**/**.xml

서비스 인터페이스를 생성합니다. 다음과 같이 com.edu.springboot.jdbc.IMemberService.java 파일을 작성합니다.

package com.edu.springboot.jdbc;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;

/* 컨트롤러와 DAO(XML) 사이에서 매개 역할을 하는 인터페이스이다.
 * JdbcTemplate에서는 @Service를 사용했지만 mybatis에서는 @Mapper를 사용한다.
 * 컨트롤러에서 인터페이스에 정의된 추상메서드를 호출하면 연결된 Mapper의 특정 엘리먼트가 호출되어 실행되는 구조를 가진다. */
@Mapper
public interface IMemberService {
	public List<MemberDTO> select();
	public int insert(MemberDTO memberDTO);
	public MemberDTO selectOne(MemberDTO memberDTO);
	public int update(MemberDTO memberDTO);
	public int delete(MemberDTO memberDTO);
}

DTO를 생성합니다. 다음과 같이 com.edu.springboot.jdbc.MemberDTO.java 파일을 작성합니다.

package com.edu.springboot.jdbc;

import lombok.Data;

@Data
public class MemberDTO {
	private String id;
	private String pass;
	private String name;
	private String regidate;
}

매퍼를 생성합니다. 다음과 같이 resources/mybatis/mapper/MemberDAO.xml 파일을 작성합니다.

<?xml version="1.0" encoding="UTF-8"?>

<!-- Mapper 파일을 구성하기 위한 Doctype 설정 -->
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 컨트롤러와 Mapper 사이에서 매개 역할을 하는 인터페이스를 namespace로 지정한다.
xml 파일에서는 클래스에 대한 import가 불가능하므로 아래와 같이 패키지의 풀경로를 지정해야 한다. -->
<mapper namespace="com.edu.springboot.jdbc.IMemberService">

</mapper>

해당 파일에서 실행에는 문제가 없으나 'downloading external resource is disabled' 라는 오류와 함께 빨간 줄이 생깁니다. 이는 다음과 같은 방법으로 해결할 수 있습니다.

  1. Settings > XML(Wild Web Developer)로 이동합니다.
  2. Download external resources like referenced DTD, XSD 를 체크합니다.

모든 설정이 완료되면 빨간 줄이 사라집니다. 이제 Mybatis를 사용하기 위한 준비가 완료되었습니다.




4. 회원목록 조회

4.1 소스코드 작성하기

홈을 생성합니다. 다음과 같이 webapp/WEB-INF/views/home.jsp 파일을 작성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>스프링 부트 프로젝트</h2>
	<ul>
		<li><a href="/">루트</a></li>
	</ul>
	
	<h2>Mybatis로 구현한 회원관리</h2>
	<ul>
		<li><a href="./list.do">회원목록</a></li>
	</ul>
</body>
</html>

컨트롤러를 생성합니다. 다음과 같이 com.edu.springboot.MainController.java 파일을 작성합니다.

package com.edu.springboot;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import com.edu.springboot.jdbc.IMemberService;

@Controller
public class MainController {
	
	/* 서비스 인터페이스를 통해 Mapper의 메서드를 호출하므로 여기서 자동주입 받아서 준비한다.
	 * 해당 인터페이스는 @Mapper 어노테이션이 부착되어 있으므로 컨테이너가 시작될 때 자동으로 빈이 생성된다. */
	@Autowired
	IMemberService dao;
	
	@RequestMapping("/")
	public String home() {
		return "home";
	}
	
	// 회원목록
	@RequestMapping("/list.do")
	public String list(Model model) {
		/* dao.select() : 서비스 인터페이스의 추상메서드를 호출한다.
		 * 그러면 인터페이스와 연결된 Mapper 파일에 정의된 특정 엘리먼트가 호출되어 실행된다. */
		model.addAttribute("memberList", dao.select());
		return "list";
	}
}

매퍼를 생성합니다. 다음과 같이 resources/mybatis/mapper/MemberDAO.xml 파일에 코드를 추가합니다.

<?xml version="1.0" encoding="UTF-8"?>

<!-- Mapper 파일을 구성하기 위한 Doctype 설정 -->
<!DOCTYPE mapper
	PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
	"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<!-- 컨트롤러와 Mapper 사이에서 매개 역할을 하는 인터페이스를 namespace로 지정한다.
xml 파일에서는 클래스에 대한 import가 불가능하므로 아래와 같이 패키지의 풀경로를 지정해야 한다. -->
<mapper namespace="com.edu.springboot.jdbc.IMemberService">
	<!-- 매퍼에서 쿼리문을 실행하기 위한 엘리먼트
	: DML의 4가지 쿼리와 동일한 이름의 엘리먼트가 존재한다.
	즉 select 쿼리는 <select> 엘리먼트를 사용하면 된다.
	
	하위 프로퍼티
	- id : 컨트롤러에서 호출하기 위한 메서드명을 기술한다. Java와 같이 메서드의 원형을 사용하지 않고, 단지 메서드명만 명시하면 된다.
	- resultType : 쿼리문 실행 후 반환할 결과의 타입을 명시한다.
		select문의 경우 ResultSet이 반환되므로, 이를 저장하기 위한 DTO를 지정하면 되고 개수가 많은 경우 Mapeer가 알아서 List에 add() 해준다.
		insert, delete, update와 같이 행의 변화가 있는 쿼리문을 결과로 int를 반환하므로 resultType은 명시하지 않는다. -->

	<!-- 컨트롤러에서 select()를 호출하면 id 속성에 함수명과 동일한 속성값을 가진 엘리먼트가 실행된다. -->
	<select id="select"
		parameterType="com.edy.sprintboot.jdbc.MemberDTO"
		resultType="com.edy.sprintboot.jdbc.MemberDTO">
		SELECT * FROM member ORDER BY regidate DESC
	</select>
</mapper>

뷰를 생성합니다. 다음과 같이 webapp/WEB-INF/views/list.jsp 파일에 코드를 추가합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="jakarta.tags.core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>회원리스트</h2>
	<table border="1">
		<tr>
			<th>아이디</th>
			<th>패스워드</th>
			<th>이름</th>
			<th>가입일</th>
			<th></th>
		</tr>
		<c:forEach items="${ memberList }" var="row" varStatus="loop">
			<tr>
				<td>${ row.id }</td>
				<td>${ row.pass }</td>
				<td>${ row.name }</td>
				<td>${ row.regidate }</td>
				<td>
					<a href="edit.do?id=${ row.id }">수정</a>
					<a href="delete.do?id=${ row.id }">삭제1</a>
				</td>
			</tr>
		</c:forEach>
	</table>
	<a href="regist.do">회원등록</a>
</body>
</html>

이제 회원 목록을 조회할 수 있습니다.


4.2 실행하기

다음과 같이 실행됩니다.

'회원목록' 링크를 클릭하면 데이터베이스에 저장된 회원목록을 확인할 수 있습니다.

회원목록 조회 기능이 성공적으로 구현되었습니다.




5. 회원정보 등록

5.1 소스코드 작성하기

컨트롤러를 생성합니다. 다음과 같이 com.edu.springboot.MainController.java 파일에 코드를 추가합니다.

// 회원정보 등록 : 가입폼은 GET 방식, 등록처리는 POST 방식으로 매핑한다.
@GetMapping("/regist.do")
public String regist1() {
	// 등록 페이지 포워드만 처리
	return "regist";
}
@PostMapping("/regist.do")
public String regist2(MemberDTO memberDTO) {
	// 전송된 폼값을 커맨드객체를 통해 일괄적으로 받은 후 DAO의 메서드 호출
	int result = dao.insert(memberDTO);
	if (result == 1) System.out.println("회원정보가 등록되었습니다.");
	// 입력에 성공하면 목록으로 이동한다.
	return "redirect:list.do";
}

매퍼를 생성합니다. 다음과 같이 resources/mybatis/mapper/MemberDAO.xml 파일에 코드를 추가합니다.

<!-- 하위 프로퍼티
- paramterType : 메서드 호출 시 파라미터로 사용할 클래스명을 명시한다.
		개발자가 직접 정의한 클래스 외에도 Map, List와 같은 컬렉션을 사용할 수 있다.
	만약 필요하지 않다면 생략할 수 있다. -->
<!-- 회원등록 : parameterType으로 명시한 DTO 객체의 멤버변수명을 통해 쿼리문의 인파라미터를 설정한다.
EL과 동일하게 DTO에 정의한 getter를 통해 값을 얻어와 세팅한다.
insert의 경우 반환타입은 무조건 정수형이므로 resultType은 생략할 수 있다. -->
<insert id="insert"
	parameterType="com.edu.springboot.jdbc.MemberDTO">
	INSERT INTO member (id, pass, name) VALUES (#{id}, #{pass}, #{name})
</insert>

뷰를 생성합니다. 다음과 같이 webapp/WEB-INF/views/regist.jsp 파일을 작성합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>회원등록</h2>
	<form action="regist.do" method="post">
		<table border="1">
			<tr>
				<th>아이디</th>
				<td><input type="text" name="id" value="" /></td>
			</tr>
			<tr>
				<th>패스워드</th>
				<td><input type="text" name="pass" value="" /></td>
			</tr>
			<tr>
				<th>이름</th>
				<td><input type="text" name="name" value="" /></td>
			</tr>
		</table>
		<input type="submit" value="전송하기" />
	</form>
</body>
</html>

이제 회원정보를 등록할 수 있습니다.


5.2 실행하기

다음과 같이 실행됩니다.

'회원등록' 링크를 클릭하면 회원정보를 입력할 수 있는 페이지로 이동합니다.

등록할 회원정보를 입력합니다.

입력한 후 '전송하기' 버튼을 클릭하면 회원정보가 등록된 후 회원목록 페이지로 이동합니다. 목록에서 회원정보가 정상적으로 등록되었음을 확인할 수 있습니다.

콘솔에는 다음과 같이 출력됩니다.

회원정보가 등록되었습니다.

회원정보 등록 기능이 성공적으로 구현되었습니다.




6. 회원정보 수정

6.1 소스코드 작성하기

컨트롤러를 생성합니다. 다음과 같이 com.edu.springboot.MainController.java 파일에 코드를 추가합니다.

// 회원정보 수정 1 : 기존 회원정보를 가져와서 수정폼 구성
@GetMapping("/edit.do")
public String edit1(MemberDTO memberDTO, Model model) {
	// 기존 레코드를 얻어온 후 View로 전달
	memberDTO = dao.selectOne(memberDTO);
	model.addAttribute("dto", memberDTO);
	return "edit";
}
// 회원정보 수정 2 : 수정된 내용을 통해 레코드 업데이트 처리
@PostMapping("/edit.do")
public String edit2(MemberDTO memberDTO) {
	int result = dao.update(memberDTO);
	if (result == 1) System.out.println("회원정보가 수정되었습니다.");
	return "redirect:list.do";
}

매퍼를 생성합니다. 다음과 같이 resources/mybatis/mapper/MemberDAO.xml 파일에 코드를 추가합니다.

<!-- 회원정보 수정 1 : 회원정보를 select한 후 DTO에 저장 후 반환한다. -->
<select id="selectOne"
	parameterType="com.edu.springboot.jdbc.MemberDTO"
	resultType="com.edu.springboot.jdbc.MemberDTO">
	SELECT * FROM member WEHRE id=#{id}
</select>
<!-- 회원정보 수정 2 : 회원정보를 수정한 결과를 반환하므로 resultType은 명시하지 않는다. -->
<update id="update"
	parameterType="com.edu.springboot.jdbc.MemberDTO">
	UPDATE member SET pass=#{pass} name=#{name} WHERE id=#{id}
</update>

뷰를 생성합니다. 다음과 같이 webapp/WEB-INF/views/edit.jsp 파일에 코드를 추가합니다.

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h2>회원정보 수정</h2>
	<form action="edit.do" method="post">
		<table border="1">
			<tr>
				<th>아이디</th>
				<td><input type="text" name="id" value="${ dto.id }" readonly /></td>
			</tr>
			<tr>
				<th>패스워드</th>
				<td><input type="text" name="pass" value="${ dto.pass }" /></td>
			</tr>
			<tr>
				<th>이름</th>
				<td><input type="text" name="name" value="${ dto.name }" /></td>
			</tr>
		</table>
		<input type="submit" value="전송하기" />
	</form>
</body>
</html>

이제 회원정보를 조회하여 해당 회원정보를 수정할 수 있습니다.


6.2 실행하기

다음과 같이 실행됩니다.

수정할 회원의 '수정' 링크를 클릭하여 수정할 정보를 입력합니다.

'전송하기' 버튼을 누르면 회원 정보가 수정된 후 회원목록 페이지로 이동합니다. 목록에서 회원정보가 정상적으로 수정되었음을 확인할 수 있습니다.

콘솔에는 다음과 같이 출력됩니다.

회원정보가 수정되었습니다.

회원정보 수정 기능이 성공적으로 구현되었습니다.




7. 회원정보 삭제

7.1 소스코드 작성하기

컨트롤러를 생성합니다. 다음과 같이 com.edu.springboot.MainController.java 파일에 코드를 추가합니다.

// 회원정보 삭제
@RequestMapping("/delete.do")
public String delete(MemberDTO memberDTO) {
	// 아이디를 파라미터로 받은 후 delete 메서드 호출
	int result = dao.delete(memberDTO);
	if (result == 1) System.out.println("회원정보가 삭제되었습니다.");
	return "redirect:list.do";
}

매퍼를 생성합니다. 다음과 같이 resources/mybatis/mapper/MemberDAO.xml 파일에 코드를 추가합니다.

<!-- 회원정보 삭제 -->
<delete id="delete"
	parameterType="com.edu.springboot.jdbc.MemberDTO">
	DELETE FROM member WHERE id=#{id}
</delete>

이제 회원정보를 삭제할 수 있습니다.


7.2 실행하기

다음과 같이 실행됩니다.

수정할 회원의 '삭제' 링크를 클릭하면 회원 정보가 삭제된 후 회원목록 페이지로 이동합니다. 목록에서 회원정보가 정상적으로 삭제되었음을 확인할 수 있습니다.

콘솔에는 다음과 같이 출력됩니다.

회원정보가 삭제되었습니다.

회원정보 삭제 기능이 성공적으로 구현되었습니다.

0개의 댓글