๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ‘ฉ‍๐Ÿ’ป Learn programming

[Spring] Spring ๊ตฌ์กฐ์™€ API ํ๋ฆ„ ์ดํ•ดํ•˜๊ธฐ2 (์ŠคํŒŒ๋ฅดํƒ€์ฝ”๋”ฉํด๋Ÿฝ - ์›น๊ฐœ๋ฐœ์˜ ๋ด„, Spring 3์ฃผ์ฐจ)

by ๋ฐ๊ตฅ์ž‰ 2022. 5. 26.
๋ฐ˜์‘ํ˜•

{ โญ ๋” ์ •๋ฆฌ๋œ ๋…ธ์…˜ ๋ฒ„์ „ โญ}

 

 

ํƒ€์ž„๋ผ์ธ ์„œ๋น„์Šค๋กœ Spring ๊ตฌ์กฐ ์ดํ•ด

API ์„ค๊ณ„ํ•˜๊ธฐ (CRUD)

fair-cheetah-80d.notion.site



โ—API ์„ค๊ณ„ํ•˜๊ธฐ (CRUD)



 

โœ”๏ธ Repository ๋งŒ๋“ค๊ธฐ

 

  1. domain ํŒจํ‚ค์ง€ (Repo ์˜์—ญ) ๋งŒ๋“ค๊ธฐ
  2. domain - Memo.java ํด๋ž˜์Šค ์ƒ์„ฑ
package com.sparta.week03.domain;

import lombok.Getter;
import lombok.NoArgsConstructor;

import javax.persistence.*;

@NoArgsConstructor // ๊ธฐ๋ณธ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.
@Getter
@Entity // ํ…Œ์ด๋ธ”๊ณผ ์—ฐ๊ณ„๋จ์„ ์Šคํ”„๋ง์—๊ฒŒ ์•Œ๋ ค์ค๋‹ˆ๋‹ค.
public class Memo extends Timestamped { // ์ƒ์„ฑ,์ˆ˜์ • ์‹œ๊ฐ„์„ ์ž๋™์œผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Id
    private Long id;

    @Column(nullable = false)
    private String username;

    @Column(nullable = false)
    private String contents;

    public Memo(String username, String contents) {
        this.username = username;
        this.contents = contents;
    }

    public Memo(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }
}
  • lombok์„ ์ด์šฉํ•ด ๊ธฐ๋ณธ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“œ๋Š” @NoArgsConstructor, Getter๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” @Getter๋ฅผ ์ถ”๊ฐ€
  • ํ…Œ์ด๋ธ”๊ณผ ์ด์–ด์ง€๋Š” ํŒŒ์ผ์ด๋ผ๋Š” ๊ฒƒ์„ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด @Entity๋ฅผ ์ถ”๊ฐ€
  • ๋ฉ”๋ชจ๋Š” 1) ์ต๋ช…์˜ ์ž‘์„ฑ์ž ์ด๋ฆ„ (username), 2) ๋ฉ”๋ชจ ๋‚ด์šฉ (contents)๋กœ ์ด๋ฃจ์–ด์ง
    • ๊ตฌ๋ณ„ํ•ด์ฃผ๋Š” ํ‚ค id๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์ž๋™์œผ๋กœ ์ฆ๊ฐ€ํ•˜๋„๋ก *@GeneratedValue*(strategy = *GenerationType*.AUTO) ์ถ”๊ฐ€
  • ํ˜„์žฌ ์ƒํƒœ : (๐Ÿฅถ)Timestamped, (๐Ÿ˜ค)MemoRequestDto ๊ฐ€ ์ƒ์„ฑ๋˜์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ์—๋Ÿฌ

3. domain - Timestemped.java ํด๋ž˜์Šค ์ƒ์„ฑ

@MappedSuperclass // Entity๊ฐ€ ์ž๋™์œผ๋กœ ์ปฌ๋Ÿผ์œผ๋กœ ์ธ์‹ํ•ฉ๋‹ˆ๋‹ค.
@EntityListeners(AuditingEntityListener.class) // ์ƒ์„ฑ/๋ณ€๊ฒฝ ์‹œ๊ฐ„์„ ์ž๋™์œผ๋กœ ์—…๋ฐ์ดํŠธํ•ฉ๋‹ˆ๋‹ค.
public abstract class Timestamped {

    @CreatedDate
    private LocalDateTime createdAt; //์ƒ์„ฑ์‹œ๊ฐ„

    @LastModifiedDate
    private LocalDateTime modifiedAt; //์ˆ˜์ •์‹œ๊ฐ„
}
  • @MappedSuperclass : Timestamped๋ฅผ ์ƒ์†ํ•œ ํด๋ž˜์Šค(์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Memo.java)์— ์ž๋™์œผ๋กœ ์ƒ์„ฑ ์‹œ๊ฐ„๊ณผ ์ˆ˜์ • ์‹œ๊ฐ„์„ colunm์œผ๋กœ ์ธ์‹ํ•˜๊ฒŒ ํ•จ.
  • @EntityListeners : Entity(์ด ํ”„๋กœ์ ํŠธ์—์„œ๋Š” Memo.java)๊ฐ€ ๋ณ€ํ™”ํ•˜๋Š” ๊ฒƒ์„ ํ•ญ์ƒ ๋“ฃ๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ.
  • LocalDateTime : ์‹œ๊ฐ„์„ ๋‚˜ํƒ€๋‚ด๋Š” ์ž๋ฃŒํ˜•
  • abstract ์ถ”๊ฐ€ํ•ด์„œ ์ถ”์ƒ ํด๋ž˜์Šค๋กœ ๋งŒ๋“ค์–ด์ค˜์•ผํ•จ.
    • New Timestamped ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Œ,
    • (๋นต ํ‹€์€ ์žˆ์ง€๋งŒ ๋นต ๋ชป๋งŒ๋“ค๊ณ , ์ƒ์†์ด ๋˜์–ด์•ผ๋งŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค๋‹ค)
  • (๐Ÿฅถ) Timestamped ํด๋ž˜์Šค ๋งŒ๋“ค์–ด์„œ ์—๋Ÿฌ ํ•ด๊ฒฐ!

4. domain - MemoRequestDto.java ํด๋ž˜์Šค ์ƒ์„ฑ

@Getter
public class MemoRequestDto {
    private String username;
    private String contents;
}
  • RequestDto๋Š” ๊ณ„์ธต๊ฐ„ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ์œ„ํ•ด ํ•„์š”ํ•œ ์ •๋ณด(username, contents)๋ฅผ ๊ฐ€์ง€๊ณ  ๋‹ค๋‹˜.
  • private๋กœ ์„ค์ •ํ•˜๊ณ , ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด @Getter ์ถ”๊ฐ€
  • (๐Ÿ˜ค) MemoRequestDto ํด๋ž˜์Šค ๋งŒ๋“ค์–ด์„œ ์—๋Ÿฌ ํ•ด๊ฒฐ!

 

5. domain - MemoRepository.java ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ

public interface MemoRepository extends JpaRepository<Memo, Long> {
    List<Memo> findAllByOrderByModifiedAtDesc();
}
  • (extends) MemoRepository๋Š” ๋ฏธ๋ฆฌ ์ž‘์„ฑ๋œ JpaRepository(findAll, delete, findById, sava …)๋ฅผ / Memo๋ผ๋Š” ํด๋ž˜์Šค์˜ id๊ฐ€ Long์ธ ๊ฒƒ์— ๋Œ€ํ•ด์„œ ๊ฐ€์ ธ๋‹ค๊ฐ€ ์“ธ๊ฑฐ์•ผ
  • findAllByOrderByModifiedAtDesc
    • *๏ธโƒฃ JPA ๊ณต์‹ ํ™ˆํŽ˜์ด์ง€ ๋ฌธ์„œ ์ฐธ๊ณ 
    • https://docs.spring.io/spring-data/jpa/docs/current/reference/html/#jpa.query-methods
    • findAll By OrderBy ModifiedAt Des
    • ๋‹ค ์ฐพ์•„์„œ ์ •๋ ฌํ•ด์ค˜ ์ˆ˜์ •๋œ ๋‚ ์งœ ๊ธฐ์ค€์œผ๋กœ ๋‚ด๋ฆผ์ฐจ์ˆœ(์ตœ์‹ ์ˆœ)
    • ⇒ ๋‹ค ์ฐพ์•„์„œ ์ˆ˜์ •๋œ ๋‚ ์งœ ๊ธฐ์ค€์œผ๋กœ ์ตœ์‹ ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ด์ค˜

 

โœ”๏ธ Service ๋งŒ๋“ค๊ธฐ 

 

 

  1. service ํŒจํ‚ค์ง€ ์ƒ์„ฑํ•˜๊ธฐ
  2. service - MemoService.java ํด๋ž˜์Šค ์ƒ์„ฑ
@Service
public class MemoService {

    @Transactional
    public Long update(Long id, MemoRequestDto requestDto) {
        Memo memo = memoRepository.findById(id).orElseThrow(
                () -> new NullPointerException("์•„์ด๋””๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ")
        );
        memo.update(requestDto);
        return id;
    }
  • update ์‹œ service ๊ฐ€ ํ•„์š”ํ•˜๊ธฐ ๋•Œ๋ฌธ์— update ๋ฉ”์†Œ๋“œ๋ฅผ ์ƒ์„ฑํ•ด์คŒ.
  • public ๋ฐ˜ํ™˜ํƒ€์ž… ๋ฉ”์†Œ๋“œ์ด๋ฆ„(ํŒŒ๋ผ๋ฏธํ„ฐ) { }
  • id๋ฅผ ๊ฐ€์ ธ์™€์„œ ํ•ด๋‹นํ•˜๋Š” id์˜ Dto๋ฅผ ๋ณ€๊ฒฝํ•ด์ค˜์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— (Long id, MemoRequestDto requestDto)์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์„ค์ •
  • return ํ•˜๋Š” id์˜ ๋ฐ˜ํ™˜ํƒ€์ž…์ธ Long

 

1) id๋กœ ํ•ด๋‹นํ•˜๋Š” ๋ฉ”๋ชจ ์ฐพ๊ธฐ

  • Memo memo = memoRepository.findById(id).orElseThrow(
                    () -> new NullPointerException("์•„์ด๋””๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ")
            );
    
    • memoRepository์˜ findId๋กœ id๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์ฐพ์„ ๊ฑด๋ฐ, ๋งŒ์•ฝ์— ์—†์œผ๋ฉด ์˜ค๋ฅ˜ ๋ฐœ์ƒ ์‹œ์ผœ์ค˜
      • NullPointerException : ๊ฐ€๋ฆฌํ‚จ ๊ฒŒ ๋น„์–ด์žˆ์œผ๋ฉด ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ•ด์ค˜
      • IllegalArgumentException : Argument(ํŒŒ๋ผ๋ฏธํ„ฐ)๊ฐ€ ๋ญ”๊ฐ€ ์ž˜๋ชป๋์œผ๋ฉด ์˜ˆ์™ธ์ฒ˜๋ฆฌ ํ•ด์ค˜
    • id๋กœ ๋ฉ”๋ชจ๋ฅผ ์ฐพ์•˜๊ฑฐ๋‚˜ ์˜ค๋ฅ˜๋ฅผ ๋ณด๋ƒˆ์œผ๋ฉด memo์— ๋ฐ˜ํ™˜ํ•ด์ค˜.

2) update ํ•˜๊ธฐ

  • memo.update(requestDto);
    return id;
    
    • memo์— requestDto๋ฅผ update ํ•˜๊ณ , id ๊ฐ’์œผ๋กœ ๋„˜๊ฒจ์ค˜

 

3. domain - Memo.java ํด๋ž˜์Šค์— update ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ํ•˜๊ธฐ

public void update(MemoRequestDto requestDto) {
        this.username = requestDto.getUsername();
        this.contents = requestDto.getContents();
    }
  • MemoService์—์„œ requestDto๋ฅผ ์ „๋‹ฌ๋ฐ›๊ธฐ ๋•Œ๋ฌธ์— update ๋ฉ”์†Œ๋“œ์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” requestDto
  • ๋ณ€๊ฒฝํ•  ๊ฐ’์„ ์‹ค์–ด๋‚˜๋ฅด๋Š” Dto์˜ ๊ฐ’์ด Memo ์•ˆ์— ์ €์žฅ๋จ.

 

4. MemoService.java ์™„์„ฑ์‹œํ‚ค๊ธฐ

@RequiredArgsConstructor
@Service
public classMemoService{

    private final MemoRepository memoRepository;

		@Transactional
		publicLongupdate(Longid,MemoRequestDtorequestDto) {
		Memomemo = memoRepository.findById(id).orElseThrow(
		                () -> new NullPointerException("์•„์ด๋””๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ")
		        );
		        memo.update(requestDto);
		        returnid;
		    }
}

  • memoRepository ๊ผญ ํ•„์š”ํ•˜๋‹ˆ๊นŒ final ์ ์–ด์ฃผ๊ธฐ
  • @RequiredArgsConstructor : fianl์ด ์žˆ์œผ๋ฉด ์•Œ์•„์„œ ์ƒ์„ฑ์ž๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋Š” ๊ถŒํ•œ์„ ์ค˜์•ผํ•จ
  • @Service : ์„œ๋น„์Šค๋ผ๊ณ  ์•Œ๋ ค์ฃผ๊ธฐ
  • @Transactional : ์—…๋ฐ์ดํŠธ ํ•  ๋•Œ DB์— ์ง„์งœ ๋ฐ˜์˜๋˜์•ผํ•œ๋‹ค๊ณ  ์•Œ๋ ค์คŒ.

 

โœ”๏ธ Controller ๋งŒ๋“ค๊ธฐ

 

 

  1. Controller ํŒจํ‚ค์ง€ ์ƒ์„ฑํ•˜๊ธฐ
  2. MemoController.java ํด๋ž˜์Šค ์ƒ์„ฑ
@RequiredArgsConstructor
@RestController
public classMemoController{
    private final MemoRepository memoRepository;
    private final MemoService memoService;
}
  • MemoRepository๋ž‘ memoService ์‚ฌ์šฉํ•˜๊ฑด๋ฐ ๊ผญ ํ•„์š”ํ•˜๋‹ˆ๊นŒ final ์ถ”๊ฐ€ํ•ด์ค˜
  • ์›๋ž˜๋Š” ์š”์ฒญ์ด ๋“ค์–ด์˜ค๋ฉด new memoController ~ ๋ผ๊ณ  ์ƒ์„ฑ์ด ๋œ ํ›„ ์‚ฌ์šฉํ•ด์•ผํ•˜๋Š”๋ฐ, @RequiredArgsConstructor, @RestController ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์Šคํ”„๋ง์ด ๊ทธ ์—ญํ• ์„ ํ•ด์คŒ.

 

POST - ์ƒ์„ฑ

@PostMapping("/api/memos")
    public Memo createMemo(@RequestBody MemoRequestDto requestDto) {
        Memo memo = new Memo(requestDto);
        return memoRepository.save(memo);
    }
  • requestDto๋ผ๋Š” ํ‹€์— ์ƒˆ๋กœ์šด ๋ฉ”๋ชจ๋ฅผ ๋งŒ๋“ค์–ด์„œ memoRepository์˜ save๋ฅผ ํ™œ์šฉํ•ด์„œ ์ €์žฅ.

 

Get - ์กฐํšŒ

@GetMapping("/api/memos")
    public List<Memo> readMemo() {
        return memoRepository.findAllByOrderByModifiedAtDesc();
    }
  • memoRepository์— ์žˆ๋Š” ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ˆ˜์ •๋‚ ์งœ ๊ธฐ์ค€์œผ๋กœ ์ตœ์‹ ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ด ๋ณด์—ฌ์คŒ.

 

PUT - ๋ณ€๊ฒฝ

@PutMapping("/api/memos/{id}")
    public Long updateMemo(@PathVariable Long id, @RequestBody MemoRequestDto requestDto) {
        memoService.update(id, requestDto);
        return id;
    }
  • ๋ณ€๊ฒฝํ•  ๋ฉ”๋ชจ์˜ id๋ฅผ ๋ฐ›์•„์„œ memoService๋กœ ์—…๋ฐ์ดํŠธ ํ•˜๊ณ  ๋‹ค์‹œ id๋ฅผ ๋Œ๋ ค์คŒ

 

DELETE - ์‚ญ์ œ

@DeleteMapping("/api/memo/{id}")
    public Long deleteMemo(@PathVariable Long id) {
        memoRepository.deleteById(id);
        return id;
    }
  • ์‚ญ์ œํ•  ๋ฉ”๋ชจ์˜ id๋ฅผ ๋ฐ›์•„์„œ ์‚ญ์ œํ•˜๊ณ  id๋ฅผ ๋Œ๋ ค์คŒ.
๋ฐ˜์‘ํ˜•