202212
이번주는 백엔드에서 데이터를 받아와서 카카오 데이터와 연결, 편의점 상세페이지, 리뷰 작성/수정 페이지 구현과 지도 리스트 필터링 기능 구현을 주로 하였는데 아무래도 UI + 기능 구현이다보니 많은 것들을 하게되어 정리하기 쉽지 않을 것 같다.
첫번째 수업에서는 solid 원칙에 대해서 공부했다.
1. SRP 단일 책임의 원칙 - 하나의 컴포넌트에 너무 많은 기능을 넣지 말 것 / 최대한 다른 모듈로 분리시키기
2. OCP 개방 폐쇄 원칙 - 적절한 props 사용 / 다른 추가 사항이 일어나더라도 기존 구성은 변경하지 않으며 확장에 대한 가능성을 열어줘야 한다, 컴포넌트의 확장성을 높일 수 있음
3. LSP 리스코프 치환 원칙 - 클래스 관련 // 리액트에선 많이 상관 없음
4. ISP 인터페이스 분리 원칙 - props 필요한 부분만 전달
5. DIP 의존관계 역전 원칙 - 리덕스 툴킷에서 액션을 디스패치 하는 것(액션에 따라 받는 부분을 바꿀 수 있음)
https://bottom-to-top.tistory.com/27
https://sumini.dev/til/009-react-solid/
→ 변경이 쉽도록, 하나가 변경되면 여러 곳이 변경되면 안된다.
*피드백
-develop 브랜치로 머지하면서 package-lock.json 오류 -> 흔히 나타나는 오류로 팀원 간에 npm 버전이 달라서 그럴 수 있기 때문에 확인하고 하나로 통일해서 진행하기
-일정보다 빠르게 진행 시 할 수 있는 추가 과제들(시맨틱 태그, 접근성 향상, TDD 등)
두번째 수업때는 pull request를 진행했던 브랜치들에 대해서 피드백을 받았다.
-eslint rule 추가 → exhaustive-deps-warning (중요함!)
-qs 라이브러리 이용 query String 값 배열로 보내기
-map 메소드 사용 시 idx보다는 고유한 값으로
-공통 컴포넌트 사용 시에도 최대한 반복 줄이기
-컨벤션 공부하기 -> 참고 https://github.com/naver/eslint-config-naver/blob/master/STYLE_GUIDE.md#naming-conventions
selected: string[]
setSelected: (selected: string[]) => void
const ITEMS = [
{ title: '제품', keywordArray: PRODUCT },
{ title: '분위기', keywordArray: MOOD },
{ title: '편의시설', keywordArray: FACILITIES },
]
<>
{ITEMS.map((el) => (
<Select
key={el.title}
title={el.title}
keywordArray={el.keywordArray}
selected={selectKeyword}
setSelected={setSelectKeyword}
selectType={'checkbox'}/>
))}
</>
저번주 주말 ~ 이번주 초반에는 package-lock.json 충돌 오류로 또 머지 문제가 생겨 복잡했었는데 npm 버전을 맞추고 통일해서 하니 한번에 쉽게 해결되어서 다행이었다.
이번주는 많은 기능을 구현해야 해서 처음에는 막막하기만 했는데 그래도 팀원들과 함께 해서 할 수 있었던 것 같다. 특히 필터링 부분은 어떻게 해야할 지 고민이 많았지만 이렇게 저렇게 해보고 막히는 부분은 팀원들에게 물어보고 같이 하면서 해낼 수 있었다. 배우고 느낀 게 매우 많은 주였어서 모두 머릿 속에 꼭꼭 기억하고 싶다.
주요 부분인 메인페이지와 리뷰페이지의 기능이 거의 완료되었다!
처음에 기획했던 것과 비슷하게 기능과 UI가 대체로 잘 나오고 있는 것 같아서 다행이었고, 팀원분의 노고로 로고까지 예쁘게 업그레이드 되었다!
기능을 어느정도 구현하고 백엔드와 붙여서 진행해보니 로그인 오류나 생각지 못했던 문제들이 생겼고 이 외에도 구현했던 부분에 약간의 오류들이 나타나서 이 부분을 수정하기도 했는데, 아마 마지막 주차에 develop 브랜치로 모두 머지하고 나면 쭉 훑으면서 수정할 부분을 정리해야 할 것 같다.
우리 팀의 필터링 부분은 다음과 같고,
필터링은 브랜드, 키워드 모두 중복선택이 가능함
*브랜드
'GS25', 'CU', '세븐일레븐', '이마트24', '미니스톱', '기타'가 있고, 기타 선택 시 나머지 편의점이 아닌 곳을 가져와야해서 약간의 어려움이 있었음
-> 선택된 브랜드 없음 or 기타 + 브랜드 선택 or 브랜드 선택(기타 없음)
*키워드
키워드는 종류는 많았지만 선택된 키워드중 하나라도 리뷰에 포함되어 있으면 편의점 리스트에 띄우는 것으로 결정
-> 선택된 키워드 없음 or 키워드 선택
-FilterBox.ts
1. 편의점 브랜드 sort 함수
const sortBrand = () => {
let newData: ConvType[]
if (selectBrand.length === 0) {
// 선택된 브랜드가 없을 시 원래 편의점 리스트를 가져옴
newData = convList
// 선택된 브랜드에 기타가 포함되어 있을 시
// 기타 / 브랜드 이름 분리해서 결과 가져오기
} else if (selectBrand.includes('기타')) {
// 편의점 이름에 브랜드 이름이 있는 경우
newData = stores.filter((data) =>
selectBrand.includes(data.place_name.split(' ')[0])
)
// 편의점 이름에 브랜드 이름이 없는 경우(기타)
const etcData = stores.filter(
(data) =>
!['GS25', 'CU', '세븐일레븐', '이마트24', '미니스톱'].includes(
data.place_name.split(' ')[0]
)
)
newData = [...newData, ...etcData]
} else {
// 선택된 브랜드가 있고 기타는 없을 시
newData = stores.filter((data) =>
selectBrand.includes(data.place_name.split(' ')[0])
)
}
return newData
}
2. 키워드 sort 함수
선택된 키워드들은 배열이었고, filter 메소드 안에서 각 데이터가 문자열 배열을 하나라도 포함하고 있는 지 확인했어야 하기때문에 조금 헷갈렸는데, some 메소드를 활용하여 할 수 있었다.
const sortKeyword = (newData: ConvType[]) => {
let sortResult
if (selectKeyword.length === 0) {
// 선택된 키워드가 없을 시 원래 편의점 리스트를 가져옴
sortResult = newData
} else {
// 선택된 키워드가 하나라도 리뷰에 포함되어 있으면 리스트에 포함
sortResult = newData.filter((data) =>
data.keywordList.some((keyword) => selectKeyword.includes(keyword))
)
}
return sortResult
}
3. 버튼 누르면 sort 진행
const sortStore = () => {
...생략...
// 브랜드 sort 함수 진행 -> 이 데이터를 가지고 키워드 sort 함수 진행
const newData = sortBrand()
const sortResult = sortKeyword(newData)
// 완료된 결과를 store에 넣어주고 지도에 표시
dispatch(setSortStores(sortResult))
sortCallBack(sortResult)
...생략...
현재는 필터링 부분 리팩토링까지 완료하여 코드가 조금 달라졌다.