혼자 프로젝트를 진행하면서 프론트엔드 개발자로서 서버 개발 없이 어떻게 서비스를 구현할 수 있을지 고민하다 Supabase를 알게 되었다. 이를 활용해 데이터베이스를 설계하고 프로젝트를 구현하면서, 서버의 응답 형식과 프론트엔드 코드가 거의 동일하게 작성되는 경우가 많았다. 이는 API를 호출하는 주체가 '나'뿐이었기에 서버가 클라이언트에 맞춰 데이터를 반환해도 문제가 없었기 때문이다.
하지만 프로젝트가 커지면서 데이터 구조 변경이 필요해지는 상황이 발생했다. 이때 서버와 프론트엔드가 강하게 결합된 상태에서는 데이터 구조가 조금만 바뀌어도 프론트엔드 코드까지 대규모로 수정해야 하는 문제가 발생했다.
1. 서버에서 내려주는 데이터 형태와 UI를 렌더링하기 위한 데이터 형태는 항상 일치하지 않는다.
2. 데이터는 지속적으로 수정되고 확장된다.
서버와 프론트엔드는 동일한 목표로 서비스를 만들어가지만, 수행하는 역할이 다르다. 서버는 데이터를 효율적으로 제공하는 역할을 하고, 프론트엔드는 사용자에게 데이터를 시각적으로 제공하는 역할을 한다. 따라서 두 시스템이 서로의 내부 사정에 지나치게 의존하지 않아야 한다. 결합도가 높아지면 데이터 구조가 조금만 변경되어도 프론트엔드와 서버 모두들 수정해야 하는 비효율적인 상황이 발생한다. 이러한 결합도를 낮추기 위해 고민한 끝에 서버의 응답을 UI 에 맞게 변환해주는 "데이터 변환 함수" 를 도입하게 되었다.
서버에서 받아온 userData는 UI에서 바로 사용하기 어려운 형태이다.
const userData = {
id: 1,
user_name: "kim",
email: "example@email.com",
created_at: "2024-02-22T10:00:00Z",
updated_at: "2024-02-23T10:00:00Z"
};
예를들어 서버에서 주로 사용하는 스네이크_케이스를 카멜케이스로 바꾸거나 혹은 아예 다른 변수명으로 사용할 수도 있다. 또한 UTC 표기법으로 되어 있는 날짜형식을 YYYY-MM-DD 와 같은 형식으로 변환해줘야 한다.
서버 데이터를 UI에서 사용하기 적절한 형식으로 변환하는 함수를 만들었다.
const convertApiToUser = (init) => ({
id: init.id,
userName: init.user_name, // 변수명 변환
email: init.email,
createdAt: dayjs(init.created_at).format('YYYY-MM-DD'), // 날짜 변환
})
const user = convertApiToUser(userData) // 서버에서 받아온 데이터를 넣어준다
console.log(user)
// { id: 1, userName: "kim", email: "example@email.com", createdAt: "2024-01-23" }
반대로, UI에서 입력받은 데이터를 서버에 전송할 때도 동일한 방식으로 변환한다.
const convertUserToApi = (init) => ({
id : init.id,
user_name : init.userName,
email : init.email,
})
이제 컴포넌트에서는 데이터 변환 로직을 신경 쓰지 않고, 데이터 가공 함수를 통해 변환된 데이터를 바로 사용할 수 있다. 이처럼 데이터 변환 로직이 UI 코드에서 완전히 분리되면서, View는 UI 렌더링에만 집중할 수 있게 되었다.
return (
<>
<div>이름: {userName}</div>
<div>이메일: {email}</div>
<div>가입 날짜: {createdAt}</div>
</>
)
서버-클라이언트의 결합도 감소
데이터 구조 변경 시, UI 코드 전체를 수정할 필요 없이 가공 함수만 수정하면 해결 가능하다.
유지보수성 향상
데이터 변환 로직이 한 곳에(가공 함수) 집중되어 있어, 서버 응답이 바뀌더라도 최소한의 코드 수정으로 대응 가능하다.
UI 집중
기존 코드에서는 컴포넌트 내에서 서버에서 받아온 데이터를 가공하는 로직이 포함되어 있었는데 이제는 UI 에만 집중할 수 있어 더 직관적인 코드 작성이 가능해졌다.
독립적인 클라이언트 개발 가능
서버 응답이 확정되지 않았더라도, 미리 변환 레이어를 정의해 두면 프론트엔드 개발을 독립적으로 진행할 수 있다.