카테고리 없음

Movie-diary (Spring Boot, JPA 기반 REST API 서버 구현)

com.oryneogury 2025. 12. 22. 12:07

영화 감상일지 프로젝트 - React + Spring Boot 연동 과제

본 영화에 대한 감상을 기록하고 공유할 수 있는 웹 애플리케이션을 개발했다.


프로젝트 개요

영화 감상일지는 React와 Spring Boot를 활용하여 구현한 풀스택 웹 애플리케이션이다. 사용자가 영화를 본 후 감상을 기록하고, 다른 사용자들의 기록을 탐색하며, 댓글을 통해 소통할 수 있는 기능을 제공한다.

이 프로젝트는 React SPA와 Spring Boot REST API 서버를 연동하는 실습을 목적으로 제작되었다.


주요 기능

1. 영화 감상 기록하기

본 영화에 대한 감상을 기록하는 기능을 구현했다.

  • 영화 제목: 영화 제목을 입력한다
  • 장르 선택: 액션, 드라마, 코미디, 로맨스, 스릴러 등 다양한 장르 중 선택한다
  • 평점: 1점부터 5점까지 별점으로 평가한다
  • 감상평: 영화를 보고 느낀 점을 작성한다 (최소 10자 이상)

감상 기록은 수정 및 삭제가 가능하다.


2. 감상 기록 탐색하기

다양한 방식으로 감상 기록을 탐색할 수 있다.

  • 전체 목록 보기: 모든 사용자가 작성한 감상 기록을 조회한다
  • 검색 기능: 영화 제목, 장르, 감상 내용으로 검색한다
  • 정렬 기능:
    • 최신순: 가장 최근에 작성된 순서대로
    • 오래된순: 가장 오래전에 작성된 순서대로
    • 평점 높은순: 높은 평점부터
    • 평점 낮은순: 낮은 평점부터
    • 제목순: 가나다 순서대로

3. 댓글 기능

다른 사용자의 감상 기록에 댓글을 작성할 수 있다.

  • 감상 기록에 대한 의견을 댓글로 표현한다
  • 본인이 작성한 댓글은 삭제할 수 있다

4. 회원 기능

회원 관리 기능을 구현했다.

회원가입

  • 이메일과 비밀번호로 가입한다
  • 이름을 설정하여 다른 사용자들에게 표시한다

로그인

  • 가입한 계정으로 로그인한다
  • 로그인 상태는 localStorage에 저장되어 유지된다

마이페이지

  • 프로필 관리: 이름을 수정할 수 있다
  • 내 감상 기록: 본인이 작성한 모든 감상 기록을 조회한다
  • 통계 정보:
    • 작성한 감상 기록 수
    • 평균 평점
    • 받은 댓글 수

5. 홈 화면

메인 화면에서는 다음을 확인할 수 있다.

  • 서비스 소개와 시작하기 버튼
  • 최근 감상 기록 6개를 미리보기로 제공
  • 전체 목록으로 이동하는 링크

기술 스택

프론트엔드

  • React 19.2.0: UI 라이브러리
  • Vite 7.2.4: 빌드 도구 및 개발 서버
  • React Router DOM 7.11.0: 클라이언트 사이드 라우팅
  • Styled Components 6.1.19: CSS-in-JS 스타일링
  • Zustand 5.0.9: 상태 관리 라이브러리

백엔드

  • Spring Boot 3.2.0: 백엔드 프레임워크
  • Spring Data JPA: 데이터베이스 연동
  • H2 Database: 인메모리/파일 기반 데이터베이스

구현 내용

프론트엔드 구현

  • React 함수형 컴포넌트와 Hooks를 사용하여 구현했다
  • Zustand를 사용하여 전역 상태를 관리한다
  • Styled Components로 컴포넌트별 스타일을 정의했다
  • React Router로 페이지 라우팅을 구현했다
  • REST API를 호출하여 백엔드와 통신한다

백엔드 구현

  • RESTful API 설계 원칙을 따라 엔드포인트를 구성했다
  • DTO를 사용하여 엔티티를 직접 반환하지 않도록 했다
  • JPA를 활용하여 데이터베이스 연동을 구현했다
  • 회원(Member), 게시글(Post), 댓글(Comment) 엔티티 간 연관관계를 설정했다

JPA 도입 전후 비교

처음에는 간단한 메모리 저장소(ArrayList)를 사용하여 데이터를 관리했다. 하지만 JPA를 도입하면서 많은 부분이 개선되었다.

이전 방식 (메모리 저장소)

// 간단한 ArrayList로 데이터 저장
private List<Post> posts = new ArrayList<>();

public void savePost(Post post) {
    posts.add(post);
}

public Post findById(Long id) {
    return posts.stream()
        .filter(p -> p.getId().equals(id))
        .findFirst()
        .orElse(null);
}

문제점:

  • 서버를 재시작하면 모든 데이터가 사라진다
  • 복잡한 검색이나 정렬을 직접 구현해야 한다
  • 연관관계를 수동으로 관리해야 한다
  • 트랜잭션 처리가 어렵다

JPA 도입 후

1. 엔티티 기반 객체 지향 프로그래밍

@Entity
@Table(name = "posts")
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "member_id")
    private Member member;

    @OneToMany(mappedBy = "post", cascade = CascadeType.ALL)
    private List<Comment> comments;
}

엔티티 클래스만 정의하면 데이터베이스 테이블이 자동으로 생성된다.

2. 자동 쿼리 생성

// 메서드 이름만으로 쿼리 자동 생성
public interface PostRepository extends JpaRepository<Post, Long> {
    List<Post> findAllByOrderByCreatedAtDesc();
    List<Post> findByMemberId(Long memberId);
    boolean existsByEmail(String email);
}

복잡한 SQL을 작성하지 않아도 메서드 이름만으로 쿼리가 자동 생성된다.

3. 연관관계 자동 관리

// 게시글 조회 시 연관된 회원 정보도 자동으로 가져옴
Post post = postRepository.findById(id);
String memberName = post.getMember().getName(); // 자동 조인

연관된 엔티티를 자동으로 조회할 수 있어 코드가 간결해진다.

4. JPQL을 활용한 복잡한 검색

@Query("SELECT p FROM Post p WHERE " +
       "LOWER(p.title) LIKE LOWER(CONCAT('%', :keyword, '%')) OR " +
       "LOWER(p.content) LIKE LOWER(CONCAT('%', :keyword, '%'))")
List<Post> searchByKeyword(@Param("keyword") String keyword);

객체 지향 쿼리 언어로 복잡한 검색도 쉽게 구현할 수 있다.

5. 트랜잭션 자동 관리

@Transactional
public PostDto.Response createPost(PostDto.CreateRequest request) {
    // 여러 작업이 하나의 트랜잭션으로 처리됨
    Member member = memberRepository.findById(...);
    Post post = Post.builder()...build();
    return postRepository.save(post);
}

@Transactional 어노테이션만으로 트랜잭션을 자동으로 관리할 수 있다.

JPA 도입의 장점

  1. 코드 간결화: SQL을 직접 작성하지 않아도 된다
  2. 데이터 영속성: 데이터베이스에 저장되어 서버 재시작 후에도 유지된다
  3. 연관관계 관리: 엔티티 간 관계를 자동으로 관리한다
  4. 타입 안정성: 컴파일 타임에 오류를 발견할 수 있다
  5. 유지보수성: 엔티티 수정 시 자동으로 스키마가 업데이트된다

개발 과정에서 배운 점

프론트엔드

  • Zustand를 사용한 상태 관리 방법을 학습했다
  • React Context API에서 Zustand로 마이그레이션하는 과정을 경험했다
  • 비동기 작업 처리와 에러 핸들링 방법을 익혔다
  • Styled Components를 활용한 스타일링 방법을 학습했다

백엔드

  • RESTful API 설계 원칙을 적용해보았다
  • DTO 패턴을 사용하여 API 응답을 구성하는 방법을 학습했다
  • JPA 연관관계 매핑을 실습했다
  • CORS 설정 방법을 학습했다

연동

  • 프론트엔드와 백엔드 간 데이터 통신 방법을 이해했다
  • Vite proxy 설정을 통해 CORS 문제를 해결하는 방법을 학습했다
  • API 요청/응답 형식을 일치시키는 중요성을 경험했다

부족한 점

기능적 부족한 점

  • 비밀번호가 암호화되지 않고 평문으로 저장된다
  • 페이지네이션이 없어 게시글이 많아지면 한 번에 모두 불러온다
  • 이미지 업로드 기능이 없다
  • 좋아요나 북마크 같은 추가 기능이 없다

사용자 경험

  • 일부 페이지에서 로딩 표시가 없다
  • 에러 메시지가 기술적이어서 사용자가 이해하기 어렵다
  • 모바일 화면에서 일부 레이아웃이 깨진다

코드 품질

  • 에러 처리가 일관되지 않다
  • 비슷한 코드가 여러 곳에 반복된다
  • 테스트 코드가 전혀 없다

프로젝트를 통해 배운 점

이 프로젝트를 통해 React와 Spring Boot를 연동하는 전체적인 흐름을 이해할 수 있었다. 특히 프론트엔드와 백엔드 간의 데이터 통신, 상태 관리, API 설계 등 풀스택 개발의 기본기를 학습할 수 있었다.

또한 실제 개발 과정에서 발생하는 문제들(CORS, 타입 불일치, 비동기 처리 등)을 해결하는 경험을 통해 실무에 필요한 문제 해결 능력을 기를 수 있었다.


마무리

이 프로젝트는 학습 목적으로 제작된 웹 애플리케이션이다. 기본적인 CRUD 기능과 사용자 인증 기능을 구현했으며, React와 Spring Boot를 연동하는 방법을 실습했다.

앞으로는 보안 강화, 성능 최적화, 추가 기능 구현 등을 통해 더 완성도 높은 프로젝트로 발전시킬 계획이다.

 

 

git 주소: https://github.com/heetwo2234/movie-diary-edit.git