본문 바로가기
PROJECT

[JAVA] 웹 프로젝트 - 영화 리뷰 웹 사이트 'Film-E'

by sngynhy 2021. 10. 20.

프로젝트 주제 (팀 프로젝트로 진행)

영화 정보를 제공 하는 영화 리뷰 웹 사이트 제작

http://film-e.pe.kr

 

Film-E | Main

 

film-e.pe.kr

주제 선정 이유

  • With Corona로 전환을 앞두고, 영화관을 찾는 고객의 증가가 예상.
    - 따라서 다양한 영화 정보를 얻기 위한 사용자들의 니즈가 늘어나게 될 것으로 예측
    - 영화에 관한 다양한 시각들을 공유
  • 해외에는 로튼토마토, IMDB 같은 영화 리뷰를 보여주는 전문적인 사이트가 존재.
    - 국내 : 전문 영화 리뷰 플랫폼의 부재
    - 해외 : 언어적인 문제와 대한민국 정서에 특화된 디자인 구현 가능
    - Film-E (영화리뷰) 프로그램 기획
  • 기생충, 미나리, 오징어게임 등 전세계적으로 OTT 플랫폼 서비스를 통한 K영화,드라마에 대한 해외의 관심 증
    - K문화의 전문적인 사이트로서 
  • 추후 예고편 및 예매사이트 연결 등으로 다양한 개발의 방향성 제시 가능

목표

  • MVC 패턴 기반 (본인 담당 :  Controller)
  • 크롤링을 활용한 샘플 데이터 삽입
  • 파일 입출력
  • Ajax를 활용한 비동기적 처리 방식으로 SPA 구현
  • 반응형 웹 앱 구현

주요 기능

  • 리뷰 작성 및 별점 기능
  • 영화 정보 추가/수정 시 파일 입출력 및 미리보기 기능
  • 회원 가입 시 사용자로부터 입력 받은 값에 대하여 실시간으로 유효성 검사 실행
  • 랜덤 영화 추천
  • 보안 기능 - Admin 계정 진입시 유효성 체크와 uri입력을 통한 진입을 방지

내가 맡은 역할

  • Controller - ClientDB, ReviewDB 처리 담당
  • Crawling - Jsoup을 이용하여 샘플 데이터로 사용하기 위한 영화 데이터와 리뷰 데이터 크롤링
  • 별점 기능 구현

개발 환경

  • Language : JAVA (Eclipse)
  • Server : Apache Tomcat
  • DBMS : MySQL
  • Version Control : GitHub
  • Front-End : JSP / Java Script / jQuery / CSS

개발 일정 (2021-09/02 ~ 2021-10-18)

ERD

각 테이블은 참조되지 않고 트랜잭션 처리

ex) 회원 탈퇴 시 해당 회원의 리뷰 작성자명을 '알 수 없음'으로 처리

User Flow

Logic Process

 

  • 카테고리 페이지에 진입시 DB의 movie 테이블을 조회하여
    검색, 페이징, 장르선택을 고려하여 별점순으로 영화 리스트를 출력
  • 영화를 선택하여 리뷰페이지에 진입시, DB의 review 테이블을
    조회하여 페이징을 고려하여 최신순으로 리뷰 리스트를 출력
  • 리뷰는 영화당 1개만 입력가능하고, 별점과 리뷰를 입력하면
    현재시간으로 DB의 review 테이블에 저장

 

  • 관리자 페이지에 진입시 DB의 movie 테이블을 조회하여 검색, 페이징 고려하여 영화 리스트를 출력
  • 영화 등록 또는 영화 수정을 선택시 암호를 통해 관리자 인증을 한 후에 관리 페이지로 이동
  • 영화 등록, 수정, 삭제시 DB의 movie 테이블에 추가

 

  • 로그인 페이지에서 DB의 client 테이블을 조회하여 아이디와 비밀번호를 비교하여 로그인을 수행하고, 세션에 아이디 정보를 저장
  • 회원가입 페이지에서 정보를 입력받아 DB의 client테이블에 추가
  • my페이지에 진입시 세션에 저장된 아이디를 비교하여 DB의 client에서 회원정보 출력

 

Version

ver. 업데이트 기능 개발 일자
Film-E 1.1.1 1차 버그 리포트
MVC 취합
21.09.26
Film-E 1.1.4 파일 입출력 구현 21.09.29
Film-E 1.1.5 영화 크롤링 구현
페이징 구현
21.09.30
Film-E 1.2.1 리뷰 크롤링 구현 21.10.04
Film-E 1.2.4 미리보기 구현 21.10.06
Film-E 2.1.1 2차 버그 리포트 21.10.09
Film-E 2.1.3 별점 기능 구현 21.10.12
Film-E 2.1.6 Admin 보안 기능 구현 21.10.15

페이지 별 기능

메인 페이지

① 로고 이미지 클릭 시 메인 페이지 이동

② 활성 페이지

③ 각 메뉴 클릭 시 해당 페이지 이동

④ 영화 제목으로 검색

⑤ 로그인 페이지 이동

⑥ 스와이프 방식

    이미지 클릭 시 해당 영화 리뷰로 이동

⑦ 네이버 영화에서 크롤링한 데이터를

    평점 기준 내림차순으로 정렬

 

 

 

 

 

 

 

 

로그인 페이지

① 아이디 입력창

② 비밀번호 입력창

③ 로그인 버튼

④ 회원가입 페이지로 이동

 

 

 

 

 

 

 

 

 

 

회원가입 페이지

① 아이디 입력창

- Ajax를 이용한 비동기처리 방식으로 아이디 중복 검사

② 비밀번호 입력창

③ 비밀번호 확인 입력창

④ 이메일 입력창

> ①~④ jQuery를 이용한 실시간 유효성 검사

⑤ 회원가입 버튼

⑥ 초기화 버튼

⑦ 개인 정보 보호 정책 동의

 

 

 

 

카테고리 페이지

① 카테고리 표시

② 영화 이미지

 - 제목 순으로 정렬

 - 영화 상세 정보 페이지로 이동

③ 페이지네이션

 - 한 페이지 당 8개 출력

 - 현재 페이지 표시

④ 카테고리 메뉴

 - 아코디언 형식으로 장르 표시

 

 

 

 

 

 

리뷰 페이지

① 각 영화 별 제목, 장르, 평점, 개봉일, 줄거리

    표시

② 비 로그인 시 댓글 달기 불가능 및

    로그인 시 1000자 이내 댓글 달기 가능

    (이미 댓글을 달았을 시 댓글 삭제 가능)

③ 랜덤으로 영화 추천 기능

④ 해당 영화 리뷰 최신 순으로 정렬

 

 

 

 

 

 

 

 

관리자 페이지

① 관리자 메뉴

 - 관리자 계정으로 로그인 시 메뉴 표시

② 영화 이미지

 - 클릭 시 영화 수정 페이지로 이동

③ 영화 등록 버튼

 - 영화 등록 페이지로 이동

 

 

 

 

 

 

 

 

 

 

관리자 보안 설정

① 관리 비밀번호

 - 영화 삽입, 수정 페이지 진입 시 Tomcat

   서버에 설정된 암호를 입력해야 진입 가능

② 확인 버튼

 

 

 

 

 

 

 

 

 

 

영화 등록 페이지

① 이미지 파일 등록 ( jpeg, jpg, png 가능)

② 썸네일 미리 보기 

③ 영화 제목 작성

④ 영화 장르 선택

⑤ 영화 개봉일 선택

⑥ 영화 줄거리 작성

⑦ 영화 정보 등록 버튼

 

 

 

 

 

 

 

 

영화 수정/삭제 페이지

① 사진 파일 등록 가능( jpeg, jpg, png 가능)

② 썸네일 미리 보기 

③ 영화 제목 작성

④ 영화 개봉일 선택

⑤ 영화 줄거리 작성

⑥ 영화 정보 수정 버튼

⑦ 영화 삭제 버튼

 

 

 

 

 

주요 기능 코드

1. 보안 설정

1-1. 관리자 전용 ID/PW 설정 - tomcat 서버의 tomcat-users.xml 파일 내 <tomcat-users> 태그 안에 아래 코드 작성

<tomcat-users>
	<role rolename="admin"/>
	<user username="admin" password="1234" roles="admin"/>
</tomcat-users>

1-2. 프로젝트의 web.xml 파일에 관리자 페이지들 중 영화 추가/수정 페이지 진입 시 보안 설정이 작동하도록 설정

<security-role>
	<role-name>admin</role-name>
</security-role>
<security-constraint>
	<web-resource-collection>
		<web-resource-name>JspBook</web-resource-name>
		<url-pattern>/Admin.do</url-pattern>
		<http-method>GET</http-method>
		<http-method>POST</http-method>
	</web-resource-collection>
	
	<auth-constraint>
		<description></description>
		<role-name>admin</role-name>
	</auth-constraint>
</security-constraint>

1-3. 관리자 로그인 폼을 통해 정확한 암호를 입력 시 해당 보안 통과

<login-config>
	<auth-method>FORM</auth-method>
	<form-login-config>
		<form-login-page>/adminlogin.jsp</form-login-page>
		<form-error-page>/adminlogin.jsp</form-error-page>
	</form-login-config>
</login-config>

2. 파일 입출력 및 이미지 파일 미리보기

2-1. Form Data

enctype : form data가 서버로 제출될 때 해당 데이터가 인코딩되는 방식을 명시하는 속성

multipart/form-data: formdata가 여러부분으로 나뉘어서 서버로 전송됨

 

2-2. Controller

① 실제로 서버에 저장되는 path를 “img”로 설정 + 파일의 최대 크기를 16mb로 설정

② 파라미터로 request, 파일 저장 경로, 최대 용량, 인코딩, 중복 파일명에 대한 정책을 받음.

DefaultFilerenamePolicy() : 중복되는 파일 이름이 존재하는 경우 파일명 뒤에 숫자(n)를 붙여줌으로써 파일명 중복 방지

③ view에서 form형식을 enctype="multipart/form-data"로 보내주기때문에 컨트롤러에서 값을 받을 때 request가 아닌 선언한 multi로 받아줘야 함.

④ 영화 데이터 insert가 실패될 경우 등록 시 넣은 이미지 파일 데이터 삭제

 

2-3. 이미지 파일 미리보기

- 이미지 파일 미리보기를 위한 form

- 이미지 파일만 필터링해서 보이도록 accept 속성을 부여

- 선택한 파일의 객체를 파라미터로 넘겨 파일 타입 비교

document.addEventListener('DOMContentLoaded', function(){
    // 이미지 객체 타입으로 이미지 확장자 밸리데이션
    var validateType = function(img){
        return (['image/jpeg','image/jpg','image/png'].indexOf(img.type) > -1);
    }
    var validateName = function(fname){
        let extensions = ['jpeg','jpg','png'];
        let fparts = fname.split('.');
        let fext = '';
        if(fparts.length > 1){
            fext = fparts[fparts.length-1];
        }

        let validated = false;
        if(fext != ''){
            extensions.forEach(function(ext){
                if(ext == fext){
                    validated = true;
                }
            });
        }
        return validated;
    }

- 파일 입력 필드는 파일을 선택하면 "change" 이벤트 발생

  -> "change" 이벤트 리스너를 등록하여 파일 선택 시 썸네일 미리보기 처리

    // 파일 선택 필드에 이벤트 리스너 등록
    document.getElementById('imageSelector').addEventListener('change', function(e){
        let elem = e.target;
        if(validateType(elem.files[0])){
            let preview = document.querySelector('.thumb');
            preview.src = URL.createObjectURL(elem.files[0]); // 파일 객체에서 이미지 데이터 가져옴.
            document.querySelector('.dellink').style.display = 'block'; // 이미지 삭제 링크 표시
            preview.onload = function() {
                URL.revokeObjectURL(preview.src); // URL 객체 해제
            }
        }else{
        console.log('이미지 파일이 아닙니다.');
        }
    });

    document.querySelector('.dellink').addEventListener('click', function(e){
        let dellink = e.target;
        let preview = dellink.previousElementSibling;
        preview.src = ''; // 썸네일 이미지 src 데이터 해제
        document.querySelector('.dellink').style.display = 'none';
    });
});

3. 별점 기능

3-1. 라디오 버튼을 이용하여 별점 입력

<fieldset style="float: right;">
	<input type="radio" name="rating" value="5" id="rate1">
	<label for="rate1">⭐</label>
    <input type="radio" name="rating" value="4" id="rate2">
    <label for="rate2">⭐</label>
    <input type="radio" name="rating" value="3" id="rate3" checked>
    <label for="rate3">⭐</label>
	<input type="radio" name="rating" value="2" id="rate4">
	<label for="rate4">⭐</label>
    <input type="radio" name="rating" value="1" id="rate5">
    <label for="rate5">⭐</label>
</fieldset>

3-2. CSS를 이용하여 라디오버튼을 감추고 ☆를 클릭할수 있도록 변경

@charset "UTF-8";
#myform fieldset{
    display: inline-block; /* 하위 별점 이미지들이 있는 영역만 자리를 차지함.*/
    border: 0; /* 필드셋 테두리 제거 */
}
#myform input[type=radio]{
    display: none; /* 라디오박스 감춤 */
}
#myform label{
    font-size: 1.5em; /* 이모지 크기 */
    color: transparent; /* 기존 이모지 컬러 제거 */
    text-shadow: 0 0 0 #f0f0f0; /* 새 이모지 색상 부여 */
}
#myform label:hover{
    color:black; /* text 컬러 원상태로 */
    opacity:0.5; /* text 투명도 50% */
}
#myform label:hover ~ label{
    opacity:0.5;
    color:black;
}
#myform fieldset{
    display: inline-block; /* 하위 별점 이미지들이 있는 영역만 자리를 차지함.*/
    direction: rtl; /* 이모지 순서 반전 */
    border: 1px; /* 필드셋 테두리 제거 */
}
#myform fieldset legend{
    text-align: left;
}
#myform input[type=radio]:checked ~ label{
    opacity:1; /* text 투명도 100% */
    color:black;
}

3-3. 별점 등록 시 소수점 첫번째 자리 수 까지만 저장 + SQL AVG 함수를 이용하여 별점의 평균 계산 - 트래잭션 처리

String starAVG= "select avg(rating) from review where mpk = ?"; // 별점 평균 계산
String mUpdate= "update movie set ratingavg=? where mpk=?"; // 별점 평균을 해당 영화에 저장
public boolean r_insertDB(ReviewVO vo) throws SQLException{ // 리뷰 등록
	conn =JNDI.connect();
	boolean result =false;
	try {
		conn.setAutoCommit(false);
		
		pstmt=conn.prepareStatement(insert); // 리뷰 등록
		pstmt.setString(1, vo.getCmt());
		pstmt.setString(2, vo.getId());
		pstmt.setString(3, vo.getMpk());
		pstmt.setDouble(4, vo.getRating()); // 별점 추가
		pstmt.executeUpdate();
		
		pstmt=conn.prepareStatement(starAVG); // 별점 평균 
		pstmt.setString(1, vo.getMpk());
		ResultSet rs=pstmt.executeQuery();
		if(rs.next()) {
			ratingavg=rs.getDouble(1); 
		}
		rs.close();
        
		ratingavg = Math.round(ratingavg*10)/10.0;
		pstmt=conn.prepareStatement(mUpdate); // 별점 평균을 해당 영화에 저장
		pstmt.setDouble(1, ratingavg);
		pstmt.setString(2, vo.getMpk());
		pstmt.executeUpdate();

		conn.commit();
		conn.setAutoCommit(true);
		result = true;
	} catch (SQLException e) {
		e.printStackTrace();
		conn.rollback();
		conn.setAutoCommit(true);
	} finally {
		JNDI.disconnect(pstmt, conn);
	}
	return result;
}

개선 사항

현재 랜덤으로 영화를 추천해주고 있지만 많은 데이터가 쌓일 경우 회원들의 리뷰와 별점 데이터를 분석하여

각자 취향에 맞는 영화를 추천해주는 서비스로 개선할 수 있을거 같다.

느낀점

MVC 기반의 웹 제작에 대한 전반적인 흐름을 확실히 이해할 수 있는 유익한 시간이었다.

크롤링, 파일 입출력, 별점 처리 등 전에 해보지 않았던 기능들을 직접 구현하고 시도해 보면서

다양한 기능을 배울 수 있었고, 팀원들과 함께 소통하고 협력하며 즐겁게 프로젝트에 임할 수 있었다.

내가 구현한 기능들 외에 다른 팀원들의 코드를 분석하며 공부할 수 있는 시간이기도 했다.

현재 프로젝트 이전에 맨 처음 팀 프로젝트를 진행했을 때에는 소통의 부재와 부족한 설계로 난관에 부딪히기도 했지만,

이를 계기로 서로 간에 의사소통의 중요성을 느끼고 배울 수 있는 기회가 되었고,

여러 번의 팀 프로젝트를 거듭해 나가면서 탄탄한 설계를 통해 기대보다 더 완성도 있는 결과물이 만들어진 것 같아

만족스러운 프로젝트였다. (아주 재밌었음!)

 

Git : https://github.com/sngynhy/Fiim-E

Hosting : http://film-e.pe.kr

 

 

2021.10.01 - [PROJECT] - [JAVA] 네이버 영화 크롤링하여 DB에 저장하기 (영화 정보 및 리뷰)

 

[JAVA] 네이버 영화 크롤링하여 DB에 저장하기 (영화 정보 및 리뷰)

https://movie.naver.com/movie/running/current.naver 현재상영작 : 네이버 영화 상영 중 영화의 예매율/평점/좋아요 순 정보 제공. movie.naver.com 크롤링 과정 1. 아래 페이지에서 각 포스터 이미지 클릭을 하..

sngynhy.tistory.com