오늘 배운 것

프론트 레포에서 팀원의 react query 관련 PR을 리뷰하는데 PR의 규모가 심상치 않았다. 장기적으로 꼭 필요한 리팩토링이고, 나도 이 리팩토링 코드를 받아서 앞으로의 작업을 이어가야 하는 상황이라 어제 했던 캘린더 모달 작업을 계속하려면 이 React Query에 대한 이해가 필요할 것 같다. 

 

해당 PR과 관련된 올려둔 브랜치를 pull 받아서 확인해보니 401 에러가 떴다. 일단 서버가 잘 살아있긴 한데, 메모리나 CPU 사용량에서 무리하고 있지는 않은지도 확인해 보고, 서버에서 띄우는 에러 메시지가 있는지도 확인해 보았다. 

일단 서버는 살아있긴 하다

 

그리고 ECS 태스크의 로그를 보니 띄워진 WAS에서 무언가 에러를 내고 있었다... 정확한 원인은 파악해봐야 알겠지만 프론트에서 내린 요청과 서버의 API 메소드가 일치하지 않아서 나는 오류이지 않을까 싶다. 다시 보니 몇 분 사이에 서버의 로그가 몇백 개가 늘어나 있었다. 프론트 react query에서도 요청을 계속 보내고, 서버에서도 계속 에러 코드 500을 리턴하면서 그 사이에 로그가 늘어난 것 같았다. 

 

일단 원격 서버에서 연결해서 콘솔에서 에러 로그를 보면서 디버깅하는것도 좋지만, 어차피 원격 서버에 띄워진 WAS의 상태는 main 브랜치에 올라온 코드와 완벽히 동일하기 때문에(깃허브 액션을 설정한 보람이 있다) 로그를 보면서 작업하기에는 로컬에 서버를 띄워두고, 팀원이 config.js 파일에 명시해둔 URL을 잠시 로컬 서버로 돌려두고 작업하는 것이 더 편할 것 같았다. 

 

암튼 이렇게 세팅해 두고 소셜로그인 버튼을 누르니, 서버에서는 401 에러가 났다. 로컬 백엔드 서버의 로그를 확인해보니 user_id는 undefined가 아니라 int여야 한다... 식의 에러라서 아마 파라미터 전달이 잘못된 것 같다. 이 부분을 수정해 주면 될 것 같아서 수정해 주었다. 알고보니 ({}) 형식으로 파라미터를 받던 코드를 그냥 ()로 수정해 주었더니 파라미터 바인딩이 잘 되더라. 

 

이제 오늘 작업하려던 SZ-118 이슈의 투두 모달에서 캘린더를 통해 투두 날짜를 변경할 때 API를 호출하는 로직을 짜면 된다. 사실 어제 작성해 뒀었는데, 해당 로직은 fetch()를 써서 작성된 것이나 이제부터는 API를 호출할 때 react query를 사용하기로 했기 때문에 로직을 다시 작성해야 한다. 문제는 내가 react query를 하나도 모른다는 것...! 급한 대로 다른 팀원이 작성한 코드를 슥 보고 어떤 식으로 사용하는지만 일단 익혀보자. 

 

그리고 하다보니 또 다른 문제가 생겼다. 무엇이냐면 내 아이디로 작성된 투두가 하나도 없다는 거였다. 그럼 투두를 작성하면 되지 않나? 라고 생각할 수 있지만, 팀원들 서로 맡은 부분이 다르기 때문에 현재 다른 팀원은 투두 카테고리 관련된 부분을 작업 중이고, 나는 투두 모달 부분을 작업 중이었다. 그런데 투두 모달을 보려면 일단 만들어진 투두가 필요하다. 그리고 투두 만드는 부분에 대해서는 다행히 react query로 기초 작업이 되어있었지만 실제로 텍스트 인풋에 내용을 입력하고 엔터를 누르는데 투두가 안 만들어진다. 

 

즉 투두 모달창에서 react query로 API 호출 로직을 짜려면 그 전에 react query로 투두 만드는 API가 잘 호출되어야 하고, 이 작업이 아직 되어있지 않아서 dependency 이슈가 생겼다. 그러므로 이걸 먼저 완료하고 투두 모달 작업을 마저 하는 게 맞겠다고 생각되니 까먹지 않도록 지라 이슈를 편집해두자. 

 

오늘 해야 할 일들이다. 

 

프론트에서 react query, axios를 이용해서 투두 생성하는 API에 요청을 보내고 있는데, 서버에서는 파라미터가 없다고 뜬 오류가 있었다. 알고보니 API request에 쓰일 헤더를 정의하는 함수에서 {} 괄호를 없애 주었더니 파라미터 바인딩이 잘 되었다. 이제는 투두 날짜수정 API를 react query를 통해서 호출하면 된다! (이 과정도 1시간이나 걸렸다...)

 

그런데 카테고리를 post하는 API를 호출했을 때는 {} 괄호를 없애면 되었는데, 문제는 유저 데이터를 retrieve하는 API는 괄호를 없애니까 에러가 난다. 즉 두 개의 API 호출 로직에서 무언가가 다르다는 말이었다. 하지만 생각해보니 일단 앞의 시행착오를 통해 무사히 내 유저의 category는 잘 생성하였고, 그러면 이 문제는 일단 두고 내가 맡은 투두 모달 이슈를 먼저 하는 게 맞겠다는 생각이 들었다. 

 

투두 모달 이슈를 처리하기 위해서는 또 나름의 문제가 있었다. 바로 투두를 생성할 때, selectedCategory라는 상태 변수에서 유저의 카테고리 중 가장 첫 번째(맨 처음에 뜨는 화면에서 선택되어 있는 카테고리)의 값을 갖고 있어야 했다. 그러기 위해서는 이 selectedCategory의 값을 받아오는 CategoryContext 내부에서 맨 처음에 null로 초기화되었던 이 selectedCategory의 값을, category API를 호출해서 그중 맨 첫 번째 category의 ID 값으로 바꿔줘야 했다. 

 

원래 계획은 기존에 hooks 폴더에 별도로 정의된 useCategoriesQuery() 라는 react query를 통해 category 데이터를 불러오는 함수가 있어서, 이 함수를 useEffect() 안에 선언해서 사용하려고 했다. 그런데 useCategoriesQuery는 react hook이기 때문에 컴포넌트나 커스텀 훅 함수 안에서 말고는 사용할 수 없다는 메시지가 떴다. 그래서 다른 팀원이 이를 사용하고 있는 코드를 참고해서 작성하였다. 

const { isLoading, error, data, isSuccess } = useCategoriesQuery(
	accessToken,
	userId,
);

useEffect(() => {
	if (isSuccess) {
		setSelectedCategory(data[0].id);
	}
}, [data, isSuccess]);

 

이런 식으로 해당 훅 함수를 호출하면 isSuccess라는 변수를 받을 수 있다. 이 변수는 해당 훅이 성공적으로 실행되었을 때 true를 반환하며, 이를 통해 useEffect() 안에서 해당 훅이 성공적으로 실행되었을 때 selectedCategory 변수에 값을 할당할 수 있다. 왜 이런 식으로 리액트 훅을 동작하게 만들었는지는 잘 모르겠다..! 나름의 이유가 있을 텐데 말이다. 

 

그리고 투두를 생성하는 데도 문제가 있었다. 아까와 같이, react query를 사용해서 만든 커스텀 훅이 파라미터를 제대로 전달하지 못하는 오류였다. GPT에게 물어봤더니 이를 위해서 async를 사용하는 비동기 커스텀 훅을 만들고, 그 훅 함수를 useEffect() 내부에서 사용하는 방법을 제시해 주었는데... 일단 이해하기 너무 복잡했다. 그래서 임시로 postman으로 투두를 생성하는 API를 호출하고, 그 임시 데이터를 통해 모달작업을 해 보기로 했다. 

 

그랬는데 또 다른 문제가 생겼다... 위 방법을 통해 투두는 잘 생성되었지만, 그 투두 데이터가 앱에 나타나지 않는 거였다. 왜냐하면 상태관리 설정이 제대로 안 되어있기 때문이다. 그러니까 이 상태관리 설정들이 다 완료된 다음에야 생성된 투두 데이터가 제대로 나타날 수 있고, 그 투두 데이터를 클릭한 다음에야 모달이 활성화되어서 원하는 작업을 이어할 수 있는데, 이 dependency를 가진 이슈들이 아직 완료되지 않은 상황이다. 

 

아 그리고 위에서 CPU랑 메모리 사용량 그래프를 보다가 문득 '저 정도면 CPU랑 메모리 사용량이 안전한 걸까?' 라는 생각이 들어서 멘토님께 여쭤보았다. 멘토님께서는 그거는 SLI랑 SLO를 정의하기 나름이라고 하셨다. 서비스가 어느 정도의 성능과 사용량을 추구할 것인지에 대한 지표인 것 같았다. 


그리고 인프런 강의를 들으면서 ELB(elastic load balancer)에 대해서도 배웠는데, ELB의 세부 종류 중 ALB(application LB)와 NLB(network LB)의 차이가 무엇인지가 궁금해졌다. 둘 다 여러 개의 서버에 가해지는 부하(로드)를 밸런싱해준다는 것은 잘 알겠는데, ALB는 어플리케이션 계층에서, NLB는 송신(transport) 계층에서 동작한다는 말이 정확히 무슨 의미인지 와닿지 않았다. 

 

아니면 요청이 low layer에서 high layer로 올 때, 말 그대로 ALB는 7계층에서 동작하고 NLB는 4계층에서 동작한다는 것인가? 의미로는 알 것 같은데 그러면 7계층에서 로드밸런싱을 하나 4계층에서 로드밸런싱을 하나 구체적으로 무슨 차이인지 잘 와닿지 않는다. 

 

그리고 'ELB를 사용할 때 EC2 인스턴스는 private address 밖에 알 수가 없다. 그러므로 x-forwarded-for' 헤더를 사용해서 public address 값을 알아낼 수 있다' 라는 내용이 잘 이해가 되지 않는다. 그렇다면 EC2 인스턴스 설정에 나오는 public endpoint는 다른 의미인 것일까? 그 차이를 잘 모르겠다. 

 

그리고 EC2와 관련이 있는 Route53 서비스도 나왔다. 이 친구는 AWS에서 제공하는 DNS 서비스라고 하며, EC2 인스턴스나 S3 버킷, 로드밸런서에 public DNS를 제공해주는 역할을 해 준다고 한다. 도메인 주소를 구매하여 연결시켜 준다고 하니, 우리 상황에 딱 맞다. 

 

+ Recent posts