영화 감상일지 프로젝트 - 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 도입의 장점
- 코드 간결화: SQL을 직접 작성하지 않아도 된다
- 데이터 영속성: 데이터베이스에 저장되어 서버 재시작 후에도 유지된다
- 연관관계 관리: 엔티티 간 관계를 자동으로 관리한다
- 타입 안정성: 컴파일 타임에 오류를 발견할 수 있다
- 유지보수성: 엔티티 수정 시 자동으로 스키마가 업데이트된다
개발 과정에서 배운 점
프론트엔드
- 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를 연동하는 방법을 실습했다.
앞으로는 보안 강화, 성능 최적화, 추가 기능 구현 등을 통해 더 완성도 높은 프로젝트로 발전시킬 계획이다.