Spring Boot CRUD API ๊ตฌํ (1) - ์๊ตฌ์ฌํญ ๋ถ์, ๋ฐ์ด๋ฒํ ์ด์ค ์ค๊ณ, ๋๋ฉ์ธ ์ค๊ณ
by rlaehddnd0422๊ธฐ๋ณธ์ ์ธ ๊ฒ์ํ API๋ฅผ ์ค๊ณํจ์ ์์ ์๊ตฌ์ฌํญ์ ๋ถ์ํ๊ณ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ์ค๊ณํ๊ณ ๋๋ฉ์ธ์ ์ค๊ณํด๋ด ์๋ค.
์๊ตฌ์ฌํญ
- ๊ธฐ๋ณธ๊ธฐ๋ฅ
- ํ์ ํ ์ด๋ธ์ ๋ฑ๋ก๋ ์ฌ๋๋ง ๊ฒ์๊ธ๊ณผ ๊ฒ์๊ธ์ ๋๊ธ์ ๋จ๊ธธ ์ ์์.
- ํ์ ๊ฐ์
- ์์ด๋๋ ํน์๋ฌธ์๋ฅผ ์ ์ธํ 4~20์๋ฆฌ
- ๋น๋ฐ๋ฒํธ๋ 8~16์ ์๋ฌธ ๋์๋ฌธ์, ์ซ์ ํน์๋ฌธ์๋ฅผ ๋ฐ๋์ ํฌํจ
- ๋๋ค์์ ํน์๋ฌธ์ ์ ์ธ 2~10์๋ฆฌ
- ์ด๋ฉ์ผ์ ์ด๋ฉ์ผ ํ์์ ๊ฐ์ถ์ด์ผ ํจ (~~@naver.com)
- ๊ฒ์ํ
- ๊ธฐ๋ณธ์ ์ธ CRUD ( Create(์์ฑ), Read(์กฐํ), Update(์์ ), Delete(์ญ์ ) )
- ๋๊ธ
- ๊ฒ์ํ์ ๋ํ ๊ธฐ๋ณธ์ ์ธ CRUD ( Create(์์ฑ), Read(์กฐํ), Update(์์ ), Delete(์ญ์ )
- ์๋ธ๊ธฐ๋ฅ
- Spring Security JWT ๊ธฐ์ ์ ๋์
ํ ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์
( ์ถํ ์ถ๊ฐ์์ )
- Oauth 2.0 ์์ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ ํ์ฅ : ๋ณ๋ ํ์๊ฐ์ ์์ด ๊ตฌ๊ธ, ๋ค์ด๋ฒ, ์นด์นด์ค ์์ด๋๋ก ๋ก๊ทธ์ธ
- ๋๊ธ ๋ฐ ๊ฒ์๊ธ ์ ๋ก๋๋ ๋ก๊ทธ์ธํ ์ฌ์ฉ์๋ง ์์ฑ ๊ฐ๋ฅ
- View ์ถ๊ฐ ( ๋จธ์คํ ์น )
- ๊ตญ์ ํ ๋ฐ ๋ฉ์์ง ๊ธฐ๋ฅ
- ๊ฒ์ํ ์กฐํ์ ๊ธฐ๋ฅ ์ถ๊ฐ
- Spring Security JWT ๊ธฐ์ ์ ๋์
ํ ๋ก๊ทธ์ธ ๋ฐ ํ์๊ฐ์
( ์ถํ ์ถ๊ฐ์์ )
๋ฐ์ดํฐ๋ฒ ์ด์ค ์ค๊ณ
Member
- member_id : Long (PK)
- username : String
- password : String
- nickname : String
- email : String
- role : Enum Type (USER, ADMIN)
Board
- board_id : Long (PK)
- member_id : Long
- content : String
- title : String
- comments : List<String>
Comment
- comment_id : Long (PK)
- board_id : Long
- member_id : Long
- comment : String
BaseEntity
: Member, Board, Comment ํ ์ด๋ธ์์ ๊ณตํต์ผ๋ก ์ฌ์ฉํ๋ ์ํฐํฐ๋ก ๋ฑ๋ก์ผ, ์์ ์ผ์ ํฌํจ. ์ค์ ๋ก ๋ฐ์ดํฐ๋ฒ ์ด์ค์์ ํ ์ด๋ธ๋ก ๋ฑ๋กํ์ง ์์.
์ฐ๊ด๊ด๊ณ ๋งคํ
1. ํ์์ ๊ธ์ ์ฌ๋ฌ ๊ฐ ๋ฑ๋กํ ์ ์์ต๋๋ค.
: Member (1) ↔๏ธ Board(ๅค) : ์ผ๋๋ค ๊ด๊ณ ( OneToMany )
: Board(ๅค) ↔๏ธ Member : ๋ค๋์ผ ๊ด๊ณ ( ManyToOne)
2. ๊ธ์๋ ๋๊ธ์ด ์ฌ๋ฌ๊ฐ ๋ฌ๋ฆด ์ ์์ต๋๋ค.
: Board (1) ↔๏ธ Comment (ๅค) : ์ผ๋๋ค ๊ด๊ณ ( OneToMany )
: Comment(ๅค) ↔๏ธ Board : ๋ค๋์ผ ๊ด๊ณ ( ManyToOne)
3. ํ์์ ๋๊ธ์ ์ฌ๋ฌ๊ฐ ๋ฑ๋กํ ์ ์์ต๋๋ค.
: Member (1) ↔๏ธ Comment(ๅค) : ์ผ๋๋ค ๊ด๊ณ ( OneToMany )
: Comment(ๅค) ↔๏ธ Member : ๋ค๋์ผ ๊ด๊ณ ( ManyToOne)
๋๋ฉ์ธ ์ค๊ณ ๋ฐ ํ ์ด๋ธ ๋งคํ
Member
package dongwoongkim.crud.domain;
import dongwoongkim.crud.domain.base.BaseEntity;
import dongwoongkim.crud.dto.member.MemberEditRequestDto;
import dongwoongkim.crud.dto.member.MemberRequestDto;
import dongwoongkim.crud.repository.MemberRepository;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "MEMBER_ID")
private Long id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String nickname;
@Column(nullable = false)
private String email;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private MemberRole role;
@OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE)
private List<Comment> comments = new ArrayList<>();
@OneToMany(mappedBy = "member", cascade = CascadeType.REMOVE)
private List<Board> boards = new ArrayList<>();
public Member(MemberRequestDto memberRequestDto) {
this.username = memberRequestDto.getUsername();
this.password = memberRequestDto.getPassword();
this.nickname = memberRequestDto.getNickname();
this.email = memberRequestDto.getEmail();
this.role = memberRequestDto.getRole();
}
public Member(String username, String password, String nickname, String email) {
this.username = username;
this.password = password;
this.nickname = nickname;
this.email = email;
}
public void updateMember(MemberEditRequestDto memberEditRequestDto) {
this.password = memberEditRequestDto.getPassword();
this.email = memberEditRequestDto.getEmail();
this.nickname = memberEditRequestDto.getNickname();
}
}
- @Entity : ์ค์ ์ฌ์ฉํ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ๊ณผ ๋งคํ ( @Table(name="member") ์๋ต ์ ์๋์ผ๋ก ํด๋์ค ์ด๋ฆ์ ํ ์ด๋ธ๊ณผ ๋งคํ )
- @OneToMany : ์ผ๋๋ค ๋งคํ ( comment, board )
- cascade = CascadeType.REMOVE ์ต์ : ํ์์ด ์ญ์ ๋ ๋ ํด๋น ๋ฉค๋ฒ์ PK๋ฅผ FK๋ก ๊ฐ์ง ์ฐ๊ด๋ ํ ์ด๋ธ์ ์ปฌ๋ผ๋ค๋ ํจ๊ป ์ญ์ ํ๋๋ก ์ค์
- @Column(nullable = false) : ๋ ๊ฐ ํ์ฉ X
MemberRole
package dongwoongkim.crud.domain;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@Getter
@RequiredArgsConstructor
public enum MemberRole {
USER("USER"),
ADMIN("ADMIN");
private final String value;
}
- EnumType : ADMIN, USER
Board
package dongwoongkim.crud.domain;
import dongwoongkim.crud.domain.base.BaseEntity;
import dongwoongkim.crud.dto.board.BoardEditRequestDto;
import dongwoongkim.crud.dto.board.BoardRequestDto;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Board extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "BOARD_ID")
private Long id;
@Column(nullable = false, length = 50)
private String title;
@Column(nullable = false)
private String content;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
@OneToMany(mappedBy = "board")
@OrderBy("id asc")
private List<Comment> comments = new ArrayList<>();
public Board(String title, String content, Member member) {
this.title = title;
this.content = content;
this.member = member;
}
public static Board toEntity(BoardRequestDto boardRequestDto) {
return new Board(boardRequestDto.getTitle(), boardRequestDto.getContent(), boardRequestDto.getMember());
}
public void updateBoard(BoardEditRequestDto boardEditRequestDto) {
this.title = boardEditRequestDto.getTitle();
this.content = boardEditRequestDto.getContent();
}
}
- @ManyToOne : ๋ค๋์ผ ๋งคํ ( board -> member )
- @JoinColumn(name="member_id") : ์ธ๋ ํค๋ก Member ํ ์ด๋ธ์ PK์ธ member_id ์ฌ์ฉ
- fetch = FetchType.LAZY : ์ง์ฐ๋ก๋ฉ์ผ๋ก ์ค์ ํ์ฌ Member ์ํฐํฐ ์ง์ ์ฌ์ฉ ์ ํ๋ก์๋ก ์ค์ ๊ฐ์ฒด ํธ์ถ
- @OneToMany : ์ผ๋ ๋ค ๋งคํ ( board -> comment )
Comment
package dongwoongkim.crud.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import dongwoongkim.crud.domain.base.BaseEntity;
import dongwoongkim.crud.dto.comment.CommentRequestDto;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import javax.persistence.*;
@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Comment extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String comment;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "BOARD_ID")
private Board board;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "MEMBER_ID")
private Member member;
public Comment(String comment, Board board, Member member) {
this.comment = comment;
this.board = board;
this.member = member;
}
public static Comment toEntity(CommentRequestDto commentRequestDto) {
return new Comment(commentRequestDto.getComment(),commentRequestDto.getBoard(),commentRequestDto.getMember());
}
public void update(String comment) {
this.comment = comment;
}
}
- @ManyToOne : ๋ค๋์ผ ๋งคํ ( Commnet -> Board )
- @ManyToOne : ๋ค๋์ผ ๋งคํ ( Comment -> Member)
~ToMany ๋ ์ง์ฐ๋ก๋ฉ(LAZY)์ด default๋ก ์ค์ ๋์์ง๋ง, ~ToOne์ ์ฆ์๋ก๋ฉ์ด default๋ก ์ค์ ๋์ด ์๊ธฐ ๋๋ฌธ์
๋ชจ๋ fetch ํ์ ์ LAZY๋ก ์ค์ ํด์ฃผ์์ต๋๋ค.
BaseEntity
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModified;
@PreUpdate
public void onPreUpdate() {
this.lastModified = LocalDateTime.now();
}
}
- ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ
์ด๋ธ๋ก ์ง์ ์ฌ์ฉํ์ง ์๊ณ ์ค๋ก์ง ์ํฐํฐ๋ค์๊ฒ ์์ํ๊ธฐ ์ํ ๋ชฉ์ ์ผ๋ก ๋ง๋ ์ํฐํฐ.
- @Entity๋ฅผ ๋ถ์ฌ์ฃผ์ง ์์๊ธฐ ๋๋ฌธ์ ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ํ ์ด๋ธ๊ณผ ๋งคํ๋์ง ์์ต๋๋ค.
- @CreatedDate : ๋ฐ์ดํฐ๊ฐ ์์ฑ๋ ๋ ์๋์ผ๋ก ํ์ฌ ๋ ์ง ๋ฐ ์๊ฐ์ผ๋ก ์์ฑ๋๋ ์ปฌ๋ผ
- @LastModifiedDate : ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๋ ์๋์ผ๋ก ํ์ฌ ๋ ์ง ๋ฐ ์๊ฐ์ผ๋ก ์ ๋ฐ์ดํธ๋๋ ์ปฌ๋ผ
'๐ Backend' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring Boot๋ฅผ ํ์ฉํ์ฌ ๊ฒ์ํ API ์๋ฒ ์ ์ (1) - ํ๋ก์ ํธ ์์ฑ (0) | 2023.06.07 |
---|---|
Spring Boot CRUD API ๊ตฌํ (2) - Repository, Service, Controller ๊ณ์ธต ๊ตฌํ (Member) (0) | 2023.05.26 |
Spring Boot CRUD API ๊ตฌํ (1) | 2023.05.24 |
Spring / ์ง๊ธ๊น์ง ์ฌ์ฉํ ์ด๋ ธํ ์ด์ ์ ๋ฆฌ @ (0) | 2023.02.20 |
Spring / Web ์ค์ฝํ (0) | 2023.02.13 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
Study Repository
rlaehddnd0422