하루하루 꾸준히, 인생은 되는대로

리액트

간단한 뉴스 뷰어 만들기

긤효중 2023. 1. 19. 01:30

리액트를 다루는 기술 14장을 참고해서 만들었고, 타입스크립트도 적용해보았다.

 

먼저 API KEY가 필요하다.

https://newsapi.org/account

 

Login - News API

 

newsapi.org

API KEY를 발급받으면 이메일로, KEY가 올 것이다.

 

리액트에서 API KEY를 환경변수로 관리 할 수 있다.

프로젝트 최상단에 .env파일을 만들고, .gitingnore파일에 .env를 추가해서 깃에 올라가는 것을 막아준다.

그리고 API KEY를 적어주면 된다.

이떄, API KEY는 REACT_APP_으로 시작해야 한다 

사용할 떄는 jsx,js에서 process.env.REACT_APP_이름 변수명을 넣어서 사용해준다.

 

src폴더 구조는 다음과 같고, constants.ts에서는 받아올 API Data의 타입을 맞춰서 지정해주고,

axios 인스턴스를 넣어주었다.

받아올 API는 크게 2가지 인데, 전체 기사와, 카테고리별 기사이다.

 

먼저 axios 인스턴스를 만들어주었다.

axios 인스턴스를 사용하면, 기본 구성 값 설정을 편하게 할 수 있고, 인터셉트도 사용 가능하다.

 

axios 인터셉트는 then,catch처리 이전에 요청이나 응답을 가로챌 수 있다.

 

axios 인스턴스 예시

const instance = axios.create({
  baseURL: 'https://some-domain.com/api/',
  headers: { 'X-Custom-Header': 'foobar' },
  timeout: 1000,
});

이외에도 구성 값 설정이 되게 많은데, 필요할떄 마다 찾아 쓰면 될 거 같다.

https://yamoo9.github.io/axios/guide/api.html#%EC%9D%B8%EC%8A%A4%ED%84%B4%EC%8A%A4-%EC%83%9D%EC%84%B1

 

API | Axios 러닝 가이드

API 구성(configuration) 설정을axios()에 전달하여 요청할 수 있습니다. axios(config) axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }); 1 2 3 4 5 6 7 8 9 axios({ method:'get', url:'http://bit

yamoo9.github.io

전체 기사, 카테고리 별 기사에 따른 다른 API주소가 있었고, 인스턴스를 2개 만들었다.

const instance = axios.create({
  baseURL: `https://newsapi.org/v2/top-headlines?country=kr&apiKey=${process.env.REACT_APP_API_KEY}`,
});

const categoryinstance = axios.create({
  baseURL: `https://newsapi.org/v2/top-headlines?country=kr&`,
});

전체 기사에 대해 get요청을 보냈을떄, 받은 data의 타입을 지정했다.

먼저 전체 기사에 대한 get요청을 보내면, 다음과 같이 오는데,

articles안에 여러 배열이 들어있는 것을 볼 수 있다.

이 배열 하나를 자세히 보면, 

이렇게 author,content,title...등의 정보가 담겨 있는 것을 확인 할 수 있고, 이를 위한 타입을 생성해주었다.

한 article에 source 객체가 들어있고, author,content,....이 들어있는데, 이를 타입으로 설정해주었다.

 

type article = {
  id: number;
  author: string;
  content: string;
  description: string;
  publishedAt: string;
  source: source;
  title: string;
  url: string;
  urlToImage: string;
};

type source = {
  id: null | string;
  name: string;
};

 

source의 id에 null 타입도 가능하게 한 이유는 , 실제 요청을 받았을 떄 id가 null이었기 떄문이다.

(왜 null인거지..)

 


전체 화면은 다음과 같이 구성된다.

가장 최상단에 헤더가 위치하고,

 

전체 기사를 감싸는 section이 위치한다.

 

그리고 기사 하나하나는 div태그로 묶어주었다.


Header에서 카테고리를 클릭하면, props로 카테고리가 뿌려지는데(Header가 최상단),

누른 카테고리에 따라 카테고리별 기사가 달라진다.

 

먼저 최상단 NewsHeader 컴포넌트이다(헤더부분)

먼저 모든 카테고리를 문자열 배열로서 만들었다.(비즈니스,과학,연애,스포츠,건강,기술)

 

state를 하나 만들고, 카테고리를 누를떄마다 state가 바뀌도록 해주었다.

그리고 최종적으로 누른 카테고리(state)가 하위 컴포넌트로 전달되도록 했다.

 

이떄 카테고리들을 랜더링 할 떄, uuid()함수를 사용하였다.
고유한 키를 요구할떄, 유용하게 사용할 수 있다.

 

NewsContent컴포넌트로 최종적으로 선택된 category가 props로 전달되는 것을 볼 수 있다.


NewsContent 컴포넌트인데, 이 부분은 전체 기사를 감싸는 컴포넌트이다.

특별한 건 없고, NewsList에 NewsHeader에서 받은 category props를 전달해주었다.

 


마지막 기사 하나하나에 해당하는 NewsList 컴포넌트이다.

 

 

 

앞서 전달 받은 category props는 한글이었다. (건강,스포츠 등등...)

 

다만 카테고리 별로 Get요청을 했을 떄, 주소는 다음과 같았고 

GET https://newsapi.org/v2/top-headlines/sources?category=businessapiKey=API_KEY

한글에 대응하는 영어를 constants.ts에서 map으로 매핑시켰다.

//['비즈니스', '과학', '연애', '스포츠', '건강', '기술']
const mappingkrtoEn = new Map([
  ['비즈니스', 'business'],
  ['연애', 'entertainment'],
  ['스포츠', 'sports'],
  ['건강', 'health'],
  ['기술', 'technology'],
  ['과학', 'science'],
]);

 


그리고 props가 2번에 걸쳐서 이동하는데 NewsHeader->NewsContent->NewsList

이 과정이 많아지는 경우, 하나의 어플리케이션에서 여러 컴포넌트로 전달해 줘야하는 경우

props-driling이 발생한다고 하고, 이를 해결하기 위해 전역 상태관리가 필요하다고 한다.

 

전역 상태 관리는 차근차근 공부해 볼 생각이다