본문 바로가기
BE/Spring

Spring Boot + Gradle + Mybatis + MySQL REST API 서버 만들기 (2)

by Day0404 2021. 5. 13.
728x90
반응형

Spring Boot Gradle Mybatis MySQL을 통한 REST API 서버 만들기

지난번에 REST API 서버를 만들기 위한 프로젝트 생성 및 MySQL 연동을 진행했습니다.

혹시나 내용이 궁금하신 분이나 프로젝트 생성을 안 하신 분은 아래 글을 먼저 읽고 오시면 좋습니다!

2021.05.11 - [BE/Spring] - Spring Boot + Gradle + Mybatis + MySQL REST API 서버 만들기 (1)

 

Spring Boot + Gradle + Mybatis + MySQL REST API 서버 만들기 (1)

Spring Boot Gradle Mybatis REST API 서버 만들기 지금 제가 진행하고 있는 프로젝트의 API 서버가 Spring Boot 기반으로 되어 있기 때문에 복습도 할 겸 Spring Boot에 대한 내용도 글을 써보려 합니다. 사실 지..

day0404.tistory.com

 

위 글까지 진행하고 오시면 프로젝트 생성 및 Controller 생성까지 진행되어 있을 겁니다.

이번 글에서는 전반적인 프로젝트 구성을 하고 실제 API를 호출하여 데이터를 받아오는 것 까지 진행할 예정입니다.

 

프로젝트 구조 설계하기

  • controller
  • dto
  • mapper
  • service
  • resources/mapper

일단 간단한 예제형이기 때문에 위 내용처럼 구조를 짰습니다.

그리고 MySQL에 테스트 데이터를 넣어놨습니다.

 

DTO

테스트 프로젝트이기 때문에 DTO로 만들었습니다.

보통 Entity, Domain 등으로 만드시는 분도 봤었고 패키지를 Domain 등으로 만들고 그 안에 DTO를 넣으시는 분들도 봤습니다. 저도 뭐가 정답인지는 잘 모르겠으나 저는 Domain 패키지 안에 UserDto나 User라고 정의하여 사용합니다.

간단한 예제이기 때문에 @Getter, @Setter 어노테이션을 사용하여 편하게 작성하였고, 실제 프로젝트에서는 @Setter를 막아야 하는 부분이 생길 수 있기 때문에 @Getter,@Setter 남발은 좋지 않습니다!

package com.example.demo.dto;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class TestDto {
	private String name;
	private int age;
	private String email;
}

 

Controller

지난번에 만들었던 Hello World 테스트는 그대로 뒀습니다.

@RequiredArgsConstructor 어노테이션은 final이나 @NonNull이 붙은 필드에 생성자를 생성해줍니다.

보통 @Autowired를 사용하는 경우가 많은데 저는 할 수 있다면 필드 주입은 최대한 피하려고 하는 편입니다.

(Autowired를 남발하다가 순환 참조에 걸린 적이 있어서 굉장히 당황했던 기억이 있습니다.)

이러한 순환 참조를 피하기 위해서라도 저는 생성자 주입을 하려고 하는 편입니다.

package com.example.demo.controller;

import com.example.demo.dto.TestDto;
import com.example.demo.service.TestService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequiredArgsConstructor
public class TestController {

	private final TestService testService;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public Object test() {
		return "Hello World!";
	}

	@RequestMapping(value = "/user", method = RequestMethod.GET)
	public List<TestDto> getUser() {
		return testService.getUserList();
	}

}

Mapper

DAO로 사용하시는 분들도 많이 봤었는데 저는 @Mapper을 사용하여 Mapper로 사용하는 게 편하더라고요.

Mapper 인터페이스만 구현해서 Service에서 바로 사용이 가능합니다.

package com.example.demo.mapper;

import com.example.demo.dto.TestDto;
import org.apache.ibatis.annotations.Mapper;

import java.util.List;

@Mapper
public interface TestMapper {

	List<TestDto> getUserList();
}

 

Service

기본적으로 인터페이스를 두고 implements 하는 형태로 만들었습니다.

package com.example.demo.service;

import com.example.demo.dto.TestDto;

import java.util.List;

public interface TestService {

	public List<TestDto> getUserList();
}
package com.example.demo.service;

import com.example.demo.dto.TestDto;
import com.example.demo.mapper.TestMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@RequiredArgsConstructor
public class TestServiceImpl implements TestService {

	private final TestMapper testMapper;

	@Override
	public List<TestDto> getUserList() {
		return testMapper.getUserList();
	}
}

resources/mapper

resources 안에 mapper 디렉터리를 생성해주고 TestMapper.xml이라는 mapper.xml 파일을 생성해줍니다.

이곳에 쿼리들이 들어가게 됩니다.

일단은 조회하는 API만 만들었기 때문에 간단합니다.

주의해야 할 부분은 mapper namespace와 id, resultType 등을 주의해야 합니다.

오타 나면 invalidInvalid bound statement 에러를 볼 수 있습니다.

<?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.demo.mapper.TestMapper">

    <select id="getUserList" resultType="com.example.demo.dto.TestDto">
        SELECT * FROM test.user
    </select>

</mapper>

 

이렇게 프로젝트 구조 잡으시고 실행을 시켜서 GET방식이기 때문에 인터넷 URL에서 바로 확인이 가능합니다.

아까 컨트롤러에서 /user라고 URL 패턴을 지정했기 때문에 아래와 같이 입력하면 결과를 볼 수 있습니다.

URL에 http://localhost:8084/user

 

혹시나 Invalid bound statement 에러가 나오신다면 application.yml 파일을 아래와 같이 수정해줍니다.

이렇게 수정하시고 다시 실행하면 정상적으로 데이터가 나오실 겁니다.

 

반응형

댓글