FrameWork/Spring Boot

블로그 기획하고 API 만들기 - 블로그 글 목록 조회

soooy0 2025. 3. 28. 13:36

글 추가하는 API를 만들었다. 이제는 추가한 글을 조회할 수 있는 API를 만들어보자.

서비스 메서드 코드 작성

 

BlogService.java 파일에 db에 저장되어 있는 글을 모두 가져오는 findAll()메서드 추가
/*
* 메서드: DB에 저장된 모든 글들을 조회하는 메서드
**/
public List<Article> findAll(){
    return blogRepository.findAll();
}

 

/api/articles GET요청이 오면 글 목록을 조회할 findAllArticles() 메서드를 작성해보자.

1. 응답을 위한 DTO 작성, DTO디렉터리에 ArticleReponse.java 파일 생성

@Getter
public class ArticleResponse {

    // 제목
    private final String title;
    // 내용
    private final String content;

    // 엔티티를 인수로 받는 생성자
    public ArticleResponse(Article article){
        this.title =  article.getTitle();
        this.content = article.getContent();
    }
}

 

controller 디렉토리에 있는 BlogApiController.java 파일>> 전체 글을 조회한 뒤 반환하는 findAllArticles() 메서드를 추가
/*
* GET 요청이 들어오면, 블로그의 모든 게시글을 가져와 JSON 형태로 반환
* @return
* */
@GetMapping("api/articles")
// ResponseEntity : HTTP 응답을 감싸는 객체로, HTTP 상태 코드 + 응답 데이터를 설정할 수 있음.
// List<ArticleResponse> : ArticleResponse 객체의 리스트를 반환.
public ResponseEntity<List<ArticleResponse>> findAllArticles() {
    // findAll() 메서드는 모든 게시글을 가져오는 역할을 함
    // 반환값: List<Article> (게시글 엔티티 리스트)
    List<ArticleResponse> articles = blogService.findAll()
            // Article 엔티티 리스트를 ArticleResponse DTO로 변환하는 과정
            // stream() : 가져온 List<Article>을 스트림으로 변환.
            // ((ArticleResponse는 게시글 데이터를 클라이언트에게 반환할 때 사용하는 DTO))
            .stream()
            // map(ArticleResponse::new)": Article 객체를 ArticleResponse 객체로 변환. 스트림의 각 요소를 다른 형태로 변환하는 메서드.
            // ArticleResponse::new는 new ArticleResponse(article)의 축약형.
            // 즉, ArticleResponse의 생성자를 호출해서 Article → ArticleResponse 변환.
            .map(ArticleResponse::new)
            // toList(): 변환된 ArticleResponse 리스트를 다시 List<ArticleResponse> 형태로 반환.
            .toList();

    // HTTP 응답 상태를 200 OK로 설정.
    // .body(articles) → 응답 본문(body)에 Body에 List<ArticleResponse> 객체가 담김.
    // 즉, 게시글 목록을 JSON 형태로 클라이언트에게 반환하는 역할을 함.
    return ResponseEntity.ok()
            .body(articles);
}
Q. 왜 JSON으로 바꿀까?
A. 웹과 모바일에서 가장 많이 쓰이는 데이터 형식이기 때문이다.

- JSON은 REST API의 표준 데이터 형식
- 웹 브라우저, 모바일 앱, 프론트엔드(React, Vue, Angular 등)에서 쉽게 다룰 수 있음
- 대부분의 프로그래밍 언어(JavaScript, Python, Java, Swift 등)에서 JSON을 쉽게 파싱할 수 있음.
- List<ArticleResponse> 같은 Java 객체를 그대로 반환하면 브라우저가 이해할 수 없음.
- Java의 객체를 문자열(JSON) 형태로 직렬화(Serialize)해야 함.
- 리턴 타입이 List<ArticleResponse>인데도, JSON으로 자동 변환돼서 응답됨!
(Spring Boot에서 @RestController나 @ResponseBody가 있으면 자동 변환됨)
- JSON을 사용하면, 백엔드(Spring Boot)와 프론트엔드(React, Vue, 모바일 앱)가 서로 독립적으로 개발 가능함.
   -> 백엔드는 JSON 형태의 데이터만 제공 프론트엔드는 JSON을 받아서 화면(UI)을 구성



 

실행 테스트

 

1. 테스트를 쉽게 하기 위해 data.sql 파일 생성, resorce/data.sql 생성

INSERT INTO article(title, content) VALUES ('제목 1', '내용 1')
INSERT INTO article(title, content) VALUES ('제목 2', '내용 2')
INSERT INTO article(title, content) VALUES ('제목 3', '내용 3')

 

2. 포스트맨 열어서 결과 확인

어랏.. insert가 실행되어 값이 들어가야 하는데 결과가 나오지 않는다. 왜지?

application.yml에서 보니 전에 data.sql이 자동으로 실행되지 않도록 설정해둔 코드가 있어서 sql이 실행되지 않았고, insert가 이루어지지 않는 것이었다.

"# data.sql이 자동으로 실행되지 않도록 설정
#Spring:
    sql:
      init:
       mode: never"

이 부분을 주석처리 해주었다.

 

Body에 잘 들어가는 것을 확인 가능

 

그럼 data.sql 파일은 언제 실행되는 걸까?

- 서버 실행 시 Article 엔티티 기반으로 테이블 생성 (ddl-auto) data.sql 실행
→ 미리 INSERT된 데이터가 DB에 저장됨
→ 클라이언트가 GET 요청 (/api/articles) 보내면 컨트롤러 실행 (findAllArticles())
→ JPA가 DB에서 Article 데이터를 가져옴 (SELECT * FROM article)
→ 데이터를 ArticleResponse로 변환 후 JSON 응답 반환

즉, data.sql은 서버가 실행될 때 실행되며, 컨트롤러는 요청이 왔을 때 실행되는 것
- data.sql은 스프링 부트 실행 시, SQL 문을 데이터베이스에 직접 실행하는 방식
- 즉, JPA가 개입하지 않고 DB에 바로 INSERT가 이루어짐
- 따라서 Article 엔티티 객체를 직접 생성하는 게 아니라, DB 테이블에 데이터가 들어가는 것.