오늘은 특별한 이야기를 하려고 한다. 바로 일주일 동안 몰두했던 리액트 숙련 과제, '나만의 포켓몬 도감' 프로젝트에 대한 이야기이다.
포켓몬 도감 마스터를 향한 7일간의 여정이다. 이번 과제는 단순한 코딩 연습이 아닌, 기능 구현에 심혈을 기울이는 것은 물론이고, CSS 디자인에도 내 창의력을 쏟아부었다. 그 결과, 나름 그럴싸한 포켓몬 도감이 탄생했다!
7일간의 여정이 순탄했던 것만은 아니다. 수많은 오류와 난관에 부딪혔고 좌절도 느꼈다. 하지만 그 모든 과정에 내게는 값진 경험이 되었다. 어떤 문제들을 만났고, 그것을 어떻게 해결해 나갔는지 이야기를 이 블로그에 담아보려고 한다🌟
포켓몬의 세계로의 여행 지금 시작합니다!🚀🌈
# 사진
# 시연 영상
🚀 포켓몬 도감 개발 여정
1. 필수 구현 사항 완성
- Git 브랜치 전략 활용 ( props-drilling => context-API )
- react-router-dom으로 페이지 라우팅 구현
- Dashboard, PokemonList, PokemonCard 컴포넌트 구성
- 포켓몬 선택/삭제 기능 및 최개 6마리 제한, 동일 포켓몬 배제 구현
- queryString을 활용한 디테일 페이지 구현
2. 문제점 해결🌟🌟🌟
- Props drilling 에서 Context API로 발전 (props drilling로 불필요한 데이터 전달 해결!)
- Redux 도입으로 상태 관리 최적화 (뒤로가기 시 포켓몬 리셋 문제 해결!)
- 코드를 작성하며 생긴 각종 오류 해결
3. 사용자 경험 향상
- styled-components로 멋진 UI 디자인
- SweetAlert 라이브러리로 깜찍한 알람 기능 구현
🚀 오류 해결 방법
1. props drilling으로 인한 불필요한 데이터 전달의 문제는 Context API로 해결!
이 과정은 이 블로그에서 'Context API로 Props Drilling 해결하기'에 담겨 있으므로 생략 ···
2. Redux 도입으로 상태 관리 최적화
내 포켓몬 도감 프로젝트가 Redux를 만나 한 단계 더 진화했다. 이전 버전과 비교해 어떤 점이 개선되었는지 살펴보겠다.
중앙 집중식 상태 관리 🎯
- 이전: 여러 컴포넌트에 널부러진 상태들
- 현재: store를 통한 통합 데이터 관리로 데이터의 흐름이 명확
import { createStore } from "redux";
import pokemonReducer from "./reducer";
// 스토어 생성
const store = createStore(pokemonReducer);
export default store;
예측 가능한 상태 변화 🔮
- 이전: 복잡한 상태 업데이트 로직
- 현재: action과 reducer를 통한 명확한 상태 변화 추적 가능
비즈니스 로직의 분리 🧩
- 이전: 컴포넌트에 섞여 있던 로직들
- 현재: action과 reducer로 비즈니스 로직을 분리하여 코드 가돋성과 유지보수성 증가
// action type 정의
export const ADD_POKEMON = "ADD_POKEMON";
export const DELETE_POKEMON = "DELETE_POKEMON";
export const GET_POKEMON_LIST = "GET_POKEMON_LIST";
// action 생성자 함수
export const addPokemon = (pokemon) => {
return {
type: ADD_POKEMON,
payload: pokemon,
};
};
export const deletePokemon = (id) => {
return {
type: DELETE_POKEMON,
payload: id,
};
};
export const getPokemonList = () => {
return {
type: GET_POKEMON_LIST,
};
};
import { ADD_POKEMON, DELETE_POKEMON, GET_POKEMON_LIST } from "./action";
//초기값 세팅
const initialState = {
pokemonList: [],
travelPokemon: [],
};
// 리듀서 함수
const pokemonReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_POKEMON:
// 중복 체크 로직 추가
const isDuplicate = state.travelPokemon.some(
(pokemon) => pokemon.id === action.payload.id
);
// 중복되지 않은 경우에만 추가
if (!isDuplicate) {
return {
...state,
travelPokemon: [...state.travelPokemon, action.payload],
};
} else {
// 중복인 경우 기존 상태 반환
return state;
}
case DELETE_POKEMON:
return {
...state,
travelPokemon: state.travelPokemon.filter(
(pokemon) => pokemon.id !== action.payload
),
};
case GET_POKEMON_LIST:
return {
...state,
};
default:
return state;
}
};
export default pokemonReducer;
시간 여행 디버깅의 즐거움 ⏰
- 이전: 오류 추적이 어려움
- 현재: 각 액션별 상태 변화를 쉽게 확인할 수 있어 디버깅이 한결 수월해짐
성능 최적화 🚄
- 이전: 불필요한 리렌더링이 발생
- 현재: 필요한 컴포넌트만 업데이트 되어 앱의 반응성 향상
지속적인 상태 유지 🔄
- 이전: 페이지 이동 시 상태 초기화 문제
- 현재: 뒤로가기를 눌러도 선택한 포켓몬이 리셋되지 않아 사용자 경험 개선
특히, 포켓몬 추가 시 중복 체크 로직을 reducer에서 처리하는 방식이 좋았던 것 같다. 이로 인해 컴포넌트는 깔끔해지고, 로직은 한 곳에서 일관되게 관리할 수 있게 되었다. 리덕스의 도입으로 포켓몬 도감은 더욱 강력하고 유연해졌다. 마치 진화한 포켓몬같다🌟
3. 각종 오류 해결 (리덕스 리팩토링 중 발생한 중복 데이터 문제 해결하기)
원래 이 프로젝트는 useState 만을 사용하여 상태를 관리하고 있다가 Redux에 대해 공부해보고 싶어 전체 프로젝트를 Redux를 사용하도록 리팩토링 하기로 결정했다.
리팩토링을 마치고 테스트 하던 도중, 흥미로운 문제를 발견했다. 동일한 포켓몬이 리스트에 중복으로 추가되는 현상이 발생한 것이다. 분명 중복 방지를 위한 유효성 검사 로직을 추가했음에도 불구하고 말이다.
원인 파악
: 이 문제의 원인을 찾기 위해 코드를 꼼꼼히 살펴보았다. 그 결과 다음과 같은 문제점을 발견했다.
- Redux action과 reducer을 새로 만들어 사용하기 시작했지만, 기존의 추가 및 삭제 함수를 완전히 제거하지 않은 문제점
- 새로 만든 dispatch 함수만 연결했고, 이 함수에는 유효성 검사 로직이 포함되어 있지 않은 문제점
- 원래의 추가 함수에는 some() 메서드를 사용하여 중복 Id 값을 검사하는 로직이 있었지만, 새로운 reducer 에는 이러한 유효성 검사가 누락되어 있었던 문제점
해결 방법
: 이 문제를 해결하기 위해 다음과 같은 방법을 거쳤다.
- 기존의 추가 및 삭제 함수를 완전히 제거함
- reducer에 유효성 검사 로직을 추가함 (구체적으로, 새 포켓몬을 추가하기 전에 해당 Id가 이미 존재하는지 확인하는 로직을 넣음)
- 중복 발견 시 상태를 변경하지 않고 그대로 반환하도록 함
- 컴포넌트에서는 dispatch 결과를 확인하여 중복일 경우 사용자에게 알림을 주도록 수정함
교훈
- 리팩토링 시 기존 코드의 완전한 제거 확인의 중요성
- 상태 관리 라이브러리 전환 시 기존 로직의 누락 주의
- 변경 사항에 대한 철저한 테스트의 필요성
.
.
.
🚀 느낀점
이 일주일간의 포켓몬 도감 개발 여정은 단순한 과제 이상의 의미를 가졌다. 매일 조금씩 진전을 이루다 보니, 이렇게 큰 성과를 이루어낼 수 있었고 내 문제 해결 능력이 크게 향상되었다. 오류와 난관에 부딪힐때마다 두려워하지 않고 해결책을 찾아가는 과정에 큰 도움이 되었다.
이 경험을 통해 기능 구현뿐만 아니라 UI에도 신경 쓰면서, 사용자 중심의 개발이 얼마나 중요한지 깨달았다. 비록 개인 프로젝트였지만, 스스로 리뷰하고 피드백을 주며 작업물을 발전시켜 나가는 과정에서 보람을 느꼈다.
이 프로젝트는 내게 개발로써 성장과 자신감을 안겨준 소중한 경험이다!🌟🌟🌟
'개인과제' 카테고리의 다른 글
MBTI test(트러블 슈팅1🌟) (0) | 2024.09.10 |
---|---|
로그인 기능 구현하기 (0) | 2024.08.27 |
Redux 사용해서 TodoList 만들기! (0) | 2024.08.22 |
Context API로 Props Drilling 해결하기 (0) | 2024.08.21 |
올림픽 메달 트레커 만들기! (0) | 2024.08.14 |