Rest api Test

์ด์€์ฒ ยท2024๋…„ 11์›” 7์ผ

์œ„ํ‚ค

๋ชฉ๋ก ๋ณด๊ธฐ
17/20
post-thumbnail

๐Ÿ“Œ https://github.com/LEEEUNCHEOL96/demo241106

Rest Api CRUD test

์ž‘์—… ์ง„ํ–‰ ์ˆœ์„œ
1. IntelliJ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •
2. BaseEntity ๋ฐ ArticleEntity ์„ค์ •
3. Article Controller, DTO, RsData ์„ค์ •
4. ์š”์ฒญ ๋ฐ ์‘๋‹ต ์„ค์ •
5. Service ์„ค์ •
6. ์ปจํŠธ๋กค๋Ÿฌ์— ๊ตฌํ˜„ํ•˜๊ธฐ

1. IntelliJ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์„ค์ •

  • IntelliJ ๊ฐœ๋ฐœํ™˜๊ฒฝ ์„ค์ •

  • MariaDB ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , JPA์™€ Hibernate๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ํšจ์œจ์ ์ธ ์—ฐ๋™.

    application.yml ํŒŒ์ผ์—์„œ ์ฃผ์š” ์„ค์ • ํ•ญ๋ชฉ์„ ์„ค๋ช…ํ•œ ๋‚ด์šฉ์ด๋‹ค.

// application.yml 
spring:
  datasource:
    driver-class-name: org.mariadb.jdbc.Driver
    url: jdbc:mariadb://localhost:3306/demo241106
    username: *****
    password: *****
  jpa:
    hibernate:
      ddl-auto: create
    properties:
      hibernate:
        show_sql: true
        format_sql: true
        use_sql_comments: true
logging:
  level:
    root: INFO
    example.demo.rest_api: DEBUG
    org.hibernate.orm.jdbc.bind: TRACE
    org.hibernate.orm.jdbc.extract: TRACE
  • DB ์ƒ์„ฑํ•˜๊ธฐ

2. BaseEntity ๋ฐ ArticleEntity ์„ค์ •

  • BaseEntity ์„ค์ •
// global.jpa > BaseEntity

@Getter
@SuperBuilder
@MappedSuperclass
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EntityListeners(AuditingEntityListener.class)
@ToString
public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @CreatedDate
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime modifiedDate;
}

์–ด๋…ธํ…Œ์ด์…˜

  • @SuperBuilder: ๋นŒ๋” ํŒจํ„ด์„ ํ†ตํ•ด ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ง€์›, ์ƒ์† ๊ด€๊ณ„์—์„œ๋„ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
  • @MappedSuperclass: ์ด ํด๋ž˜์Šค๋Š” ์ง์ ‘ ํ…Œ์ด๋ธ”์— ๋งคํ•‘๋˜์ง€ ์•Š์ง€๋งŒ, ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค๋“ค์ด ์ด๋ฅผ ์ƒ์†ํ•˜์—ฌ ๋งคํ•‘๋  ์ˆ˜ ์žˆ๋„๋ก ํ•จ.
  • @EntityListeners(AuditingEntityListener.class): Auditing ๊ธฐ๋Šฅ์„ ํ™œ์„ฑํ™”ํ•˜์—ฌ createdDate์™€ modifiedDate ํ•„๋“œ๊ฐ€ ์ž๋™์œผ๋กœ ๊ด€๋ฆฌ๋˜๋„๋ก ํ•จ.
  • ArticleEntity ์„ค์ •
// domain.article.entity > Article
@Entity
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@SuperBuilder
@ToString(callSuper = true)
public class Article extends BaseEntity {
    private String subject;
    private String content;
    private String author;
}

Entity ๋ฅผ ์ดˆ๊ธฐ ์„ค์ •ํ•˜๋Š” ์ด์œ 
JPA์™€ Spring Data JPA์—์„œ ์—”ํ‹ฐํ‹ฐ๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. Article ์—”ํ‹ฐํ‹ฐ์™€ ๊ฐ™์€ JPA ์—”ํ‹ฐํ‹ฐ ํด๋ž˜์Šค๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ…Œ์ด๋ธ”๊ณผ ๋งคํ•‘๋˜๋Š” ๊ฐ์ฒด๋กœ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์„ ์ •์˜ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค CRUD ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐ ํ•ต์‹ฌ์ ์ธ ์—ญํ• ์„ ํ•œ๋‹ค.

3. Article Controller, DTO, RsData ์„ค์ •

์ด๋ฒˆ ์ž‘์—…์—์„œ๋Š” HTML ๊ธฐ๋ฐ˜์˜ ํ”„๋ก ํŠธ์—”๋“œ ๊ตฌํ˜„ ์—†์ด, Postman์„ ์ด์šฉํ•˜์—ฌ API ํ…Œ์ŠคํŠธ ๋ฐ ๊ฒ€์ฆ์„ ์ง„ํ–‰ํ•  ์˜ˆ์ •์ด๋‹ค.

  • ArticleDTO ์„ค์ •
//domain.article.dto > ArticleDTO
@Getter
public class ArticleDTO {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private final Long id;

    private final String subject;

    private final String content;

    private final String author;

    private final LocalDateTime createdDate;

    @LastModifiedDate
    private final LocalDateTime modifiedDate;

    public ArticleDTO(Article article){
        this.id = article.getId();
        this.subject = article.getSubject();
        this.content = article.getContent();
        this.author = article.getAuthor();
        this.createdDate = article.getCreatedDate();
        this.modifiedDate = article.getModifiedDate();
    }
}

DTO ๋ฅผ ๋งŒ๋“  ์ด์œ 
์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ๊ฐ ๊ณ„์ธต ๊ฐ„ ๋ฐ์ดํ„ฐ ๊ตํ™˜์„ ๋ณด๋‹ค ๋ช…ํ™•ํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ์ด๋‹ค. ํŠนํžˆ ArticleDTO๋Š” Article ์—”ํ‹ฐํ‹ฐ์™€ ์ปจํŠธ๋กค๋Ÿฌ ๋˜๋Š” ์„œ๋น„์Šค ๊ฐ„์˜ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค. ๋˜ํ•œ ์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค.

  • Article Controller ์—์„œ ์ดˆ๊ธฐ Test ์ง„ํ–‰

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/demo241106/articles")
public class ArticleController {
    private final ArticleService articleService;

    @GetMapping("") // ๋‹ค๊ฑด์กฐํšŒ
    public List<ArticleDTO> list() {
        List<ArticleDTO> articleDTOS = new ArrayList<>();
        Article article = new Article("์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.", "์ž‘์„ฑ์ž");
        articleDTOS.add(new ArticleDTO(article));

        Article article2 = new Article("๋‘ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.2", "์ž‘์„ฑ์ž2");
        articleDTOS.add(new ArticleDTO(article2));

        Article article3 = new Article("์„ธ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.3", "์ž‘์„ฑ์ž3");
        articleDTOS.add(new ArticleDTO(article3));

        return articleDTOS;
    }

    @GetExchange("/{id}") //๋‹จ๊ฑด์กฐํšŒ
    public ArticleDTO getArticle(@PathVariable("id") Long id){
        Article article = new Article("์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€","๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.","์ž‘์„ฑ์ž");
        ArticleDTO articleDTO = new ArticleDTO(article);

        return articleDTO;
    }

    @PostMapping("") // ์ƒ์„ฑ
    public String create(@RequestParam("subject") String subject,
                         @RequestParam("content") String content,
                         @RequestParam("author") String author){

        System.out.println(subject);
        System.out.println(content);
        System.out.println(author);

        return "๋“ฑ๋ก";
    }

    @PatchMapping("/{id}") // ์ˆ˜์ •
    public String modify(@PathVariable("id") Long id,
                         @RequestParam("subject") String subject,
                         @RequestParam("content") String content,
                         @RequestParam("author") String author){

        System.out.println(id);
        System.out.println(subject);
        System.out.println(content);
        System.out.println(author);

        return "์ˆ˜์ •";
    }

    @DeleteMapping("/{id}")  // ์ƒ‚๊ฒŒ
    public String delete(@PathVariable("id") Long id){
        System.out.println(id);

        return "์‚ญ์ œ";
    }
}

Postman์—์„œ ์œ„์˜ ArticleController์˜ REST API๋ฅผ ๊ฐ„๋‹จํ•˜๊ฒŒ ํ…Œ์ŠคํŠธํ•ด๋ณด์ž. ๊ฐ ์—”๋“œํฌ์ธํŠธ์— ๋งž๋Š” ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ  ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•œ๋‹ค.

4. ์š”์ฒญ ๋ฐ ์‘๋‹ต ์„ค์ •

  • ๋‹ค์Œ์œผ๋กœ๋Š” ์š”์ฒญ ๋ฐ ์‘๋‹ต์— ๋Œ€ํ•œ ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ค์ž
global.RsData > RsData

@Getter
@Setter
@AllArgsConstructor
public class RsData<T> {
    private String resultCode;
    private String msg;
    private T data;
    public static <T> RsData<T> of(String resultCode, String msg, T data) {
        return new RsData<>(resultCode, msg, data);
    }
    public static <T> RsData<T> of(String resultCode, String msg) {
        return of(resultCode, msg, null);
    }
    @JsonIgnore
    public boolean isSuccess() {
        return resultCode.startsWith("200");
    }
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }
}

RsData๋ž€?
API ์‘๋‹ต์„ ์ผ๊ด€๋œ ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋œ๋‹ค. ์ฃผ๋กœ ์‘๋‹ต ์ฝ”๋“œ, ๋ฉ”์‹œ์ง€, ๊ทธ๋ฆฌ๊ณ  ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด๋กœ, ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ์ „๋‹ฌํ•  API ์‘๋‹ต์˜ ๊ตฌ์กฐ๋ฅผ ์ •์˜๋œ๋‹ค.

  • Controller ์— RsData ๋ฅผ ์ ์šฉ์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์‘๋‹ต ๋ฐ ์š”์ฒญ์„ ์ƒ์„ฑํ•œ๋‹ค.

  • ์š”์ฒญ

// domain.article.request > ArticleCreateRequest 
// domain.article.request > ArticleModifyRequest 
@Getter
@Setter
public class Article_____Request{
    @NotBlank
    private String subject;
    @NotBlank
    private String content;
    @NotBlank
    private String author;
}
  • ์‘๋‹ต
// domain.article.response > ArticleResponse ๋‹จ๊ฑด
// domain.article.response > ArticlesResponse ๋‹ค๊ฑด
@Getter
@AllArgsConstructor
public class ArticleResponse {
    private final ArticleDTO article;
}

RsData ์™€ Requset,Response ์ ์šฉํ•˜๊ธฐ

  • ์ด๋ฒˆ์—๋Š” Postman์„ ์‚ฌ์šฉํ•˜์—ฌ RsData, Request, Response๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ ArticleController์˜ REST API๋ฅผ ๊ฐ„๋‹จํžˆ ํ…Œ์ŠคํŠธํ•ด๋ณด์ž.

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/demo241106/articles")
public class ArticleController {
    private final ArticleService articleService;

    @GetMapping("") // ๋‹ค๊ฑด์กฐํšŒ
    public RsData<ArticlesResponse> list() {
        List<ArticleDTO> articleDTOS = new ArrayList<>();
        Article article = new Article("์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.", "์ž‘์„ฑ์ž");
        articleDTOS.add(new ArticleDTO(article));

        Article article2 = new Article("๋‘ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.2", "์ž‘์„ฑ์ž2");
        articleDTOS.add(new ArticleDTO(article2));

        Article article3 = new Article("์„ธ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€", "๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.3", "์ž‘์„ฑ์ž3");
        articleDTOS.add(new ArticleDTO(article3));

        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ๋‹ค๊ฑด ์กฐํšŒ ์„ฑ๊ณต", new ArticlesResponse(articleDTOS));
    }


    @GetExchange("/{id}") //๋‹จ๊ฑด์กฐํšŒ
    public RsData<ArticleResponse> getArticle(@PathVariable("id") Long id){
        Article article = new Article("์ฒซ ๋ฒˆ์งธ ๊ฒŒ์‹œ๊ธ€","๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.","์ž‘์„ฑ์ž");
        ArticleDTO articleDTO = new ArticleDTO(article);

        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ๋‹จ๊ฑด ์กฐํšŒ ์„ฑ๊ณต", new ArticleResponse(articleDTO));
    }

    @PostMapping("") // ์ƒ์„ฑ
    public String create(@Valid @RequestBody ArticleCreateRequest articleCreateRequest){

        System.out.println(articleCreateRequest.getSubject());
        System.out.println(articleCreateRequest.getContent());
        System.out.println(articleCreateRequest.getAuthor());

        return "๋“ฑ๋ก์™„๋ฃŒ";
    }

    @PatchMapping("/{id}") // ์ˆ˜์ •
    public String modify(@PathVariable("id") Long id, @Valid @RequestBody ArticleModifyRequest articleModifyRequest){

        System.out.println(id);
        System.out.println(articleModifyRequest.getSubject());
        System.out.println(articleModifyRequest.getContent());
        System.out.println(articleModifyRequest.getAuthor());

        return "์ˆ˜์ •";
    }

    @DeleteMapping("/{id}")  // ์ƒ‚๊ฒŒ
    public String delete(@PathVariable("id") Long id){
        System.out.println(id);

        return "์‚ญ์ œ";
    }
}

5. Service ์„ค์ •

  • ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ๋“ค์ด ์ž˜ ์‹คํ–‰ ๋˜์—ˆ๋‹ค.์ด์ œ๋Š” ๋ณธ๊ฒฉ์ ์œผ๋กœ DB์— ์ €์žฅํ•˜๊ณ  ๋ถˆ๋Ÿฌ์™€๋ณด์ž.

@Service
@RequiredArgsConstructor
public class ArticleService {
    private final ArticleRepository articleRepository;

    public List<ArticleDTO> getList() {
        List<Article> articleList = this.articleRepository.findAll();

        List<ArticleDTO> articleDTOList = articleList.stream()
                .map(article -> new ArticleDTO(article))
                .collect(Collectors.toList());
        return articleDTOList;
    }

    public Article getArticle(Long id) {
        Optional<Article> optionalArticle = this.articleRepository.findById(id);

        return optionalArticle.orElse(null);
    }


    public Article write(String subject, String content,String author){
        Article article = Article.builder()
                .subject(subject)
                .content(content)
                .author(author)
                .build();
        this.articleRepository.save(article);
        return article;
    }

    public Article update(Article article, String content, String subject,String author) {
        article.setSubject(subject);
        article.setContent(content);
        article.setAuthor(author);
        this.articleRepository.save(article);
        return article;
    }

    public void delete(Article article) {
        this.articleRepository.delete(article);
    }
} 

์„œ๋น„์Šค ๊ณ„์ธต

  • getList : ๋ชจ๋“  ๊ฒŒ์‹œ๊ธ€์„ ์กฐํšŒ (๋‹ค๊ฑด ์กฐํšŒ)
  • getAritlce(Long id) : ํŠน์ • ๊ฒŒ์‹œ๊ธ€์„ ID๋กœ ์กฐํšŒ (๋‹จ๊ฑด ์กฐํšŒ)
  • write : ์ƒˆ๋กœ์šด ๊ฒŒ์‹œ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ  ์ €์žฅ (๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ)
  • update : ๊ธฐ์กด ๊ฒŒ์‹œ๊ธ€์„ ์ˆ˜์ • (๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •)
  • delete : ํŠน์ • ๊ฒŒ์‹œ๊ธ€์„ ์‚ญ์ œ (๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ)

Response ์ถ”๊ฐ€

  • create,modify ์— ๊ด€ํ•œ ์‘๋‹ต์„ ์ถ”๊ฐ€!
// domain.article.response > ArticleCreateResponse ์ƒ์„ฑ
// domain.article.response > ArticlesModifyResponse ์ˆ˜์ •
@Getter
@AllArgsConstructor
public class Article______Response {
    private final Article article;
}

why delete response ๋Š” ๋งŒ๋“ค์ง€ ์•Š๊ณ  articleResponse ๋ฅผ ์žฌ์‚ฌ์šฉํ• ๊นŒ?

  • ์žฌ์‚ฌ์šฉํ•œ ์ด์œ ๋Š” ์‚ญ์ œ๋œ ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ์ตœ์†Œํ•œ์˜ ์ •๋ณด๋ฅผ ํฌํ•จํ•œ ์‘๋‹ต์„ ์ œ๊ณต๋ฉฐ, ์‚ญ์ œ๋œ ๊ฒŒ์‹œ๊ธ€์— ๋Œ€ํ•œ ์„ธ๋ถ€ ์ •๋ณด๋ฅผ ArticleResponse๋กœ ๋‹ด์•„์„œ ํด๋ผ์ด์–ธํŠธ๊ฐ€ ์–ด๋–ค ๊ฒŒ์‹œ๊ธ€์ด ์‚ญ์ œ๋˜์—ˆ๋Š”์ง€ ์•Œ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ผ๊ด€์„ฑ ์žˆ๋Š” ์‘๋‹ต ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
    ๋‹ค๋ฅธ CRUD ์ž‘์—…(์กฐํšŒ, ์ˆ˜์ • ๋“ฑ)๊ณผ ์‘๋‹ต ํ˜•์‹์„ ํ†ต์ผํ•˜๋Š” ๊ฒƒ์ด API์˜ ์œ ์ง€๋ณด์ˆ˜์™€ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์— ์œ ๋ฆฌํ•˜๋‹ค!

6. ์ปจํŠธ๋กค๋Ÿฌ์— ๊ตฌํ˜„ํ•˜๊ธฐ

  • service ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ์ด์   ๋งˆ๋ฌด๋ฆฌํ•ด๋ณด์ž

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/demo241106/articles")
public class ArticleController {
    private final ArticleService articleService;

    @GetMapping("") // ๋‹ค๊ฑด์กฐํšŒ
    public RsData<ArticlesResponse> list() {
        List<ArticleDTO> articleDTOS = this.articleService.getList();

        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ๋‹ค๊ฑด ์กฐํšŒ ์„ฑ๊ณต", new ArticlesResponse(articleDTOS));
    }


    @GetMapping("/{id}") //๋‹จ๊ฑด์กฐํšŒ
    public RsData<ArticleResponse> getArticle(@PathVariable("id") Long id){
        Article article = this.articleService.getArticle(id);

        if(article ==null)
            return RsData.of("500","%d ๋ฒˆ๊ฒŒ์‹œ๋ฌผ์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.".formatted(id),null);

        ArticleDTO articleDTO = new ArticleDTO(article);
        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ๋‹จ๊ฑด ์กฐํšŒ ์„ฑ๊ณต", new ArticleResponse(articleDTO));
    }

    @PostMapping("") // ์ƒ์„ฑ
    public RsData<ArticleCreateResponse> create(@Valid @RequestBody ArticleCreateRequest articleCreateRequest){
        Article article = this.articleService.write(articleCreateRequest.getSubject(),articleCreateRequest.getContent(),articleCreateRequest.getAuthor());

        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ๋“ฑ๋ก ์„ฑ๊ณต", new ArticleCreateResponse(article));
    }

    @PatchMapping("/{id}") // ์ˆ˜์ •
    public RsData<ArticleModifyResponse> modify(@PathVariable("id") Long id, @Valid @RequestBody ArticleModifyRequest articleModifyRequest){
        Article article = this.articleService.getArticle(id);

        if(article ==null)
            return RsData.of("500","%d ๋ฒˆ๊ฒŒ์‹œ๋ฌผ์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.".formatted(id),null);

        article = this.articleService.update(article,articleModifyRequest.getSubject(),articleModifyRequest.getContent(),articleModifyRequest.getAuthor());


        return RsData.of("200","๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ • ์„ฑ๊ณต",new ArticleModifyResponse(article));
    }

    @DeleteMapping("/{id}")  // ์ƒ‚๊ฒŒ
    public RsData<ArticleResponse> delete(@PathVariable("id") Long id){
        Article article = this.articleService.getArticle(id);

        if(article ==null)
            return RsData.of("500","%d ๋ฒˆ๊ฒŒ์‹œ๋ฌผ์€ ์กด์žฌํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.".formatted(id),null);

        this.articleService.delete(article);
        ArticleDTO articleDTO = new ArticleDTO(article);

        return RsData.of("200","%d ๋ฒˆ ๊ฒŒ์‹œ๋ฌผ ์‚ญ์ œ ์„ฑ๊ณต".formatted(id), new ArticleResponse(articleDTO));
    }
}

๋ชจ๋“  Service ๋“ค์„ ์ ์šฉ ์‹œ์ผฐ๋‹ค. ์ด์ œ PostMan ์—์„œ ํ™•์ธํ•ด๋ณด์ž

  • ๊ฒŒ์‹œ๊ธ€ ์ƒ์„ฑ

  • ๋‹จ๊ฑด ์กฐํšŒ

  • ๋‹ค๊ฑด ์กฐํšŒ

  • ๊ฒŒ์‹œ๊ธ€ ์ˆ˜์ •

  • ๊ฒŒ์‹œ๊ธ€ ์‚ญ์ œ

  • ์กฐํšŒ, ์ˆ˜์ •, ์‚ญ์ œ ์˜ค๋ฅ˜ ๋ฉ”์„ธ์ง€ ์ถœ๋ ฅ

๋งˆ๋ฌด๋ฆฌํ•˜๋ฉฐ

  • Spring Boot๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๊ฒŒ์‹œ๊ธ€ CRUD API๋ฅผ ๊ตฌํ˜„ TEST๋ฅผ ์ง„ํ–‰ํ–ˆ๋‹ค. API๋ฅผ ์„ค๊ณ„ํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์—์„œ ์ค‘์š”ํ•œ ๋ถ€๋ถ„๋“ค์„ ์งš์–ด๋ณด์ž.
  1. RESTful API ์„ค๊ณ„
    ์ด๋ฒˆ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๊ฒŒ์‹œ๊ธ€์„ ๋‹ค๋ฃจ๋Š” API๋ฅผ ์„ค๊ณ„ํ•˜๋ฉด์„œ, HTTP ๋ฉ”์„œ๋“œ(GET, POST, PATCH, DELETE)๋ฅผ ์ ์ ˆํžˆ ์‚ฌ์šฉํ•˜์—ฌ RESTfulํ•œ API๋ฅผ ๊ตฌํ˜„ํ–ˆ๋‹ค.

  2. DTO(Data Transfer Object)์™€ Response ์ฒ˜๋ฆฌ
    DTO๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ์˜ ๊ตฌ์กฐ๋ฅผ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ  ์ด๋ฅผ ํ†ตํ•ด API์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋ฐฉ์‹์ด ๊น”๋”ํ•˜๊ณ  ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์‰ฌ์šด ๊ตฌ์กฐ๋กœ ๊ด€๋ฆฌํ•œ๋‹ค.
    ๋˜ํ•œ RsData ํด๋ž˜์Šค๋ฅผ ๋„์ž…ํ•˜์—ฌ API์˜ ๊ฒฐ๊ณผ๋ฅผ ํ‘œ์ค€ํ™” ์ด๋ฅผ ํ†ตํ•ด ๊ฐ API ์‘๋‹ต์˜ ์ƒํƒœ ์ฝ”๋“œ์™€ ๋ฉ”์‹œ์ง€๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๊ณ , ํด๋ผ์ด์–ธํŠธ๊ฐ€ API ์‘๋‹ต์„ ์‰ฝ๊ฒŒ ํ•ด์„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  3. ์ฝ”๋“œ์˜ ์œ ์ง€๋ณด์ˆ˜์™€ ํ™•์žฅ์„ฑ
    REST API๋ฅผ ์„ค๊ณ„ํ•˜๋ฉด์„œ ๊ฐ ๊ธฐ๋Šฅ๋ณ„๋กœ ์„œ๋น„์Šค์™€ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•˜๊ณ , DTO์™€ ์‘๋‹ต ํด๋ž˜์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‘๋‹ต ํ˜•์‹์„ ์ผ๊ด€์„ฑ ์žˆ๊ฒŒ ์ฒ˜๋ฆฌํ•œ๋‹ค. ์ด๋Ÿฐ ๋ฐฉ์‹์€ ํ–ฅํ›„ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ ์ถ”๊ฐ€๋‚˜ ์ˆ˜์ • ์‹œ ํ™•์žฅ์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜์„ฑ์„ ๋†’์ด๋Š” ๋ฐ ํฐ ๋„์›€๋œ๋‹ค.

profile
์ฝ”๋ฆฐ์ด

0๊ฐœ์˜ ๋Œ“๊ธ€