지난 API에 이어서 오늘은 mysql을 통해 DB를 사용해보았다.
서버를 열고, 가입한 회원의 정보를 GET API로 받아보았다.
List < User > users = new ArrayList<>();
회원 정보를 담는 리스트이고, GET API는 users에 담긴 User 객체를 가져와 출력한다.
그러나, 해당 데이터들은 메모리(RAM)에 담겨있다. 때문에 서버가 종료하면 -> 다! 사라지는 것이다.
위와 같은 그림에서 서버가 종료된다면, RAM에 있는 정보, 유저 정보가 모두 사라진다.
=> CPU - RAM - DISK 이 관계에서 RAM에 있는 회원 정보 데이터들을 DISK 에 저장해야 한다.
서버 어플리케이션은 DB를 사용해 데이터를 저장한다.
관계형 데이터베이스 관리 시스템이다.
재수강했던 데이터베이스 기초 수업 때부터 냄새를 맡았다..
내 맥북에서는 sql을 사용할 수 없다는 걸..
homebrew로 수도 없이 깔고, 지우고, 구글링하고, 스택 오버플로우도 찾아보았지만 계속해서 오류가 발생했다. 결국 homebrew 사용하지 않고 mysql community server를 설치하였다.
이전 수업에서는 SQL Developer를 사용하였기에, terminal에서 한 줄씩 SQL문을 작성하는 게 신기하다.
Spring 서버가 Mysql DB에 접속할 수 있도록 한다.
//resources/application.yml
spring :
datasource:
url: "jdbc:mysql://localhost/library" // 스프링이 접근할 데이터베이스
username: "root"
password : ""
driver-class-name : com.mysql.cj.jdbc.Driver //데이터베이스에 접근할 프로그램
user 데이터가 저장될 user 테이블을 생성한다
기존에는 List 형태로 User 데이터를 저장/불러왔지만 <-> JdbcTemplete을 활용하여 데이터 베이스에 접근할 수 있도록 한다.
jdbcTemplete으 사용하면 -> sql을 MySQL에 날릴 수 있다.
package com.group.libraryapp.controller.user;
import com.group.libraryapp.dto.user.request.UserRequest;
import com.group.libraryapp.dto.user.response.UserResponse;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
@RestController
public class UserController {
private final JdbcTemplate jdbcTemplate;
public UserController(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
@PostMapping("/user")
void storeUser(@RequestBody UserRequest userRequest) {
String sql = "insert into user (name, age) values (?, ?)"; //sql
jdbcTemplate.update(sql, userRequest.getName(), userRequest.getAge());
// ? 부분에 각각 getName(), getAge()가 들어간다
}
//기존 코드
/*
@GetMapping("/user")
List<UserResponse> getUser() {
String sql = "select * from user";
return jdbcTemplate.query(sql, new RowMapper<UserResponse>() {
@Override
public UserResponse mapRow(ResultSet rs, int rowNum) throws SQLException {
long id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age") ;
return new UserResponse((int) id, name, age);
}
});
}
*/
//lambda로 수정한 코드
@GetMapping("/user")
List<UserResponse> getUser() {
String sql = "select * from user";
return jdbcTemplate.query(sql, (rs, rowNum) -> {
// rs에 값을 담아와서, 이를 userResponse 객체에 집어넣음
// 이 과정을 rowNum만큼 수행
long id = rs.getInt("id");
String name = rs.getString("name");
int age = rs.getInt("age") ;
return new UserResponse((int) id, name, age);
});
}
}
아마 RowMapper<>의 경우 RN에서 forEach와 비슷하다는 생각이 들었다.
어제 진행했던 API 제작 + mySQL 연동 과정을 다시 지우고, 스스로 코드를 작성했다.
강의를 들을 때는 생각하지 못했던, 디렉토리에서 dto는 어느 위치에 와야 하는지, controller와 user 중 어떤 디렉토리가 상위 개념인지, 왜 필드가 유사한 User, UserRequest, UserResponse 클래스가 각각 있어야 하는지를 스스로 궁금증을 떠올리고, 해소할 수 있었다.
사실, 코드를 지울 때만 해도 내가 잘 떠올릴 수 있을까..? 하는 의문이었지만,
막상 코드를 지우고 나니, 수업 순서가 아닌 내가 필요하다고 생각하는 로직에 맞추어 클래스를 생성해나갈 수 있었다. 시간이 오래걸리긴 했지만, 그보다 많은 개념과 왜! 를 알 수 있었다.
조그맣지만 웹에서 서비스가 있고, 서비스를 사용하였을 때 (회원가입을 했을 때), 내가 개발자의 입장에서 새로운 데이터가 추가된 DB를 볼 수 있다는 게 너무 재미있었다. !
실제 서비스라면, 많은 실제 유저들의 데이터를 볼 수 있다는 점이 기대된다.