'Style We' 프로젝트

Junghyun Park·2021년 2월 15일
0

프로젝트 회고

목록 보기
1/3
post-thumbnail
post-custom-banner

프로젝트 개요

1. (클로닝) 프로젝트 사이트 : 'StyleShare'

"Style Share" 사이트 소개
: 10대 ~ 20대 여자가 대다수 유저인 SNS 연동 커머스 사이트라는 점이 특징
: 자신의 패션 스타일을 SNS로 공유하고, 해당 페이지에 포함되어있는 상품 배너를 클릭하면 상품 페이지로 이동하며, 여기서 구매 시 reward 부여

2. 팀 구성: 프론트엔드 3명 / 백엔드 3명

3. 프로젝트 기간 : 2/15 ~ 2/26 (약 12일)

4. 프로젝트 진행 방식

: Agile(Scrum) 방식, Sprint 주기는 1주일
: 활용 Tool은 notion, trello, slack
: 매일 오전 11시 daily stand up meeting & sprint 주기 별로 정리 미팅(회고)

5. 화면별 업무분담

: 프론트에서 구현해보기로 한 페이지는 아래와 같고,
내가 담당하기로 한 업무 및 페이지는 (1), (2), (4) + 최종 페이지 간 연결 이었음.
(1) SNS 커뮤니티 메인(진입 페이지) : 백엔드 API 통신, 비정렬 정렬, 무한 스크롤 등 포함
(2) 피드 상세페이지 : 피드 내 상품 배너 클릭 시 (6) 상품 상세페이지로 이동
(3) Nav Bar: 이중 map
*(4) Footer
(5) 회원가입/로그인 페이지
(6) 상품 상세 페이지 : 페이지 내 후기 클릭 시 (2) 피드 상세 페이지로 이동
(7) 장바구니

6. 기술 스택

  • Front-End : React.js, Sass(Scss), React Slick, React-router-dom
  • Back-End : Python, Django web framework, Bcrypt, My SQL
  • 협업에 사용 된 툴 : Git Hub, Slack, Trello, Google Calender
  • Common : RESTful API

Problems & Solutions

: 프로젝트 진행 중 마주 한 문제들과 해결책들을 정리

Problem 1 - 컨텐츠 피드 박스 불규칙 정렬 문제

실제 사이트에서는 각 피드의 높이가 다르고, 일정 간격을 유지하면서 불규칙적으로 정렬이 되어있다.

그런데, flex row 방향으로 정렬하면, 이렇게 각 피드 아래에 빈 공간 영역들이 생기게 된다.

아..빈 공간을 메워야 하는데...

Solution 1

짜잔!

.CommunityMain {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  width: 1198px;
  margin: 20px auto;
  .Feeds {
    width: inherit;
    height: 2700px;
    display: flex;
    flex-direction: column;
    flex-wrap: wrap;
  }
}

flex container의 height를 적당히 한정하고, column 방향으로 정리하니 되긴 되는 듯 한데..
문제는 가져오는 flex 박스 수와 화면 height의 수에 따라서 보여주는 게 지멋대로 바뀜
(아래는 height가 1000px 일때)

(아래는 height가 3000px 일때)

일단은 적정 container box의 height와 해당 box 내에 포함되는 컨텐츠의 수를 무한 스크롤 구현시에도 조절하면 시각적으로는 문제 없을 듯 하니 이대로 가고 추후 다시 생각해보자~

Problem 2 - 모달창 구현 문제

: 컨텐츠 작성 모달창 문제 있었음
(배경을 어둡게 하면 모달창까지 어두워지고, 모달창이 떴을 때 스크롤 바를 없앨수 가 없었음)

Solution 2

: overlay역할을 하는 div를 만들어 화면을 가득차게 하고,
isModalOpen boolean 값이 true일 때만 opacity와 background-color를 적용하여 해결

Problem & Solution 3 - 피드 텍스트를 일정 길이만 잘라서 보여주기

: 메인화면에서는 피드의 전체 텍스트를 보여주지 않고 일정 길이까지만 보여주기 위해서 처음 적용시킨 건
.substring() method 였음
: 그러나, 코드 리뷰를 통해 알게 된 css line clamp를 적용해보니, "바로 이거구나!"라고 생각됨. 잘린 부분 이후에는 '...'까지 자동으로 추가됨

Problem & Solution 4 - file type의 input 태그는 직접 디자인이 불가한데.. HOW?

: 구글링을 해본 결과, input 태그는 css로 보이지 않게 숨기고, label을 원하는 대로 디자인하면 됨
: 라벨을 클릭해도 동일하게 파일 첨부 기능 작동! 아.. 그렇구나~
: 파일 첨부시 미리보기 참고 링크
https://basketdeveloper.tistory.com/55 (파일 업로드 방법)
https://velog.io/@chdb57/%E3%85%87-3uk4u6sugu

구현 로직
1. input tag 내에 onChange 함수 추가 (파일첨부 시 함수 실행)
2. let reader = new FileReader();로 파일을 읽고 컴퓨터에 저장할 수 있는 객체를 생성
3. 내장 함수인 FileReader.onloadend(성공적으로 첨부된 파일을 로드 완료 했을 때 콜백함수를 실행)을 실행하고, 그 결과값(reader.result = 첨부된 파일을 base64 형식으로 encoding 된 데이터)을 변수에 저장
4. 위 변수를 string으로 변환하여 state 데이터로 저장 => 나중에 미리보기 src에 입력 가능
5. 첨부된 파일에 대한 정보를 담은 객체는 event.target.files에 있음 (가장 최근에 첨부된 파일는 [0]번째)

기타 - git을 활용한 코딩 작성 관련 어려움

: git을 활용하여 코드의 버전 관리 할수 있는 점은 매우 유용하고 편리하다고 생각했음
: 그러나, 실제 브랜치를 기능별로 구분하고 코드를 작성하는 과정에서, 명확히 코드를 분리해서 작성하는게 쉽지 않았음
:(예를 들면, '메인 페이지 레이아웃' branch를 구분해놓아도, 모달창으로 뜨는 상세페이지를 하면서 메인 페이지 레이아웃 관련 코드를 수정해야 하는 부분
<느낀점>
: branch 구분을 하는 명확한 기준이 필요할 듯.. 그렇지 않으면, 끊없는 confilct를 해결해야 할 수도..

Problem 5 - 이미지 파일 업로드 기능 구현 (formData 활용)

: 이 부분은 개인적으로 서치하고 학습 중, 구현까지 걸리는 시간, 백엔드 쪽에서도 넘어오는 이미지 파일에 대한 처리에 대해 추가 스터디가 필요한 관계로 2차 프로젝트에서 해결하기로 하고, 첨부 시 미리보기 화면을 띄우는 것 까지만 구현했음

Problem 6 - backend로부터의 전달 데이터 형식


위와 같이 백엔드에서 보내는 json 파일 형식 내의 값을 키 네임 없이 바로 []에 담은후, 프론트에서 전달받아 map을 돌리면,

위와 같이, 0번째, 1번째 값을 가져오지 않고, 스트링에서 첫번쨰인 'h', 두번쨰인 't'를 가져옴

Solution 6

: 임의의 키 네임(실제로는 'url')을 각각 할당하여 '키:값' 형식으로 보내면 해결!

Problem 7 - 데이터 내의 일정 depth까지만 접근 가능

백엔드에서 데이터를 수신하여 하나씩 접근 및 가져오는데 첫번째 레벨까지는 문제없이 접근하여 가져오지만, 그 안의 레벨 데이터는 undefined 오류가 나옴
(예를들어, console 창에 찍어보면, feed_basic_data나, feed_comment_data까지는 문제없이 가져오지만, "created_at"이나, comment_list처럼 하위 레벨의 값에 접근하려 하면 "undefined"오류

=== 실제 수신하는 백엔드로 부터의 데이터 형식 =====
"current_user_id": 1,
   "feed_basic_data": {
       "created_at": "2021-02-24T06:20:53.774Z",
       "description": "elementum. Etiam semper venenatis ante euismod convallis. Aenean malesuada blandit acc",
       "feed_id": 6,
       "feed_user": "styleuser08",
       "feed_user_id": 8,
       "feed_writer_about": null,
       "like_number": 36,
       "tag_item_number": null
   },
   "feed_comment_data": {
       "comment_list": [
           {
               "content": "g elit. Cras at rhoncus leo, ut tincidunt el",
               "created_at": "2021-02-24T06:22:18.022Z",
               "user": "styleuser09",
               "user_id": 9
           },
           {
               "content": "ctetur adipiscing elit. Cras at rhoncus leo, ut tincidunt el",
               "created_at": "2021-02-24T06:22:20.995Z",
               "user": "styleuser07",
               "user_id": 7
           }
       ],
       "feed_comment_count": 2
   },

Solution 7

  • 문제의 원인은 비동기적으로 통신 및 컴포넌트가 리랜더 되면서, 데이터의 depth에 따라 통신하는 시차가 발생
  • 따라서, 데이터 수신이 완료된 이후에 접근하도록 하기 위해 동기적으로 처리하는 수단으로 해결
    (실제로는 optional chaining('?")으로 해결했지만, 다른 방법도 가능)

Problem 8 - 무한 스크롤 구현

커뮤니티 메인 페이지에서의 비정형 정렬을 위해 container의 Height와 그 안의 피드수를 적정 수준으로 조절하여 원래 사이트와 비슷하게 보여주고 있어서,
스크롤이 하단에 닿으면, container의 크기를 늘려줌과 동시에 피드를 동시에 동일하게 추가해야하는 문제

Solution 8

  • 테스트 결과 container의 height가 2400px당 약 20개 정도의 피드 수가 채워지면, 실제 사이트와 유사한 정렬이 유지됨
  • 따라서, 기본적으로 scrollTop + clientHeight === scrollHeight 여부를 판단하여, 만족하는 경우, 추가로 가져올 feed data를 업데이트하는 동시에 container의 추가 height를 확보하여 계속적으로 동일한 정렬을 유지할 수 있도록 구현
  • https://velog.io/@hyounglee/TIL-56

Problem 9 - 피드 상세페이지 슬라이드 기능

: 슬라이드를 라이브러리를 활용해 상대적으로 쉽게 구현할 수도 있지만, 직접 수작업으로 한땀한땀 구현해보고 싶은 욕심에서 직접 시도함
: 하단의 썸네일을 클릭하면 바로 그 사진이 메인 큰 사이즈 사진으로 보여지고, 좌우 화살표를 클릭하면 하나씩 사진이 좌우로 넘어가는 애니메이션을 구현해야 했음.

Solution 9

: 메인 이미지가 차지하는 공간에 마진없이 가로방향으로 연속적으로 배치되어 있는 이미지 row를 css transform과 transition을 활용하여 자연스럽게 넘어가는 슬라이드를 구현
: 클릭 이벤트와 컨트롤 대상 데이터(이미지)를 유기적으로 연결하고, state를 활용하여, 꽤 성공적으로 깔끔하게 구현완료

Problem 10 - 자식에서 부모로 데이터(id) 전송 및 실행

: 가장 핵심적인 기능인 다른 팀원이 작성한 상품 상세페이지에서 후기를 클릭하면, 해당 상품 배너가 포함되어 있는 피드를 찾아 띄워줘야 하는 기능 구현에서의 문제였음
: 기존에 배웠던 내용은 parent component에서 child component로 데이터를 전달하고자 할때는 props로 전달하는 내용을 배웠고, 당시에 top->down방식으로만 데이터(id)가 전달 가능하다고 배웠기 때문에, 역으로 child에서 2 단계를 올라간 parent component에게 데이터(id)를 통해 피드 상세페이지를 띄워줘야 하는 상황이었음

Solution 10

: 마침내, 구글링 결과, child component에서도 자신의 함수 내에 부모에서 내려받은 함수를 포함시켜 실행시키는 방식으로 클릭되는 element로부터 id를 가져와 함수의 인자로서 부모로 데이터를 올려보낼 수 있음을 알아냈고, 적용결과 잘 작동됨!

최종 완성 및 발표

  • nav bar

  • 커뮤니티 메인 페이지 비정형 정렬과 무한스크롤

  • 피드 작성 화면

  • 피드 상세페이지 <=> 제품 상세 페이지 전환

느낀점

사전 기획(계획)에서 충분한 시간을 들여서라도, 화면기획이나 백엔드와의 데이터 모델링 기초 작업을 확실해 해두는 것이 추후 변경사항으로 인한 시행착오를 줄일 수 있겠구나..

내가 맡은 페이지 뿐만 아니라, 데이터를 보내주는 백엔드, 그리고 다른 페이지작업을 하는 프론트엔드 팀원과도 충분한 사전 협의와 초기 세팅(공통 scss 파일, package, 공통 js 파일 등)을 완벽하게 하고 진행해야겠다.

git을 좀 더 적극적이고 정확하게 활용해서, 코드 관리과 협업에 도움이 되도록 해야겠다.

은근히 적성에 맞는다는 느낌을 받았다. 개인적으로 지금껏 배웠던 어떤 지식보다 실용적이라고 느꼈으며, 명확하고 빠른 주기로 얻어지는 피드백으로 인해 힘들지만 재미있었던 경험이었다. (문제와 해결의 연속인 점에서 마치 '게임' 혹은 '수학문제'를 풀어나가는 어려움과 성취를 느낄수 있엇음)

profile
21c Carpenter
post-custom-banner

0개의 댓글