본문 바로가기
Spring Boot :

[FN] 신청서 조회 API

by 밍코딩코 2025. 3. 6.

모임 신청에 대한 신청서 전송과 모임장에게 푸시 알림이 가도록 구현이 완료되었으니

이제는 내가 신청한 신청서와 내 모임에 도착한 신청서를 확인하고 신청 취소, 신청 승인, 신청 거절과 같은 

신청서 상태 관리를 구현해보자

 

신청서를 Firestore Database에서 바로 불러와도 되지만, 코드 가독성과 유지보수가 어려울 수도 있을 것 같아서 Spring boot로 백엔드 API를 구축하기로 하였다.

 

Spring Boot 기본 설정은 아래 게시글 참고하기

 

[FN] Intellij Community에서 Spring Boot 사용하기

무료 버전인 Intellij Community는 Spring Initializr에서 프로젝트를 생성하고 불러와야한다.react native 프로젝트에서 모임 신청자가 모임장에게 신청서를 보내면 해당 신청서가 도착했다는 알림은 FCM을

codingco.tistory.com

 

Firebase 관련 설정은 아래 게시글에서

 

[FN] Spring Boot API / FCM Token 전송

모임 신청을 하고 신청에 대한 알림을 FCM으로 모임장에게 띄워주기 위해서React Native에서 Spring Boot 서버로 FCM 토큰을 보내주어야하는데 로컬호스트:포트 번호로 연결할 수는 있지만,다른 기기나

codingco.tistory.com

 

1. Firestore 데이터 조회

lombok 의존성 추가

    implementation 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
    
    testImplementation 'org.projectlombok:lombok:1.18.30'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'

 

Firestore Database에서 meetings 컬렉션과 그 하위 컬렉션인 applications 컬렉션을 조회하는 역할을 하는 MeetingRepository.java 파일을 생성한다.

 

@Repository
public class MeetingRepository {

    private final Firestore db;

    public MeetingRepository(Firestore db) {
        this.db = db;
    }
  • @Repository : Spring에서 이 클래스를 Bean으로 관리하도록 지정(데이터 저장소와 관련된 역할) / FirebaseConfig에서 만든 Bean을 주입받아 사용
  • Firestore db : Firestore 인스턴스를 받아 사용
  • final :  한 번 값이 할당되면 이후에 다른 값으로 재할당 x / 불변성 보장
  • 생성자 : 인스턴스를 생성할 때 호출됨 / Firestore 객체를 받아서 this.db에 저장

Bean의 흐름

  • Spring이 FirebaseConfig를 실행하여 firestore() 메서드 호출 -> Firestore 인스턴스를 생성하고 Bean으로 등록
  • MeetingRepository가 생성될 때, Firestore 인스턴스가 자동으로 주입 -> 생성자에서 Firestore db를 받아 사용

 

public List<MeetingResponse> getMeetings() throws ExecutionException, InterruptedException {
    List<MeetingResponse> meetings = new ArrayList<>();
    List<QueryDocumentSnapshot> documents = db.collection("meetings").get().get().getDocuments();

    for (QueryDocumentSnapshot doc : documents) {
        String id = doc.getId();
        String title = doc.getString("title");
        String imageUrl = doc.getString("imageUrl");
        String createdAt = doc.getString("createdAt");

        meetings.add(new MeetingResponse(id, title, imageUrl, createdAt));
    }
    return meetings;
}

 

  • getMeetings() 메서드 : 게시글 목록을 조회함

throws : 비동기 작업을 처리하는 도중 예외가 발생할 수 있음을 선언, 호출한 곳에서 처리하도록 요구

  • Firestore에서 가져온 게시글 데이터를 저장할 meetings 리스트를 생성
  • documents : meetings 컬렉션의 모든 문서를 가져와 .get().get()으로 동기적으로 데이터를 가져옴
  • for문으로 게시글 Id, title, imageUrl을 가져옴

향상된 for문 : 컬렉션(리스트 등)이나 배열을 순차적으로 순회하면서 각 항목을 하나씩 처리하는 반복문

  • 가져온 데이터를 MeetingResponse 리스트로 변환
  • 반환

모임글의 신청서 정보를 가져오는 코드도 위와 같다.

public List<ApplicationResponse> getApplications(String meetingId) throws ExecutionException, InterruptedException {
    List<ApplicationResponse> applications = new ArrayList<>();
    List<QueryDocumentSnapshot> documents = db.collection("meetings")
            .document(meetingId)
            .collection("applications")
            .get().get().getDocuments();

    for (QueryDocumentSnapshot doc : documents) {
        String id = doc.getId();
        String nicName = doc.getString("nicName");
        String message = doc.getString("message");

        applications.add(new ApplicationResponse(id, nicName, message));
    }
    return applications;
}

 

 

 

2. DTO 생성

Firestore에서 가져온 데이터를 가공 -> 프론트엔드로 전달

 

모임 게시글 DTO

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class MeetingResponse {
    private String id;
    private String title;
    private String imageUrl;
}

 

신청서 DTO

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class ApplicationResponse {
    private String id;
    private String nicName;
    private String message;
}

 

3. REST API 컨트롤러

프론트엔드에서 호출할 수 있도록 API 엔드포인트를 만듬 

package com.example.project;

import com.example.project.MeetingResponse;
import com.example.project.ApplicationResponse;
import com.example.project.MeetingRepository;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.ExecutionException;

@RestController
@RequestMapping("/api/meetings")
public class MeetingController {

    private final MeetingRepository meetingRepository;

    public MeetingController(MeetingRepository meetingRepository) {
        this.meetingRepository = meetingRepository;
    }

    // 게시글 목록 조회 (title, imageUrl만 조회)
    @GetMapping
    public List<MeetingResponse> getMeetings() throws ExecutionException, InterruptedException {
        return meetingRepository.getMeetings();
    }

    // 게시글의 신청서 목록 조회 (nicName, message만 조회)
    @GetMapping("/{meetingId}/applications")
    public List<ApplicationResponse> getApplications(@PathVariable String meetingId) throws ExecutionException, InterruptedException {
        return meetingRepository.getApplications(meetingId);
    }
}
  • @RestController : Spring Boot에서 REST API를 처리하는 컨트롤러 클래스에 붙임 / HTTP 요청을 처리하고 응답을 반환 / 메서드에서 반환된 객체가 자동으로 JSON 형식으로 변환되어 클라이언트에게 응답
  • @RequestMapping : 클래스에 대한 기본 URL 경로를 설정
  • meetingRepository : 게시글 및 신청서 데이터를 가져오는 역할
  • 생성자 : MeetingController 클래스가 생성될 때 MeetingRepository 객체를 자동으로 전달
  • @GetMapping : 클라이언트가 /api/meetings 경로로 GET 요청을 보내면 이 메서드가 실행
  • @PathVariable: URL 경로에서 meetingId 값을 추출하여 메서드의 매개변수 meetingId로 전달

 

조회 결과

localhost:8081/api/meetings로 firestore에 저장된 meeting 컬렉션의 id, title, imageUrl 조회

 

 

localhost:8081/api/meetings/게시글id/applications 를 통해서 해당 게시글의 신청서 조회

 

애플리케이션에서 데이터를 조회하고 신청서의 상태를 관리하는 과정은 다음 게시글에 정리하겠슴