88DAYS) [Pre-Project] 응답 데이터 작성, Member-Question 매핑, findByMemberId

nacSeo (낙서)·2023년 2월 22일
0

아침 회의를 끝내고, FE쪽으로 넘겨줄 데이터를 응답 JSON 데이터를 작성하는 것으로 하루를 시작했다.

CRUD를 바탕으로 Request와 Response로 나누어 Response로 넘어가는 Body안의 데이터값을 구체적으로 작성해 FE쪽으로 넘겨주는 작업이다.

✅ CREATE

Request

  • POST /questions
{
    "title" : "질문제목입니다",
    "contents" : "질문 내용입니다.",
    "memberId" : 1
}

Response

status : 201 Created

  • Header
  • Body
{
    "code": "201",
    "message": "CREATED",
    "data": null
}

✅ Read

✔︎ 한 개의 질문 데이터

Request

  • GET /questions/1

Response

status : 200 OK

  • Header
  • Body
{
    "code": "200",
    "message": "SUCCESS",
    "data": {
        "id": 1,
				"title": "질문 제목",
				"contents" : "질문 내용",
        "createdAt" : "2023-02-22T10:30:00",
				"modifiedAt": "2023-02-22T10:30:00",
				"member": {
						"id" : 1,
						"name": "coco",
						"profileImage": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f9d2aa78-51b8-44ea-ae39-4514df3f4d8a/df2638245d621a52a0a52b9bb9700477.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230221%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230221T031120Z&X-Amz-Expires=86400&X-Amz-Signature=8ccd44c8339460591fe90918de6e3ffd918d42d12f54730c1732d59eca214d71&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22df2638245d621a52a0a52b9bb9700477.png%22&x-id=GetObject"
				},
				"answers" : [
					 {
							"id": 2,
			        "contents": "답변2",
			        "createdAt" : "2023-02-22T10:35:00",
							"modifiedAt": "2023-02-22T10:35:00",
							"member": {
								"id" : 2,
								"name": "nacseo",
								"profileImage": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f9d2aa78-51b8-44ea-ae39-4514df3f4d8a/df2638245d621a52a0a52b9bb9700477.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230221%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230221T031120Z&X-Amz-Expires=86400&X-Amz-Signature=8ccd44c8339460591fe90918de6e3ffd918d42d12f54730c1732d59eca214d71&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22df2638245d621a52a0a52b9bb9700477.png%22&x-id=GetObject"
							}
				   },
					 {
							"id": 1,
			        "contents": "답변1",
			        "createdAt" : "2023-02-22T10:40:00",
							"modifiedAt": "2023-02-22T10:40:00",
							"member": {
								"id" : 3,
								"name": "kimcoding",
								"profileImage": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f9d2aa78-51b8-44ea-ae39-4514df3f4d8a/df2638245d621a52a0a52b9bb9700477.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230221%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230221T031120Z&X-Amz-Expires=86400&X-Amz-Signature=8ccd44c8339460591fe90918de6e3ffd918d42d12f54730c1732d59eca214d71&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%22df2638245d621a52a0a52b9bb9700477.png%22&x-id=GetObject"
							}
				   }
			  ]
    }
}

✔︎ 여러 개의 질문 데이터

Request

  • GET /questions

Response

status : 200 OK

  • Header
  • Body
{
    "code": "200",
    "message": "SUCCESS",
    "data": [
        {
            "id": 2,
            "title": "질문2 제목",
            "contents": "질문2 내용",
            "createAt": "2023-02-22T10:30:00",
            "modifiedAt": "2023-02-22T10:30:00",
            "member": {
                "id": 2,
                "name": "nacseo",
                "profileImage": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f38066b8-ad73-4e02-8bb2-8d6a69110a9c/7839bcaccc3359d426e4b9bda6598fe6.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230221%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230221T030701Z&X-Amz-Expires=86400&X-Amz-Signature=6a33b1e1ab867f28d08f35cd0050503634a6b6b6ea8ef788520b97ea37f99911&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%227839bcaccc3359d426e4b9bda6598fe6.png%22&x-id=GetObject"
            },
        },
        {
            "id": 1,
            "title": "질문1 제목",
            "contents": "질문1 내용",
            "createAt": "2023-02-22T10:25:00",
            "modifiedAt": "2023-02-22T10:25:00",
            "member": {
                "id": 1,
                "name": "coco",
                "profileImage": "https://s3.us-west-2.amazonaws.com/secure.notion-static.com/f38066b8-ad73-4e02-8bb2-8d6a69110a9c/7839bcaccc3359d426e4b9bda6598fe6.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Credential=AKIAT73L2G45EIPT3X45%2F20230221%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20230221T030701Z&X-Amz-Expires=86400&X-Amz-Signature=6a33b1e1ab867f28d08f35cd0050503634a6b6b6ea8ef788520b97ea37f99911&X-Amz-SignedHeaders=host&response-content-disposition=filename%3D%227839bcaccc3359d426e4b9bda6598fe6.png%22&x-id=GetObject"
            },
        }
    ],
    "pageInfo": {
        "page": 1,
        "size": 10,
        "totalElements": 2,
        "totalPages": 1
    }
}

✅ UPDATE

Request

  • PATCH /questions/1
{
    "title": "수정된 질문 제목입니다",
    "contents": "수정된 질문 내용입니다."
}

Response

status : 301 Moved Permanently

  • Header
  • Body
{
    "code": "200",
    "message": "UPDATED",
    "data": "/questions/1"
}

✅ DELETE

Request

  • DELETE /questions/1

Response

status : 204 No Content

  • Header
  • Body ❌

요론식으로 작성해줬다.


다음으로는 Question CRUD 기능을 전반적으로 살펴보며 수정하는 작업을 진행하였다.
이제는 작업 하나를 마칠 때마다 습관적으로 git pull을 받고 commit해서 push, dev 브랜치로 pr 및 merge 해준다. 처음엔 좀 무서웠는데 이제 슬- 적응이 되어가나부다.


이제 또 필요한 건 테이블 간의 연관 관계 매핑이다.
우리가 만드는 프로젝트에는 크게 Member, Question, Answer 파트가 있고 서로서로 연관 관계 매핑이 필요했다. 마침 Member를 담당하는 동료분도 매핑을 해야할 단계라 zeb에서 만나 함께 매핑을 진행해주었다. 매핑 과정에서 에러가 발생 💥

고생 끝에 디버깅과 구글링으로 해결해부렸다.

일대다, 다대일 매핑 과정에서 서로를 계속 참조하는 무한 재귀함수가 발생한 것이다. 따라서, ManyToOne 컬럼에 @Jsonignore 애너테이션을 활용하여 순환 참조 관계를 막아 해결해줬다.

참고사이트1
참고사이트2
참고사이트3

또, questionDto와 question 엔티티에서 questionId를 id로 리팩토링하는 과정이 진행되었는데, 리팩토링을 완료하고 실행해서 postman으로 테스트했는데 getQuestions에서 에러가 발생했다. 최근 애용하게 된 디버깅을 여러 번 반복하며 결국 에러 원인을 찾아냈다.

getQuestions의 service인 findQuestions에서 페이지네이션을 구현하기 위한 과정의 Sort.by("question-id")안 question-id가 문자열이기에 자동 리팩토링이 안되었다. 따라서 직접 Sort.by("id")로 변경해주어 에러를 해결하였다.



오늘의 마지막 작업으로 findByMemberId를 만들어보았다. MemberId에 해당하는 모든 Question들을 가져오는 메서드다.
지금까진 JpaRepository를 상속받아 QuestionRepository를 사용하였는데, JpaRepository 인터페이스에 구현된 메서드가 아닌, 직접 만들어 사용해줘야하는 메서드를 위해 QuestionCustomRepository 인터페이스를 생성했다.
그 후, 이 인터페이스를 구현하는 QuestionCustomRepositoryImpl 클래스를 생성해 JPAQuery를 사용하여 작성해주었다. JPAQueryFactory를 Spring Bean에 등록시키고, 구글링을 해서 JPAQuery에 대해 공부하며 해당 메서드를 구현해냈다.

public List<Question> findByMemberId(Long id) {
        QQuestion q = new QQuestion("q");
        return queryFactory
                .select(q)
                .from(q)
                .where(q.id.eq(id))
                .orderBy(q.id.desc())
                .limit(10)
                .fetch();
    }

아직 Member를 담당하는 동료분과 같이 확인은 못해봤지만, MemberId에 해당하는 질문들을 리스트 형식으로 내림차순(최신순) 10개까지 보여줄 수 있도록 하는 메서드로써 작성하였다.

QuestionService에서도 Member에서 사용할 수 있도록

public void findQuestionsOfMember (Long memberId) {
        questionRepository.findByMemberId(memberId);
    }

요로코롬 구현해놨다. 내일 한 번 맞춰봐야지!

JPAQuery에 대해서는 프로젝트를 하며 처음 다뤄봤는데 낯설면서 신기한 기술이었다. 잘 활용한다면 나중에도 도움이 많이 될 것 같다 :)
참고사이트1
참고사이트2

profile
백엔드 개발자 김창하입니다 🙇‍♂️

0개의 댓글