SSAFIT | 2일차. 기본기능 구현

호떡·2022년 11월 15일
0

💡 sql 파일 및 전체적인 코드는 깃에 있음


임영묵, 남기정, 권오영(프론트 담당), 강지수, 이지우(DB 설계 및 더미 데이터 저장, 백엔드 comment와 follow 기능 구현), 최희수, 장유범(백엔드 User, Video, Favorite) 기능을 구현하였다.
📌 프론트와 백 간 request와 response에 대해서 소통 및 규약을 정확히 해야 함을 깨달았다. comment 기능을 구현할 때, 프론트 쪽에서 각 코멘트에 대해 사용자의 id 대신 닉네임을 띄워주고자 했고, 각 기능들에 대해 어떤 파라메터를 갖고 있는 요청이 들어오며, 어떤 응답을 줄지 세세히 결정하지 않은 탓에 중간에 comment dto에 사용자의 닉네임을 추가하였다. 다행히 DB 재설계나 controller를 수정하지 않아도 됐지만 큰 프로젝트에선 굉장히 당황스러울 것 같다.
📌 소통할 것들이 많았다. 연합팀 모두가 공유할 코드이기 때문에 모두의 동의가 필요하기도 했고, 작은 수정 사항 하나하나가 프론트, 백, DB 모두에 영향을 미치기 때문에 소통이 매우 중요했다. 직접 찾아가서 이야기를 나누기도 했지만, 영묵님이 공유해주신 노션에 수정사항들을 제때 기록해두니 그래도 직접 찾아가서 이야기 나눠야하는 번거로움은 줄어들었다.


DB 설계


더미 데이터 저장

Vue 수업 중 유튜브 API에서 구현했던 것을 활용하였다. 처음엔 일일이 유튜브 영상의 소스 코드를 복붙하여 title, video id, writer을 하나하나 다시 복사 붙여넣기를 하였다. 영묵님이 많은 영상들이 저장되어 있으면 좋겠다는 의견을 제시해서 axios로 50개씩 불러와 한꺼번에 저장하였다.
또한 카테고리별로 검색 기능 구현을 위해 video table에 category 컬럼을 추가하였고, category까지 추가한 더미 데이터를 저장하였다.
가슴 운동이나 어깨 운동의 경우 '운동'이라는 단어가 붙어야 우리가 원하는 데이터가 나왔다. 따라서 검색 키워드에 '운동'이라는 단어를 붙여 검색하였고, Table에 저장할 땐 UPDATE 쿼리문을 활용하여 다시 수정하였다.

 UPDATE video
 SET category='가슴'
 WHERE category = '가슴운동';

comment와 follow 기능 구현

Comment

comment 조회는 비디오별 조회, 개인별 조회, 코멘트 1개 조회 총 3가지 경우로 조회하는 것이 필요했다. 처음에는 3가지 경우를 하나로 묶어 한번에 처리하고 싶었지만, 일단 비디오별 조회와 개인별 조회는 리턴 타입이 List<Comment>이고, 1개만 조회는 리턴 타입이 Comment 객체 하나이기 때문에 RestController에서 이를 하나의 컨트롤러로 구분하기가 어려웠다. 따라서 리턴 타입에 따라 두 가지 컨트롤러로 나누기로 우선 결정하였다.
비디오별 조회와 개인별 조회는 mapper에서 동적 쿼리문을 활용하였다. v_id와 u_id는 둘 중 하나 null일 것이기 때문에 이를 활용하여 어느 것이 null이 아니면 v_id 혹은 u_id로 검색하는 것일테고, 그에 따른 comment들을 리스트로 반환할 것이다.
코멘트 1개만 조회는 동적 쿼리문을 활용하지 않았다.

@RestController
@RequestMapping("/api/commentApi")
public class CommentRestController {

	private static final String SUCCESS = "success";
	private static final String FAIL = "fail";

	@Autowired
	private CommentService commentService;

	// 댓글 작성
	@PostMapping("/")
	public ResponseEntity<String> regist(Comment comment) {
		int result = commentService.registComment(comment);

		if (result == 1) {
			return new ResponseEntity<String>(SUCCESS, HttpStatus.CREATED);
		}
		return new ResponseEntity<String>(FAIL, HttpStatus.OK);
	}

	// 댓글 리스트 조회 
	// 1) 비디오별 조회 2) 개인별 조회
	@GetMapping("/")
	public ResponseEntity<List<Comment>> selectList(String v_id, String u_id) {
		Comment comment = new Comment();
		comment.setV_id(v_id);
		comment.setU_id(u_id);
		
		return new ResponseEntity<List<Comment>>(commentService.getCommentList(comment), HttpStatus.OK);
	}
	
	// 댓글 1개 조회
	@GetMapping("/{c_id}")
	public ResponseEntity<Comment> selectOne(@PathVariable int c_id) {
		return new ResponseEntity<Comment>(commentService.getComment(c_id), HttpStatus.OK);
	}
	
	
	// 댓글 수정
	@PutMapping("/{c_id}")
	public ResponseEntity<String> modify(Comment comment) {
		int result = commentService.modifyComment(comment);

		if (result == 1) {
			return new ResponseEntity<String>(SUCCESS, HttpStatus.CREATED);
		}
		return new ResponseEntity<String>(FAIL, HttpStatus.OK);
	}
	
	
	// 댓글 삭제
	@DeleteMapping("/{c_id}")
	public ResponseEntity<String> delete(@PathVariable int c_id) {
		int result = commentService.removeComment(c_id);

		if (result == 1) {
			return new ResponseEntity<String>(SUCCESS, HttpStatus.CREATED);
		}
		return new ResponseEntity<String>(FAIL, HttpStatus.OK);
	}
}
<mapper namespace="com.ssafy.finalPjt.model.dao.CommentDao">
	
	
	<insert id="insertComment" parameterType="Comment" >
		INSERT INTO comment (u_id, v_id, content)
		VALUES(#{u_id}, #{v_id}, #{content})
	</insert>
	
	<select id="selectCommentList" parameterType="Comment" resultType="Comment">
		SELECT *, (SELECT nickname FROM user u WHERE u.u_id = c.u_id) as nickname
		FROM comment c
		<if test="v_id != null">
			WHERE v_id = #{v_id} 
		</if> 
		<if test="u_id != null">
			WHERE u_id = #{u_id} 
		</if>
	</select>
	
	<select id="selectOne" parameterType="int" resultType="Comment">
		SELECT *, (SELECT nickname FROM user u WHERE u.u_id = c.u_id) as nickname
		FROM comment c
		WHERE c_id = #{c_id}
	</select>

	<update id="updateComment" parameterType="Comment">
		UPDATE comment
		SET content = #{content}, reg_date = now()
		WHERE c_id = #{c_id}
	</update>

	<delete id="deleteComment" parameterType="int">
	DELETE FROM comment
	WHERE c_id = #{c_id}
	</delete>


</mapper>

Follow

팔로우 기능 구현은 팔로우 조회 혹은 팔로워 조회가 어려웠다. 이것도 comment의 비디오별 조회, 개인별 조회가 구현 로직은 똑같다. from_user와 to_user를 요청 파라메터로 받을 것이고 from_user가 null이 아니면 내가 팔로우 한 사용자를 조회하는 것이고, to_user가 null이 아니면 팔로워를 조회하는 것이다. 여기서 주의할 점은 응답이 <List<User>>라는 점이다.

@RestController
@RequestMapping("/api/followApi")
public class FollowRestController {
	private static final String SUCCESS = "success";
	private static final String FAIL = "fail";

	@Autowired
	private FollowService followService;
	
	// 팔로우 하기
	@PostMapping("/")
	public ResponseEntity<String> doFollow(Follow follow) {
		int result = followService.doFollow(follow);

		if (result == 1) {
			return new ResponseEntity<String>(SUCCESS, HttpStatus.CREATED);
		}
		return new ResponseEntity<String>(FAIL, HttpStatus.OK);
	}
	
	
	// 팔로우 취소
	@DeleteMapping("/")
	public ResponseEntity<String> unFollow(Follow follow) {
		int result = followService.unFollow(follow);

		if (result == 1) {
			return new ResponseEntity<String>(SUCCESS, HttpStatus.CREATED);
		}
		return new ResponseEntity<String>(FAIL, HttpStatus.OK);
	}
	
	// 팔로우 or 팔로워 조회
	@GetMapping("/")
	public ResponseEntity<List<User>> selectList(String from_user, String to_user) {
		Follow follow = new Follow();
		follow.setFrom_user(from_user);
		follow.setTo_user(to_user);
		
		return new ResponseEntity<List<User>>(followService.getFollowList(follow), HttpStatus.OK);
	}
}
<mapper namespace="com.ssafy.finalPjt.model.dao.FollowDao">
	
	<insert id="insert" parameterType="Follow">
		INSERT INTO follow
		VALUES (#{from_user}, #{to_user})
	</insert>
	
	<delete id="delete" parameterType="Follow">
		DELETE FROM follow
		WHERE from_user = #{from_user}
		AND to_user = #{to_user}
	</delete>
	
	
	<select id="selectUser" parameterType="Follow" resultType="User">
		SELECT * FROM user
		WHERE u_id in (SELECT
		<choose>
			<when test="from_user != null">
			to_user
			FROM follow WHERE
			from_user = #{from_user})
			</when>
			<otherwise>
			from_user
			FROM follow WHERE
			to_user = #{to_user})
			</otherwise>
		</choose>
	</select>


</mapper>

0개의 댓글