Portfolio - MovieCommunitySite
Movie Community - 영화 커뮤니티 프로젝트
Movie Community는 영화에 관한 소통과 공유를 중심으로 하는 영화 커뮤니티 웹 사이트입니다. 사용자들은 영화에 대한 의견을 나누고, 추천을 받을 수 있으며, 특정 요일이나 조건에 따라 개인 맞춤형 추천 서비스를 이용할 수 있습니다. 또한 영화 검색과 리뷰 기능을 통해 다양한 영화 정보를 찾고 공유할 수 있습니다.
주요 기능
영화 토론과 추천
- 사용자들은 영화에 대한 토론을 자유롭게 할 수 있습니다.
- 특정 요일마다 추천되는 영화를 확인하고, 사용자 개인의 취향에 맞는 영화를 추천 받을 수 있습니다.
영화 검색
- 웹 사이트 내에서 영화를 검색하여 자세한 정보를 확인할 수 있습니다.
- 검색 결과를 다양한 기준으로 필터링하여 사용자 편의에 맞게 제공됩니다.
영화 리뷰 기능
- 사용자들은 영화에 대한 리뷰를 작성하고 다른 사용자들과 공유할 수 있습니다.
- 리뷰는 별점과 함께 제공되어 사용자들이 평가를 쉽게 확인할 수 있습니다.
기술 스택
백엔드
- Spring Boot
- Spring
- Java
- MyBatis
프론트엔드
- JavaScript
- jQuery
- CSS 및 Bootstrap
- HTML
데이터베이스
- Oracle DB
웹 서버
- Apache Tomcat
개발 과정과 역할
프로젝트 개발 과정 팀장 역할 수행 및 업무 진행
프로젝트 관리
- 깃허브를 활용한 버전 관리 및 이슈 트래킹으로 팀원들과의 협업
- 스프린트 계획 및 회고를 통해 프로젝트 일정을 관리, 팀원 간의 원활한 소통 유지
팀원 역할 분담
- 팀원 역할과 책임 분담으로 효율적인 개발 진행
- 코드 리뷰 및 팀원 간의 지식 공유를 통해 코드 품질 향상
개발
- 주요 회원 기능과 게시판 기능 구현
- Spring Boot, MyBatis를 활용하여 안정적이고 효율적인 백엔드 구조 구축
기능 구현
- 입력 정보 전송 -> 서버 -> 데이터베이스 매칭 -> 인증 성공 수행
데이터베이스 매칭 실패 -> 인증 실패 수행- 코드: RESTful API ‘POST’ 구현
1 2 3 4 5 6 7 8 9 @PostMapping("login") public User login(@RequestBody User userLogin, HttpSession session) { User user = userService.loginValidate(userLogin); if(user != null) { session.setAttribute("userId", user.getUserId()); session.setAttribute("userNum", user.getUserNum()); } return user; }- 설명: 로그인은 상태 변경 동작이라 명확하게 나타내기 위해 REST API 사용
- 개선점 1. 비밀번호 해시처리 필요 -> Spring Security || 해시 함수 구현을 통해 개선 가능
2. 토큰 기반의 인증 방식 도입시 세션보다 더욱 단순하게 관리 가능 -> JWT 활용으로 개선 가능
3. 응답 형식 표준화 필요 -> ResponseEntity로 상태 코드, 메시지 명시적 반환으로 개선 가능
4. HTTPS 사용 고려 -> 데이터 암호화로 데이터 변조나 도청을 방지, SEO 이점
- 로그아웃 -> 세션 종료, 로그인 상태 해제 -> 리다이렉트
- 코드:
1 2 3 4 5 6 @GetMapping("/logout") public ModelAndView logout(ModelAndView mv, HttpSession session) { session.invalidate(); mv.setViewName("redirect:/"); return mv; }- 설명: REST API 사용
- 개선점 1. GET은 보안에 취약 -> POST 메서드 사용으로 개선 가능
2. 간소화 가능 -> 반환 타입 String으로 개선 가능
1 2 3 4 5 @PostMapping("/logout") public String logout(HttpSession session) { session.invalidate(); return "redirect:/"; }
- 입력 정보 전송 -> 서버 -> 데이터베이스 매칭 -> 인증 성공 수행
데이터베이스 매칭 실패 -> 인증 실패 수행- 코드:
1 2 3 4 5 6 7 8 9 10 @PostMapping("addUser") public void addUser(@RequestBody UserGenre userGenre) { User user = userGenre.getUser(); userService.addUser(user); User userNum = userService.getUser(user.getUserId()); List<Integer> genres = userGenre.getGenreNum(); for(int genre: genres) { userService.addUserGenre(userNum.getUserNum(), genre); } }- 설명: REST API 사용, 선호장르는 없음, 단수, 복수 입력가능
- 개선점 1. 동시성 측면 고려 -> 트랜젝션 관리, 비지니스 로직을 서비스계층으로 분리로 개선 가능
1 2 3 4 5 6 7 8 UserController 작성 @PostMapping("addUser") public void addUser(@RequestBody UserGenre userGenre) { User user = userGenre.getUser(); userService.addUser(user); List<Integer> genres = userGenre.getGenreNum(); // 사용자 추가 후 바로 장르 추가 userService.addUserGenres(user.getUserId(), genres); } // UserController 비지니스 로직 제거
1 2 3 4 5 6 7 8 9 10 UserServiceImpl 작성 @Override @Transactional public void addUserGenres(String userId, List<Integer> genreNums) { User user = getUser(userId); int userNum = user.getUserNum(); for (int genre : genreNums) { addUserGenre(userNum, genre); } // 비지니스 로직 추가 }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 UserServiceImpl 작성 @Override @Transactional public void addUserGenre(int userNum, int genreNum) { try { // 데이터베이스 연결 및 트랜잭션 시작 Connection connection = // 데이터베이스 연결 객체 생성 connection.setAutoCommit(false); // 트랜잭션 시작 // SQL 쿼리를 사용하여 사용자와 장르 간의 관계 추가 String query = "INSERT INTO UserGenre (userNum, genreNum) VALUES (?, ?)"; try (PreparedStatement preparedStatement = connection.prepareStatement(query)) { preparedStatement.setInt(1, userNum); preparedStatement.setInt(2, genreNum); preparedStatement.executeUpdate(); } connection.commit(); // 트랜잭션 커밋 } catch (SQLException e) { connection.rollback(); // 예외 발생 시 롤백 e.printStackTrace(); // 예외 처리는 적절하게 수행 } finally { connection.close(); // 데이터베이스 연결 종료 } }
- 사용자 정보 조회 -> 뷰 전달 -> 사용자 정보 출력
- 코드:
1 2 3 4 5 6 7 @GetMapping("mypage") public ModelAndView mypage(ModelAndView mv, HttpSession session) { User user = userService.getUser((String)session.getAttribute("userId")); mv.addObject("user", user); mv.setViewName("user/mypage"); return mv; }- 설명: 정보 조회, 계정 관리, 로그아웃, 회원탈퇴 등의 기능 제공
- 개선점 1. 간소화 가능 -> 반환 타입 String으로 개선 가능
-> 모델에 직접 데이터 추가, 뷰 이름 반환으로 코드 간결화 가능
1 2 3 4 5 6 @GetMapping("mypage") public String mypage(Model model, HttpSession session) { User user = userService.getUser((String) session.getAttribute("userId")); model.addAttribute("user", user); return "user/mypage"; }
- 수정할 데이터 입력 -> 유효성 검사 -> 회원 정보 수정
- 코드:
1 2 3 4 5 6 7 8 9 10 @PutMapping("fixUser") public int fixUser(@RequestBody UserGenre userGenre) { userService.delUserGenre(userGenre.getUser().getUserNum()); userService.fixUser(userGenre.getUser()); List<Integer> genres = userGenre.getGenreNum(); for(int genre: genres) { userService.addUserGenre(userGenre.getUser().getUserNum(), genre); } return userService.fixUser(userGenre.getUser()); }- 설명: 사용자가 원하는 내용으로 데이터 수정
- 개선점 1. 데이터 일관성 유지 -> 트랜젝션으로 개선 가능
2. 비동기 처리 고려 -> 응답 시간 향상 가능 But 코드 복잡성 증가, 가독성 저하 가능성 있음
3. Soft Delete 고려 -> 데이터 보존, 복구 가능 But 데이터 크기 증가, 쿼리 복잡성 증가
- 회원 탈퇴 -> 회원 탈퇴 ID Number 저장
- 코드:
1 2 3 4 5 @PostMapping("addWithDrawal") public void addWithDrawal(@RequestBody User userNum, HttpSession session) { userService.addWithDrawal(userNum.getUserNum()); session.invalidate(); }- 설명: 회원 탈퇴 테이블에 탈퇴한 ID 보관
- 개선점 1. 명확성 및 확장성 고려 -> DTO 클래스로 개선 가능
2. 탈퇴 아이디 정보 고려 -> 토큰, 세션 등을 활용하여 탈퇴 정보 없이 관리
프로젝트 개선 방향
보안강화
- Spring Security를 사용하거나 해시 함수 구현
- HTTPS 사용
JWT 도입
- 효율적으로 세션 관리
클라이언트 통신 최적화
- AJAX나 비동기 처리로 응답 속도 향상
코드 리팩토링 및 구조화
- 비지니스 로직과 트랜잭션 관리를 서비스 계층으로 분리하여 확장성, 간결성 증가