Coder Social home page Coder Social logo

fe-max--newsstand's People

Contributors

crongro avatar github-actions[bot] avatar namse avatar youzysu avatar

fe-max--newsstand's Issues

가장 첫 페이지의 왼쪽 화살표와 끝 페이지 오른쪽 화살표는 표시되지 않는다.

고민

  1. Grid, List 보기 버튼 공유하기: MainMediaArea 버튼을 왼/오 & viewerOption에 따라 click event 로직을 수행하도록 하기
  2. Grid, List에 따라 각각 버튼 만들기

선택한 방법: 2번

  • 아무리 props로 넘겨서 viewerOption에 따라서 Action을 다르게 처리할 수 있다고 해도 로직이 복잡해지고, 후자가 더 이해하기 편하다고 판단

Task: 전체 언론사 리스트 보기

Data

UI & Feature

  • 리스트 보기 상태일 때 이전 Viewer를 지운다.
  • 분야별 카테고리에서 언론사의 기사를 확인할 수 있다.
    • 언론사 카테고리는 종합/경제, 방송/통신, IT, 영자지, 스포츠/연예, 메거진/전문지, 지역으로 구성된다.
    • navbar tab은 기사 영역 상단에 가로로 긴탭 형태로 배치한다.
  • #29
    image
  • 언론사의 순서는 화면이 새로고침 될 때마다 랜덤으로 정해진다.
  • 현재 순서의 언론사 내용이 표시된다.
  • 좌우 화살표를 클릭하면 이전과 다음 언론사로 이동한다.
  • 카테고리의 마지막 언론사가 보여진 후에는 다음 카테고리로 넘어가고, 카테고리의 첫 언론사인 경우에는 이전 카테고리로 넘어간다.
  • 마지막 카테고리의 마지막 언론사가 보여진 후에는 처음 카테고리의 첫 언론사로 돌아온다.
  • 한 언론사 당 20초 동안 화면에 보여지고, 20초가 지나면 다음 언론사의 내용이 나타난다.
  • navbar 현재 카테고리 탭 배경에 프로그레스바 애니메이션을 적용한다. (20초)
    • 1초 단위로 색이 차오르도록 한다.(위의 이미지 참고)
  • 선택된 카테고리가 아닌 다른 카테고리에 마우스 호버 시 밑줄이 생긴다.
  • 카테고리를 클릭하면 해당 카테고리로 바로 이동한다.
  • 언론사 기사 영역 컴포넌트 구성
    • 언론사 브랜드마크, 최종 편집 일시, [구독하기 버튼], 메인 뉴스 1개(썸네일, 타이틀), 서브뉴스 6개(뉴스 타이틀만), 편집권 안내 문구
      image
  • 메인 뉴스에 마우스를 호버하면
    • 썸네일 이미지는 5% 확대된다.
    • 뉴스 타이틀에 밑줄이 생긴다.
  • 서브 뉴스 타이틀에 마우스를 호버하면 밑줄이 생긴다.
  • #35

Refactor

Task: 기반 컴포넌트 클래스 및 설계

Flux Pattern

  • State와 Component를 분리한다.
  • Component는 State를 인자로 전달받아 UI를 만든다.
  • Component에서 발생한 Action을 dispatch를 통해 State를 변경한다.
  • dispatch 함수를 통해 action과 payload를 전달하여 reducer로 상태를 변경한다.
  • 해당 상태를 subscribe하는 함수에 변경된 상태를 인자로 전달하여 실행한다.
  • 변경된 새로운 props를 전달받은 컴포넌트는 현재 상태와 비교하여 변경된 부분만 반영한다.

Store - View 역할과 책임

  • 구독 리스트를 관리하기 위해서 별도의 store(model) 객체나 함수를 구성한다.
  • Store는 View영역에 독립적으로 동작한다.

Task: 테스트 코드 구현

  • 테스트 코드는 단위테스트를 익히는 목적으로, 함수나 메서드 단위의 테스트를 수행한다.
  • Vitest 테스트 도구를 활용한다.
  • 리팩토링을 해야 하는 코드에 대해 테스트 코드를 구현한다.
  • 리팩토링 코드를 테스트 코드를 돌려서 확인한다.

1. 최소단위 함수부터 테스트하기

반환값이 명확히 존재하고, 다른 함수를 호출하지 않는 dependency 가 없는 함수부터 테스트 한다.

  • NewsStandReducer 함수 테스트 코드 작성하기
  • #37

각 언론사 브랜드마크가 있는 셀에 마우스를 올리면, 구독 상태에 따라 버튼을 표시한다.

  • 셀에 마우스를 올리면 구독 버튼을 보여준다.
  • 리스트 보기에서도 언론사 별로 구독하기 버튼을 가져야 하므로 구독 버튼은 별도의 컴포넌트로 만든다.
  • subscribeButton props로 현재 언론사 이름과 구독 여부를 전달 받는다.

Refactor

  • 마우스 올린 셀에만 버튼 동적으로 만들어주도록 수정하기
    • 불필요한 요소를 모두 만들어서 DOM에 추가해두면 뷰를 조작할 수 있는 가능성

Task: Store 로직 개선하기

요구 사항

  • 순수한 store 구성
  • store는 view의 변화에 영향을 받지 않도록 구현한다.
  • store 내의 함수는 순수한 함수로 구현되야 하고, 테스트 가능해야 한다.

Subtasks

  • Action에 따라 payload interface를 만들기 (34f8351)
  • #24
    • 처음엔 빈 배열로 먼저 렌더링하고, fetch가 오면 그때 state를 업데이트해서 재렌더링하기

구현 과정 고민

Current

  • render 시 인자로 받은 새로운 props에 대해 이전과 변경된 부분을 반영해주기 위해서(상태 변경이 있는지, 이전 props와 비교하기 위해서) 컴포넌트에 이전 상태를 저장해두고 관리해야 한다. < 이걸 어떻게 해결해야 할까
    • 초기 데이터 동기화하기 전과 후의 변화를 감지하기 위해 null이나 빈배열을 초기에 세팅한다.
    • 이렇게 한 이유는? 각 컴포넌트가 자신의 렌더링에 필요한 상태만을 가지고 있기 위해서
    • 그냥 이전처럼 컴포넌트 생성 시 인자로 받는게 나은가?
    • 수정했던 이유는? props를 세팅하고 이전 prop과 현재 props을 비교하고 업데이트 해주는 로직에 중복이 많고 더러워졌다. 컴포넌트 생성 시에는 그냥 이를 구성하는 HTML Element들만 만들어주면 되기 때문에(props 설정과 분리), render 메서드로만 props를 전달받아 반영되도록 함
  • 근데 상태 구독은 전체 newsStand 한번만 해주고, reducer도 하나로만 관리하고 있음
  • 각 하위 컴포넌트는 NewsStandState 중 일부를 props(state)로 가지고 있어 생성한 interface의 내용 중 불필요하게 중복이 많다.

개선 방향

  • 이전처럼 생성 시 인자로 받되 필요한 props만 저장해두기

To Be

  1. 스토어를 서로 영향을 주는 상태들끼리 묶거나 일정 크기로 여러개로 나눈다. (reducer도 여러개)
  • 이렇게 하면 각 컴포넌트가 자신의 렌더링에 필요한 상태만을 가지고 있을 수 있어서 컴포넌트 생성 시 initialState도 props로 넘겨서 비교하기 용이해진다.
  1. 하나의 스토어를 두고 그 중 일부 상태와 특정 컴포넌트의 render 메서드를 mapping하여 Register한다. < 방법이 명확하진 않음

Task: 재사용 코드 구현

구독 언론사에서 기존 리스트 UI, 그리드 UI를 어떻게 재사용할 수 있을까?

  • Subtask: #19, #31
  • 일단 tabOption에 맞는 UI를 method로 구분

고민

  • 구독한 언론사 보기 UI 구현 시 전체 언론사 보기, 구독한 언론사 보기 상태에 따라 액션이 결정되어야 한다.

Before

  • GridViewer, ListViewer 각각에 버튼을 생성하고, 생성할 때 grid, viewer를 인자로 전달하여 이에 따라 액션이 결정된다.
  • 기존 구조의 문제점: 현재 상태에 따라 수행해야 하는 액션이 다르기 때문에, render method에서 매번 알맞게 이벤트리스너를 추가해줘야 함 (여러번 추가됨)

해결 방안

  1. 생성자에서 인자로 props를 받아서 저장해두고, 이에 맞게 실행되도록 미리 정해둔다: 컴포넌트 생성 시에 이미 props에 따라 컴포넌트가 어떻게 렌더링이 될지 결정되어 있도록
  2. 컴포넌트가 clickEventHandler를 property로 가지고 있고 render될 때 받은 props에 따라 handler 함수가 결정된다. -> ViewerButton
  3. Action은 하나로 두고, 리듀서에서 해당 Action에 대해 처리할 때 이전 state의 tabOption에 따라 상태를 변경한다. -> 바로 액션을 실행하지 않고 모달을 보여줘야 하는 경우

✔️ 4. 구독하기 서비스에 대한 별도의 모듈을 만든다.

구독하기 버튼

  • subscribe tab일 때는 클릭 시 구독 해지 안내 모달창이 뜬다.
  • all tab일 때는 언론사 구독상태를 변경해주는 Action을 dispatch한다.
  • all tab & list viewer 일때는 snackbar가 보여지고, 5초후에 subscribe tab & list viewer의 마지막 index로 이동한다.

`TrendNewsBar` 컴포넌트 2개로 구성된다.

image

SubTasks

  • 왼쪽 바와 오른쪽 바는 각각 다른 최신 뉴스와 헤드라인 5개로 이루어진다.
  • 부모 컴포넌트에서 전체 뉴스 데이터를 fetch 받고 5개씩 나눠서 state에 두고, props로 각 newsBar에 전달한다.

Refactor

  • 왼쪽 뉴스 리스트와 오른쪽 뉴스 리스트 분리하여 props 전달
  • currentIndex, nextIndex에 해당하는 뉴스 헤드라인 생성 & wrapper

width 930px height 388px의 영역에 6 * 4 테이블로 구성된다.

SubTasks

  • allpressList 전체 96개의 press data를 fetch 받는다.
  • allpressList와 현재 페이지의 gridPressStartIndex를 인자로 받아 테이블을 구성한다.
  • GridViewer 컴포넌트는 table 태그, 각 Grid는 td 태그, 4개의 row로 이루어진다.
  • 각 테이블의 셀에는 언론사 브랜드 마크가 중앙에 배치된다.

image

Task: 최신 뉴스 자동 롤링 영역

최신 뉴스 자동 롤링 영역

Data

설계

  • 일단 Store에 데이터 바로 저장해둔다.
  • dispatch 함수로 reducer를 실행한다. NewsStandReducer는 Store의 데이터를 갱신한다.

UI

Feature

TODO

  • NewsBar Data fetch 작업
    • 고민: fetch는 어디서 어떻게 해서 Store에 저장하지? (실제 reducer는 순수함수 여야 한다. 비동기 로직이 포함되면 안된다.)

언론사 구독/해지 기능

Subtask

  • 유저가 [구독하기] 버튼을 클릭하면 Store에서 해당 언론사의 구독 상태를 변경한다.
  • localStorage와 Store 연동하기

DB & Server

  • MongoDB

pupeteer 라이브러리를 활용하여 네이버 언론사 브랜드 마크 이미지 데이터를 크롤링하여 JSON 데이터로 구성한다.

Purpose

  • 라이브러리 공식문서 직접 읽고 API 사용하는 습관 들이기

Memo

  • Page.evaluate(callback) : 해당 페이지에서 콜백함수를 실행한 결과를 반환
  • Page.$eval(selector, pageFunction): 해당 페이지 내에서 selector로 querySelector를 실행하고, 탐색한 결과를 pageFunction에 첫 번째 인수로 전달
    • $$ 으로 querySelectorAll도 사용 가능

Task: 내가 구독한 언론사 그리드 보기

  • 전체 언론사 그리드 보기 UI와 동일 (컴포넌트 재사용)
  • 유저가 구독한 언론사 브랜드 마크만 보인다.
  • 구독중인 언론사의 브랜드마크 셀에 마우스를 올리면 [구독해지] 버튼이 나타난다.
  • 구독 해지 버튼을 누르면 구독 해지 안내 모달창이 뜬다. (위 컴포넌트 재사용)
  • 유저가 구독을 해지하면 즉시 그리드에서 해당 언론사의 브랜드 마크가 삭제된다.

WAS 구현

  • WAS(Web Application Server)의 역할에 대해 이해한다.
  • Express를 활용하여 직접 구성하고 프론트엔드와 연동하여 동작하게 한다.
    • 공식사이트를 참고하고 최신 버전을 사용한다.
    • 기본응답만 되는 수준으로 서버를 구성한다.

WAS의 역할

클라이언트 요청에 대한 처리

1. 라우팅

  • Determining how an application responds to a client request to a particular endpoint
  • URI(path), specific HTTP request methods
  • Each route which is matched <=> handler function: 클라이언트 요청에 대한 핸들러 함수 실행
  1. 미들웨어
  2. 정적 파일 제공
  3. 데이터베이스 연동
  4. 템플릿 엔진 지원

CORS

Feature: 기본 상단 영역 UI

기본 상단 영역 UI

  • 기본 상단 영역의 왼쪽에는 뉴스스탠드 로고를, 오른쪽에는 시스템 날짜를 표시한다.
image

Sub Tasks

  • 왼쪽에 뉴스스탠드 로고 컴포넌트, 오른쪽에는 날짜 컴포넌트로 헤더를 구성한다.
  • Header
    • Title
    • TodaysDate

Study: 학습 정리 백로그

#3 최신 뉴스 자동 롤링

  • 이벤트 루프 기반 rAF 동작 방식 및 콜백 실행 순서 정리하기 (타이머 함수가 실행되는 시점과 rAF callback이 실행되는 시점)

뉴스 스탠드 로고를 클릭하면 화면을 새로고침 한다.

페이지 새로고침하는 방법

1. window.location.reload

  • 현재 리소스를 다시 불러오고, 완전히 새로고침된다.
  • 모든 리소스를 다시 다운로드하므로 네트워크 트래픽이 더 많이 발생

2. history.go(0)

  • 이전 상태와 동일한 페이지로 돌아가는 대신 브라우저 캐시로 페이지를 새로고침한다.
  • 이미지, 스크립트 등 다시 다운로드할 필요가 없어 새로고침이 빠르다.

차이점

  • window.location.reload(): 페이지를 완전히 새로고침하고 이전 상태를 유지하지 않음
  • history.go(0)은 페이지를 새로 고치고 이전 상태를 유지

선택한 방법과 이유

  • history.go: 현재 변경되는 리소스가 거의 없음
  • 이후에 서버와 연동하면 reload로 변경: 사용자가 구독한 언론사 리스트를 다시 받아야 하므로 페이지의 내용을 완전히 새로 고치고 리소스를 다시 다운로드해야 하기 때문

left, right element를 인자로 받아서 rAF로 롤링 애니메이션을 실행하는 로직을 별도로 구분한다. (RollerTimer 클래스로 분리)

Screen Recording 2023-05-28 at 19 49 30

  • 5초마다 자동으로 롤링된다.
  • 무한 롤링된다.
  • rAF로 정확한 시점에 콜백이 실행되도록 구현한다.
  • 좌우 영역은 1초 간격으로 번갈아가며 롤링된다.
  • 롤링될 때 바 영역 안에서 제목이 위로 넘어가는 애니메이션을 적용한다.
  • 각 영역에 마우스를 호버하면
    • 무한 롤링이 일시정지된다.
    • 헤드라인에 밑줄을 표시한다.

Refactor

리스트 보기 데이터 fetch 로직 & 상태 관리 방식 변경하기

Current

  • 전체 언론사 데이터 한번에 받아와서, currentCategoryIndex 와 pressIndex만 상태로 관리하고 있다.

Expected

  1. 카테고리 단위로 데이터를 요청해서, currentCategoryIndex, pressList, pressIndex를 상태로 갖는다.
  2. 데이터 받아와서 원하는 형태로 가공해서 스토어에 저장해두고 사용한다.

Refactor

  • Avoid duplication in state: 현재 categoryPressList의 각 카테고리 별 pressList 데이터와 pressArticleMap(pressName을 key로, 해당 언론사의 기사들을 value로 하는 맵)이 중복된다.

Task: 내가 구독한 언론사 리스트 보기

  • 내가 구독한 언론사는 리스트 보기를 기본으로 한다.
  • 전체 언론사 리스트 보기 UI와 동일 (컴포넌트 재사용)
  • navbar tab 구독하는 언론사 목록으로 하고, 선택한 언론사 이름 > 을 파란색으로 표시한다.
  • 유저가 구독한 순서대로 배치한다.
  • [구독해지] 버튼을 누르면 구독 해지 안내 모달창이 뜬다.
  • 모달의 버튼에 마우스 호버 시 텍스트에 밑줄이 생긴다.
  • 유저가 구독을 해지하면 즉시 유저의 구독 리스트에서 해당 언론사를 삭제하고 다음 순서의 언론사가 바로 나타난다.
  • Fix: 마지막 언론사 구독을 해지하면 첫 언론사를 보여준다.
  • 구독한 언론사 목록이 많은 경우 드래그를 통해 가로로 스크롤 된다.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.