스파르타 코딩의 <Java 심화 단기 부트캠프> 를 수강하며 스프링 입문 강의에 나와있는 메모장 프로젝트에 대해 정리.
MySQL 설치 및 Spring 프로젝트에 연결 후 테이블 생성하기
- https://dev.mysql.com/downloads/mysql/ 접속 후 자신의 OS에 맞는 버전을 다운 받아 설치
- 터미널을 열어 cd /usr/local/mysql/bin 입력하여 위치로 이동
- ./mysql -u root -p 입력 후 MySQL 설치 시 설정한 비밀 번호로 접속
- CREATE DATABASE memo; 로 memo 테이블 생성 후 show databases; 명령어로 잘 생성되었는지 확인
- Intellij 오른쪽 상단의 DB 누른 후 + 버튼 → Data Source → MySQL 선택 → DB 아이디와 비밀번호 및 테이블 명 입력 → OK
위의 과정을 마치면 다음과 같이 MySQL이 내 스프링 프로젝트와 잘 연결되었음을 확인 할 수 있다.
데이터베이스를 연동하고나면 콘솔창이 뜨게 되는데 ( 안 뜨거나 창을 내렸을 경우 위의 콘솔창 아이콘 클릭 ) 이곳에 sql문을 작성하면 된다. memo 테이블에 필요한 칼럼들로는 다음과 같다.
- id : 각 메모들을 구분할 특정 id / varchar(500) / not null
- username : 메모 작성자 / varchar(255) / not null
- contents : 메모 내용 / bigint / not null / primary key / auto_increment
※ auto_increment : 컬럼의 값이 중복되지 않게 1씩 자동으로 증가시켜 고유 번호를 생성해주는 제약 조건
JDBCtemplate
JDBCtemplate를 사용하는 이유 → Connection 연결과 종료, Statement 준비 및 실행 등의 반복적이고 중복되는 작업들을 대신 처리하기 위함
JDBCtemplate를 사용하기 위해서는
1. application.properties에 DB에 접근하기 위한 정보를 작성해줌
spring.datasource.url=jdbc:mysql://localhost:3306/memo
spring.datasource.username=root
spring.datasource.password={비밀번호}
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
2. build.gradle의 dependencies에 JDBC 라이브러리와 MySQL 추가
implementation 'mysql:mysql-connector-java:8.0.28'
implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'
❗️추가 후 꼭 코끼리 아이콘을 눌러 추가된 사항이 반영되도록 해주기
3. DB 연결이 필요한 곳에서 JDBCtemplate를 주입받아 사용
private final JdbcTemplate jdbctemplate;
public MemoRepository(JdbcTemplate jdbcTemplate) {
this.jdbcTemplate = jdbcTemplate;
}
JDBCtemplate을 사용할 때는 insert, update, delete 쿼리 실행 시 update( )를 사용한다.
예시 >
String sql = "INSERT INTO memo (username, contents) VALUES (?, ?)";
jdbcTemplate.update(sql, "Terry", "오늘 하루도 화이팅!");
String sql = "UPDATE memo SET username = ? WHERE id = ?";
jdbcTemplate.update(sql, "Terry", 1);
String sql = "DELETE FROM memo WHERE id = ?";
jdbcTemplate.update(sql, 1);
첫번째 파라미터로 sql문을 받고 그 이후 파라미터로 ?에 들어갈 데이터를 유동적으로 받는다.
select 쿼리 실행 시 query( )를 사용한다.
예시 >
String sql = "SELECT * FROM memo";
return jdbcTemplate.query(sql, new RowMapper<MemoResponseDto>() {
@Override
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException {
// SQL 의 결과로 받아온 Memo 데이터들을 MemoResponseDto 타입으로 변환해줄 메서드
Long id = rs.getLong("id");
String username = rs.getString("username");
String contents = rs.getString("contents");
return new MemoResponseDto(id, username, contents);
}
});
보통 select로 조회 시 받아오는 데이터가 여러개이기 때문에 RowMapper를 사용한다.
RowMapper는 인터페이스이기 때문에 익명 클래스로 구현하여 처리한다.
public MemoResponseDto mapRow(ResultSet rs, int rowNum) throws SQLException
위 예시 속 메소드로 살펴보자면 ResultSet으로 값을 읽어와 MemoResponseDto에 저장하는 일을 rowNum만큼 반복한다는 뜻.
최종적으로 MemoResponseDto를 데이터 타입으로 하는 List를 반환하게 된다.
CRUD 기능 구현
먼저, 만들어야 하는 api 목록은 다음과 같다.
이에 따라 데이터베이스의 테이블을 나타내는 엔티티인 Memo 클래스, 클라이언트와 서버가 JSON의 형태로 데이터를 주고 받기 때문에 이를 자바 객체로 변환해 처리하고 관리하기 위한 MemoRequestDto와 MemoResponseDto 클래스, 이 모든 것을 처리하는 MemoController 클래스가 필요하다.
MemoController.java
@RestController : JSON 형태로 객체를 반환한다. @Controller에 @ResponseBody를 붙인 것과 동일한 동작 과정
@RequesMapping( ) : 매핑되는 url의 앞부분이 모두 "/api"로 동일하므로 RequestMapping을 사용하여 처리
이 컨트롤러에 메모 생성하기, 조회하기, 수정하기, 삭제하기 기능을 구현한다.
생성하기 기능 구현
@RequestBody : 클라이언트에서 비동기 처리로 요청을 보낼 때 본문(body)에 데이터를 담아 보내야 하는데, 이 때 JSON의 형태로 데이터를 담아 보내게 된다. 따라서 이 어노테이션을 붙이면 http 요청의 본문이 JSON의 형태로 서버에 전달되게 된다.
KeyHolder keyHolder = new GeneratedKeyHolder( ) : id 칼럼의 제약 조건으로 auto_increment가 있기 때문에 id가 자동 생성된다. 이 자동 생성되는 키 값을 알고 싶을 때 사용하는 것이 KeyHolder.
Memo memo = new Memo(requestDto);
먼저 클라이언트가 보낸 데이터가 JSON의 형태로 넘어오기 때문에 자바 객체로 변환해주는 작업을 거친다. 이 부분은 memo 엔티티에 생성자의 형태로 구현해준다.
Memo.java
@Getter
@Setter
@NoArgsConstructor
public class Memo {
private Long id;
private String username;
private String contents;
public Memo(MemoRequestDto requestDto) {
this.username = requestDto.getUsername();
this.contents = requestDto.getContents();
}
}
KeyHolder로 id 값을 받아오고 JDBCtemplate의 update를 사용하여 DB에 저장한다.
후에는 MemoResponseDto에 담아 JSON으로 변환 후 클라이언트로 보내준다.
MemoResponseDto.java
@Getter
public class MemoResponseDto {
private Long id;
private String username;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.username = memo.getUsername();
this.contents = memo.getContents();
}
}
memo 객체를 MemoResponseDto에 담는 방법은 생성자로 구현해준다.
※ Spring은 내장된 Jackson 라이브러리를 통해 객체를 JSON으로, JSON을 객체로 변환 할 수 있다.
조회하기 기능 구현
JDBCtemplate으로 select 쿼리 사용 시 query( )를 이용해야하며, 조회된 메모들은 1개 이상이기 때문에 RowMapper로 읽어 List의 형태로 반환해야한다.
MemoResponseDto.java
@Getter
public class MemoResponseDto {
private Long id;
private String username;
private String contents;
public MemoResponseDto(Memo memo) {
this.id = memo.getId();
this.username = memo.getUsername();
this.contents = memo.getContents();
}
public MemoResponseDto(Long id, String username, String contents) {
this.id = id;
this.username = username;
this.contents = contents;
}
}
mapRow 메소드의 반환값을 처리하기 위한 MemoResponseDto 생성자 추가 구현.
수정하기 및 삭제하기 기능 구현
먼저 findById 메소드를 통해 수정하려는/삭제하려는 메모가 DB에 존재하는지 확인한다.
메모가 있을 시 해당 메모의 username과 contents를 memo 객체에 저장해 반환하고, 메모가 없을 시 null을 반환한다.
반환된 memo 객체는 JDBCtemplate를 통해 DB에서 update되거나 delete된다.
MemoController.java
TIL 💭
이전 스프링 프로젝트에서 사용해보지 못 한 것들이 많이 나와 새로 배우는 재미가 있다. @RestController, @ResponseBody 그리고 JDBCtemplate 등 모두 이번 강의를 통해 처음 알게된 것들이라 강의 듣는 시간보다 구글링을 더 오래 한 것 같다.
'Spring' 카테고리의 다른 글
Spring의 Filter 이해하기 및 구현하기 (0) | 2024.08.16 |
---|---|
Spring에서 JWT 이해하기 + 쿠키와 세션 개념까지 (0) | 2024.08.16 |
Spring의 JPA와 Entity 이해하기 (0) | 2024.08.07 |
Spring의 IoC(제어의 역전), DI(의존성 주입) 이해하기 (0) | 2024.08.06 |
Spring을 3 Layer Architecture로 역할 분리하기 (0) | 2024.08.06 |