전자정부 프레임워크 공부

Spring Framework 게시판 1 - Spring MVC + MyBatis + MySQL

그랜파 개발자 2025. 5. 23. 14:30

Spring MVC + MyBatis + MySQL 기반 게시판 프로젝트를 posts 테이블을 중심으로 처음부터 끝까지 만드는 과정 입니다.
이 예제는 Eclipse IDE, Maven 기반의 Spring MVC 프로젝트를 사용하는 것을 기준으로 설명합니다.


📁 프로젝트 구성

spring-mybatis-board/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com.example.board/
│   │   │       ├── controller/
│   │   │       ├── mapper/
│   │   │       ├── service/
│   │   │       ├── service/impl/
│   │   │       └── vo/
│   │   ├── resources/
│   │   │   ├── mapper/
│   │   │   └── jdbc.properties
│   │   └── webapp/
│   │       └── WEB-INF/
│   │           ├── views/
│   │           └── web.xml
├── pom.xml

1. ✅ MySQL 테이블 생성

CREATE TABLE posts (
  id INT AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255),
  content TEXT,
  writer VARCHAR(100),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

2. ✅ Maven 프로젝트 생성 (Eclipse)

  • Eclipse → File → New → Maven Projec
  • Archetype: maven-archetype-webap
    reate a simple project (skip archetype selection)'을 체크
  • Group Id: com.example
  • Artifact Id: spring-mybatis-board
  • Packaging : war
  • finish

3. ✅ pom.xml 설정

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.example</groupId>
  <artifactId>spring-mybatis-board</artifactId>
  <version>1.0.0</version>
  <packaging>war</packaging>

    <dependencies>
        <!-- Spring MVC -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.30</version>
        </dependency>

        <!-- Servlet API (provided) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.1</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
          <groupId>org.apache.commons</groupId>
          <artifactId>commons-dbcp2</artifactId>
          <version>2.9.0</version>
        </dependency>

        <dependency>
          <groupId>com.mysql</groupId>
          <artifactId>mysql-connector-j</artifactId>
          <version>8.3.0</version> <!-- 또는 사용 가능한 최신 안정 버전 -->
        </dependency>

        <!-- JSTL (optional) -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

        <!-- Spring JDBC 추가 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.30</version>
        </dependency>

        <!-- MyBatis-Spring -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis-spring</artifactId>
          <version>2.0.7</version>
        </dependency>

        <!-- MyBatis -->
        <dependency>
          <groupId>org.mybatis</groupId>
          <artifactId>mybatis</artifactId>
          <version>3.5.15</version>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>

    </dependencies>

    <build>
        <finalName>spring-mybatis-board</finalName>
    </build>
</project>

4. ✅ web.xml 설정

(src/main/webapp/WEB-INF/web.xml)

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                             http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <welcome-file-list>
        <welcome-file>index.jsp</welcome-file>
    </welcome-file-list>
</web-app>

5. ✅ Spring 설정 파일

(src/main/webapp/WEB-INF/dispatcher-servlet.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans 
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context 
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/mvc 
           http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <!-- Controller 검색 -->
    <context:component-scan base-package="com.example.board.controller, com.example.board.service" />

    <!-- 기본 MVC 설정 (ViewResolver 등) -->
    <mvc:annotation-driven />

    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/views/" />
        <property name="suffix" value=".jsp" />
    </bean>
    
    <!-- 정적 리소스 처리 -->
    <mvc:resources mapping="/resources/**" location="/resources/" />
    
    <context:property-placeholder location="classpath:jdbc.properties" />

	<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource">
	  <property name="driverClassName" value="${jdbc.driverClassName}" />
	  <property name="url" value="${jdbc.url}" />
	  <property name="username" value="${jdbc.username}" />
	  <property name="password" value="${jdbc.password}" />
	</bean>
	
	<!-- JdbcTemplate 등록 -->
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
	    <property name="dataSource" ref="dataSource" />
	</bean>
	
	<!-- SqlSessionFactory 설정 -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="mapperLocations" value="classpath:mapper/*.xml" />
    </bean>

    <!-- Mapper 인터페이스 스캔 -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.example.board.mapper" />
    </bean>
    
</beans>

6. ✅ jdbc.properties

(src/main/resources/jdbc.properties)

dbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/boarddb?allowPublicKeyRetrieval=true&useSSL=false&serverTimezone=Asia/Seoul
jdbc.username=username
jdbc.password=password

7. ✅ VO 클래스

(PostVO.java)

package com.example.board.vo;

import java.util.Date;

public class PostVO {
    private int id;
    private String title;
    private String content;
    private String writer;
    private Date created_at;

    // 기본 생성자
    public PostVO() {
    }

    // 전체 필드를 사용하는 생성자
    public PostVO(int id, String title, String content, String writer, Date created_at) {
        this.id = id;
        this.title = title;
        this.content = content;
        this.writer = writer;
        this.created_at = created_at;
    }

    // Getter & Setter
    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public String getWriter() {
        return writer;
    }

    public void setWriter(String writer) {
        this.writer = writer;
    }

    public Date getCreated_at() {
        return created_at;
    }

    public void setCreated_at(Date created_at) {
        this.created_at = created_at;
    }

    @Override
    public String toString() {
        return "PostVO{" +
                "id=" + id +
                ", title='" + title + '\'' +
                ", content='" + content + '\'' +
                ", writer='" + writer + '\'' +
                ", created_at=" + created_at +
                '}';
    }
}

8. ✅ Mapper 인터페이스

(PostMapper.java)

package com.example.board.mapper;

import java.util.List;
import com.example.board.vo.PostVO;

public interface PostMapper {
    List<PostVO> getAllPosts();
    PostVO getPostById(int id);
    void insertPost(PostVO post);
    void updatePost(PostVO post);
    void deletePost(int id);
}

9. ✅ Mapper XML (PostMapper.xml)

src/main/resources/mapper/PostMapper.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="com.example.board.mapper.PostMapper">

  <select id="getAllPosts" resultType="com.example.board.vo.PostVO">
    SELECT * FROM posts ORDER BY id DESC
  </select>

  <select id="getPostById" resultType="com.example.board.vo.PostVO" parameterType="int">
    SELECT * FROM posts WHERE id = #{id}
  </select>

  <insert id="insertPost" parameterType="com.example.board.vo.PostVO">
    INSERT INTO posts(title, content, writer)
    VALUES(#{title}, #{content}, #{writer})
  </insert>

  <update id="updatePost" parameterType="com.example.board.vo.PostVO">
    UPDATE posts SET title = #{title}, content = #{content} WHERE id = #{id}
  </update>

  <delete id="deletePost" parameterType="int">
    DELETE FROM posts WHERE id = #{id}
  </delete>

</mapper>

 


10. ✅ Service 및 구현체

Service Interface

package com.example.board.service;

import java.util.List;
import com.example.board.vo.PostVO;

public interface PostService {
    List<PostVO> getAllPosts();
    PostVO getPostById(int id);
    void insertPost(PostVO post);
    void updatePost(PostVO post);
    void deletePost(int id);
}

Service Impl

package com.example.board.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.board.mapper.PostMapper;
import com.example.board.service.PostService;
import com.example.board.vo.PostVO;

@Service
public class PostServiceImpl implements PostService {

    @Autowired
    private PostMapper postMapper;

    public List<PostVO> getAllPosts() {
        return postMapper.getAllPosts();
    }

    public PostVO getPostById(int id) {
        return postMapper.getPostById(id);
    }

    public void insertPost(PostVO post) {
        postMapper.insertPost(post);
    }

    public void updatePost(PostVO post) {
        postMapper.updatePost(post);
    }

    public void deletePost(int id) {
        postMapper.deletePost(id);
    }
}

11. ✅ Controller

package com.example.board.controller;

import java.util.List;

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

import com.example.board.service.PostService;
import com.example.board.vo.PostVO;

@Controller
public class PostController {

    @Autowired
    private PostService postService;

    @GetMapping("/")
    public String list(Model model) {
        List<PostVO> posts = postService.getAllPosts();
        model.addAttribute("posts", posts);
        return "list";
    }

    @GetMapping("/write")
    public String writeForm() {
        return "write";
    }

    @PostMapping("/write")
    public String write(PostVO post) {
        postService.insertPost(post);
        return "redirect:/";
    }

    @GetMapping("/view")
    public String view(@RequestParam("id") int id, Model model) {
        PostVO post = postService.getPostById(id);
        model.addAttribute("post", post);
        return "view";
    }

    @PostMapping("/update")
    public String update(PostVO post) {
        postService.updatePost(post);
        return "redirect:/";
    }

    @GetMapping("/delete")
    public String delete(@RequestParam("id") int id) {
        postService.deletePost(id);
        return "redirect:/";
    }
}

12. ✅ JSP View 예시 (/WEB-INF/views/)

  • list.jsp, write.jsp, view.jsp, edit.jsp 등 작성

예: list.jsp

<%@ page contentType="text/html; charset=UTF-8" %>
<html>
<head>
  <title>게시판</title>
</head>
<body>
  <h2>게시판 목록</h2>
  <a href="write">글쓰기</a>
  <table border="1">
    <tr><th>번호</th><th>제목</th><th>작성자</th><th>작성일</th></tr>
    <c:forEach var="post" items="${posts}">
      <tr>
        <td>${post.id}</td>
        <td><a href="view?id=${post.id}">${post.title}</a></td>
        <td>${post.writer}</td>
        <td>${post.created_at}</td>
      </tr>
    </c:forEach>
  </table>
</body>
</html>

 


✅ 마무리

이제 프로젝트를 Tomcat 서버에 배포하면 Spring MVC + MyBatis + MySQL 게시판이 완성됩니다.

 

http://localhost:8080/spring-mybatis-board/