[UMC 8주차] 인스타그램 개발 실전! - GET 사용하기

유보라·2022년 5월 11일
1

UMC 2기

목록 보기
11/14
post-thumbnail

안녕하세요! 보라입니다💜

벌써 8주차라니! 두 달이 정말 빠르게 지나갔던 것 같습니다.

저도 이제 바쁜 일들이 거의 끝나서, 공부에만 집중할 수 있게 되었답니다~!

코로나로 인해 잠시 쉬었던 운동도 다시 다니고 있고, 알바를 그만 두니 주말에 여유 시간이 생겨 너무 좋습니다😊

당장 급한 일을 처리하느라 살짜쿵 미뤄 놓았던 강의들만 조금.. 남은 상태입니다 호호

이번 주말을 활용하여 하긴 했지만, 꼼꼼히 하지 못 했던! 공부들을 해보려고 합니다😙

이번 주차 워크북 시작합니당!

  1. 실습 과정
  2. 트러블 슈팅
  3. 강의 후기

실습 과정

1. 유저 피드 조회 API

코드 작성

  • model

유저의 피드를 생각해보자.
나의 피드인지, 다른 사람의 피드인지에 따라 구성이 다르므로 구별하는 변수를 만들어준다.
또 피드에는 유저의 정보와 유저의 게시글들이 있는데, 다소 복잡하기 때문에 각각 객체 정보로 만들어주었다.
이때, 한 명의 유저는 여러 개의 게시글을 작성했을 수 있으므로 List로 만들어준다!

@Getter
@Setter
@AllArgsConstructor
public class GetUserFeedRes {
    private boolean _isMyFeed; //내 피드인지 다른 사람의 피드인지 구별 하는 변수
    private GetUserInfoRes getUserInfo;
    private List<GetUserPostsRes> getUserPosts;

}

피드를 나타내기 위한 유저 정보에는 무엇이 필요할까?
아래와 같이 만들어주었다.

@Getter
@Setter
@AllArgsConstructor
public class GetUserInfoRes {
    private String nickName;
    private String name;
    private String profileImgUrl;
    private String website;
    private String introduce;
    private int followerCount;
    private int followingCount;
    private int postCount;
}

마지막으로 유저가 작성한 게시글 정보이다. 게시글의 번호와 이미지가 필요하다.

public class GetUserPostsRes {
    private int postIdx;
    private String postImgUrl;

}
  • UserController
    //유저 피드 조회
    @ResponseBody
    @GetMapping("/{userIdx}") // (GET) 127.0.0.1:9000/users
    public BaseResponse<GetUserFeedRes> getUserFeed(@PathVariable("userIdx") int userIdx) {
        try{
            GetUserFeedRes getUserFeedRes = userProvider.retrieveUserFeed(userIdx, userIdx);
            return new BaseResponse<>(getUserFeedRes);
        } catch(BaseException exception){
            return new BaseResponse<>((exception.getStatus()));
        }
    }
  • UserDao
    유저 정보를 받아오는 함수
public GetUserInfoRes selectUserInfo(int userIdx){
        String selectUserInfoQuery = "SELECT u.userIdx as userIdx," +
                "       u.nickName as nickName, " +
                "       u.name as name, " +
                "       u.profileImgUrl as profileImgUrl, " +
                "       u.website as website, " +
                "       u.introduce as introduce,\n" +
                "        IF(postCount is null, 0, postCount) as postCount,\n" +
                "        IF(followerCount is null, 0, followerCount) as followCount,\n" +
                "        IF(followingCount is null, 0, followingCount) as followingCount\n" +
                "FROM User as u\n" +
                "    left join (SELECT userIdx, COUNT(postIdx) as postCount\n" +
                "                FROM Post\n" +
                "             WHERE status = 'ACTIVE'\n" +
                "             GROUP BY userIdx) p on p.userIdx = u.userIdx\n" +
                "    left join (SELECT followerIdx, COUNT(followIdx) as followerCount\n" +
                "                FROM Follow\n" +
                "                WHERE status = 'ACTIVE'\n" +
                "                GROUP BY followerIdx) f1 on f1.followerIdx = u.userIdx\n" +
                "    left join (SELECT followeeIdx, COUNT(followIdx) as followingCount\n" +
                "                FROM Follow\n" +
                "                WHERE status = 'ACTIVE'\n" +
                "                GROUP BY followeeIdx) f2 on f2.followeeIdx = u.userIdx\n" +
                "\n" +
                "WHERE u.userIdx = ? and u.status = 'ACTIVE';";

        int selectUserInfoParam=userIdx;

        return this.jdbcTemplate.queryForObject(selectUserInfoQuery,
                (rs,rowNum) -> new GetUserInfoRes(
                        rs.getString("nickName"),
                        rs.getString("name"),
                        rs.getString("profileImgUrl"),
                        rs.getString("website"),
                        rs.getString("introduce"),
                        rs.getInt("followerCount"),
                        rs.getInt("followingCount"),
                        rs.getInt("postCount")
                ),selectUserInfoParam);
    }

그리고! 유저의 게시물 리스트를 받아오는 함수

    public List<GetUserPostsRes> selectUserPosts(int userIdx){
        String selectUserPostsQuery =
                "SELECT p.postIdx as postIdx,\n" +
                "       pi.imgUrl as postImgUrl\n" +
                "FROM Post as p\n" +
                "    join User as u on u.userIdx = p.userIdx\n" +
                "    join PostImgUrl as pi on pi.postIdx = p.postIdx and pi.status = 'ACTIVE'\n" +
                "WHERE p.status = 'ACTIVE' AND u.userIdx = ?\n" +
                "GROUP BY p.postIdx\n" +
                "ORDER BY p.createdAt desc;";

        int selectUserPostsParam=userIdx;

        return this.jdbcTemplate.query(selectUserPostsQuery,
                (rs,rowNum) -> new GetUserPostsRes(
                        rs.getInt("postIdx"),
                        rs.getString("postImgUrl")
            
    	),selectUserPostsParam);
    }

작성하다보니, 유저 id가 정말 존재하는지 확인하는 validation이 필요하다!

그래서 UserDao에는 이렇게

UserProvider에는 이렇게 만들어주었다.

POSTMAN 테스트

//에러 발생

명세서 작성

2. 게시물 리스트 조회 API

코드 작성

게시물 리스트 조회 API를 만들기 위해서는 src 아래 경로에 post라는 새로운 패키지를 만들어줘야한다.

그래서 아래와 같이 만들어주었고, Post를 위한 Controller, Dao, Provider, Service도 만들어주었다. User의 코드를 참고했다!

  • model
//GetPostImgRes 파일
@Getter
@Setter
@AllArgsConstructor
public class GetPostImgRes {
    private int postImgIdx;
    private String imgUrl;

}

//GetPostsRes 파일
@Getter
@Setter
@AllArgsConstructor
public class GetPostsRes {
    private int postIdx;
    private int userIdx;
    private String nickName;
    private String profileImgUrl;
    private String content;
    private int postLikeCount;
    private int commentCount;
    private String updateAt;
    private String likeOrNot;
    private List<GetPostImgRes> imgs;
}
  • PostController
//PostController 파일 안에 작성
	@ResponseBody
    @GetMapping("") // 쿼리스트링
    public BaseResponse<List<GetPostsRes>> getPosts(@RequestParam int userIdx) {
        try{
            List<GetPostsRes> getPostsRes = postProvider.retrievePosts(userIdx);
            return new BaseResponse<>(getPostsRes);
        } catch(BaseException exception){
            return new BaseResponse<>((exception.getStatus()));
        }
    }
  • PostProvider
//PostProvider 파일 안에 작성
	public List<GetPostsRes> retrievePosts(int userIdx) throws BaseException {
        Boolean isMyFeed = true;

        if(checkUserExist(userIdx) == 0) {
            throw new BaseException(USERS_EMPTY_USER_ID);
        }
        try{
            List<GetPostsRes> getPosts = postDao.selectPosts(userIdx);

            return getPosts;
        }
        catch (Exception exception) {
            throw new BaseException(DATABASE_ERROR);
        }
    }

	//userid가 존재하는지 체크하는 함수
    public int checkUserExist(int userIdx) throws BaseException{
        try{
            return postDao.checkUserExist(userIdx);
        } catch (Exception exception){
            throw new BaseException(DATABASE_ERROR);
        }
    }
  • PostDao
	//피드를 보여주는 화면에서 필요한 데이터들을 받아와주는 함수
	public List<GetPostsRes> selectPosts(int userIdx){
        String selectPostsQuery =
                "SELECT p.postIdx as postIdx,\n" +
                        "       u.userIdx as userIdx,\n" +
                        "       u.nickName as nickName,\n" +
                        "       u.profileImgUrl as profileImgUrl,\n" +
                        "       p.content as content,\n" +
                        "       IF(postLikeCount is null, 0, postLikeCount) as postLikeCount,\n" +
                        "       IF(commnentCount is null, 0, commentCount) as commmentCount,\n" +
                        "       CASE WHEN timestampdiff(second, p.updatedAt, current_timestamp) < 60\n" +
                        "        THEN concat(timestampdiff(second, p.updatedAt, current_timestamp), '초 전')\n" +
                        "        WHEN timestampdiff(minute, p.updatedAt, current_timestamp) < 60\n" +
                        "        THEN concat(timestampdiff(minute, p.updatedAt, current_timestamp), '분 전')\n" +
                        "        WHEN timestampdiff(hour, p.updatedAt, current_timestamp) < 24\n" +
                        "        THEN concat(timestampdiff(hour, p.updatedAt, current_timestamp), '시간 전')\n" +
                        "        WHEN timestampdiff(day, p.updatedAt, current_timestamp) < 365\n" +
                        "        THEN concat(timestampdiff(day, p.updatedAt, current_timestamp), '일 전')\n" +
                        "        ELSE timestampdiff(year, p.updatedAt, current_timestamp)\n" +
                        "        END AS updatedAt,\n" +
                        "        IF(pl.status = 'ACTIVE', 'Y', 'N') as likeOrNot\n" +
                        "        FROM Post as p\n" +
                        "        JOIN User as u on u.userIdx = p.useridx\n" +
                        "        LEFT JOIN (SELECT postIdx, userIdx, count(postLikeidx) as postLikeCount\n" +
                        "                   FROM PostLike\n" +
                        "                   WHERE status ='ACTIVE'\n" +
                        "                   GROUP BY postIdx) as pl on p.postIdx = pl.postIdx\n" +
                        "        LEFT JOIN (SELECT postIdx, COUNT(commentIdx) as commentCount\n" +
                        "                   FROM Comment\n" +
                        "                   WHERE status='ACTIVE') as c on c.postIdx = p.postIdx\n" +
                        "        WHERE p.status = 'ACTIVE' and p.postIdx = ?";

        int selectPostsParam=userIdx;

        return this.jdbcTemplate.query(selectPostsQuery,
                (rs,rowNum) -> new GetPostsRes(
                        rs.getInt("postIdx"),
                        rs.getInt("userIdx"),
                        rs.getString("nickname"),
                        rs.getString("profileImgUrl"),
                        rs.getString("content"),
                        rs.getInt("postLikeCount"),
                        rs.getInt("commentCount"),
                        rs.getString("updatedAt"),
                        rs.getString("likeOrNOt"),
                        getPostImgRes=this.jdbcTemplate.query("\"SELECT pi.postImgUrlIdx, pi.imgUrl +\n" +
                                "              \"               FROM PostImgUrl as pi\" +\n" +
                                "              \"               JOIN Post as p on p.postIdx = pi.postIdx +\n" +
                                "              \"               WHERE pi.status = 'ACTIVE' and p.postIdx = ?;\"",
                                (rk,rownum) -> new GetPostImgRes(
                                        rk.getInt("postImgUrlIdx"),
                                        rk.getString("imgUrl")
                                ), rs.getInt("postIdx")
                                )

                ),selectPostsParam);
    }

	//userid가 존재하는지 체크하는 함수
    public int checkUserExist(int userIdx){
        String checkUserExistQuery = "select exists(select userIdx from User where userIdx = ?)";
        int checkUserExistParams = userIdx;
        return this.jdbcTemplate.queryForObject(checkUserExistQuery,
                int.class,
                checkUserExistParams);

    }

POSTMAN 테스트

명세서 작성

트러블 슈팅

문제 원인

Postman에서 테스트를 하려고 했는데 오류가 발생했다.


Database 에러라는 것을 보아, Provider 쪽 에러 같았다.

해결 방안

강의 후기

이번 강의는 본격적으로 코딩이 포함되어 있었던 것 같다! 사실 백엔드 개발자로 진로를 정하게 된 계기가 2학년 때 인터넷 프로그래밍 과목에서 웹 프로젝트를 했었던 것인데, 이번 주차 실습을 하면서 그때 생각이 났다 ㅎㅎ

인프 과목을 듣고 웹 개발에 흥미가 생겨서 프로젝트도 해보고 이것저것 해봤었던 게 기억이 난다. 그때는 그저 교수님이 가르쳐주시는 대로 따라하기만 했고, 따라하더라도 시간이 부족해서 Controller, Dao, Provider, Service 등을 왜 만드는지, 함수가 어떻게 동작하는지도 이해하지 못 했었다. 이제는 본격적으로, 나에게 맞는 분야를 찾아 자발적으로 공부를 해야하는 3학년이 되었고 지금 다시 접했을 땐 그때보다 수월하게 이해할 수 있었다.

그래도 아직은 조금 이해가 안되는 부분이 있긴 하다. 이번 주말에 시간이 널널하니 README 파일도 다시 한 번 읽어보면서 제대로 포스팅하게 될 것 같다!

그리고 실습하면서 느낀 건데, 인텔리제이 버그 너무 많고 진짜 구린 것 같다 ㅎㅎ😊😍 (근데 이클립스는 더 구림ㅋㅋ) 솔직히 내가 실수해서 오류 뜬 걸 인텔리제이 버그라고 생각해서 화난 적도 있긴 한데 인텔리제이 버그 뜰 때마다 진짜 화면 뿌시고 싶었다 ㅎㅎ😋✨(대충 그지같은 말을 예쁘게 쓰면 예쁜 말이 된다고 믿는 사람) 근데 이건 인텔리제이 입장도 들어봐야 될 듯 합니다 ㅋ

8주차가 되기까지 쉽게 온 것 같진 않지만, 제가 관심있는 분야를 공부할 수 있는 기회를 얻어서 행운이라고 생각합니다!! 다음주도 파이팅~

profile
인하대학교 컴퓨터공학과 학생입니다😀

0개의 댓글