본문 바로가기

Parsing to BBC News

React에서 서버에 데이터 요청하고 화면에 표시하기

728x90

오늘 해볼 것은 아래와 같다.

1. 외국 사이트에서 문장을 크롤링(사실 파싱이 맞다)하여 화면에 표시(파싱)
1.1 Python(BeautifulSoup)을 통해 외국사이트에서 특정 키워드를 추출하여 배열로 return 하기
1.2 Python에서 리턴한 데이터를 node에서 받아와 GET 웹서비스로 만들기 
1.3 React 기반 웹에서 node 서비스를 호출하고, 화면에 '예쁘게' 표시하기 <- 이거에서

 

 

1.3.1 React에서 서버에 데이터 요청하고 화면에 표시하기 <- 이거

1.3.2 화면에 표시한 데이터 예쁘게 표시하기

1.3.3 화면의 일부 데이터 서버에 재요청하기(papago 이용하여 번역 기능 만들기)

1.3.4 번역한 데이터 바탕으로 듀오링고처럼 게임 형태로 데이터 표시하기

 

 

import React from 'react';
import logo from './logo.svg';
import './App.css';

class App extends React.Component {
    render() {
        return (
            <div className="App" >
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <p>
                        Edit <code>src/App.js</code> and save to reload.
                    </p>
                    <a
                        className="App-link"
                        href="https://reactjs.org"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        Learn React
                    </a>
                </header>
            </div>
        );
    }
}

export default App;

 

아무것도 건드리지 않은 기본적인 create-react-app이다.

여기에서 화면이 처음 로드되었을때 실행할 로직을 추가한다.

 

해당 로직은 componentDidMount 를 통해 작업할 수 있다. 

 

 

 

 

import React from 'react';
import logo from './logo.svg';
import './App.css';

class App extends React.Component {
    componentDidMount() {
        this.callAPI()
    }    
    callAPI = async () => {
        const response = await fetch('http://localhost:3000/viewNews')
        const body = await (response).json()
        console.log(body)
    }
    render() {
        return (
            <div className="App" >
                <header className="App-header">
                    <img src={logo} className="App-logo" alt="logo" />
                    <p>
                        Edit <code>src/App.js</code> and save to reload.
                    </p>
                    <a
                        className="App-link"
                        href="https://reactjs.org"
                        target="_blank"
                        rel="noopener noreferrer"
                    >
                        Learn React
                    </a>
                </header>
            </div>
        );
    }
}

export default App;

componentDidMount에서 callAPI를 다시 호출하는 이유는 componentDidMount에서 다른 작업을 할 수 있기 때문이다.

 

만약 componentDidMount에서 viewNews 서비스를 호출하는 것 외에 다른 작업을 해야한다면, 소스가 굉장히 보기 불편할 것이다.

 

 

    componentDidMount = async () => {
        //뉴스 가져오는 로직
        const response = await fetch('http://localhost:3000/viewNews')
        const body = await (response).json()
        console.log(body)
        
        //버튼 목록 만드는 로직
        /*


        */
        //점수 계산하는 로직
        /*



        */
        
    }

이런식으로 여러 로직을 하나의 함수가 다 처리하게하면 보기 불편하고 복잡하지만

 

 

    componentDidMount() {
        this.callAPI()
        this.createButtonView()
        this.countScore()
    }    

  이런식으로 각각의 역할에 따라 함수를 호출한다면 한눈에 보기에도 정말 깔끔하다.

 

 

    callAPI = async () => {
        const response = await fetch('http://localhost:3000/viewNews')
        const body = await (response).json()
        console.log(body)        
    }

 

다시 callAPI 함수를 보자.

 

우선 async로 비동기 함수를 선언하고, 응답 데이터를 fetch로 가져온다.

가져온 Response 객체는 그대로 사용할 수 없기 때문에 여기서 json 데이터를 추출해주는 json()를 사용해 다시 가져온다.

 

 

 

 

자세한 내용은 여기 참고

dmitripavlutin.com/javascript-fetch-async-await/

 

How to Use Fetch with async/await

How to use fetch() with async/await syntax in JavaScript: fetch JSON data, handle errors, make parallel requests, cancel and intercept requests.

dmitripavlutin.com

 

 

 

화면에서 이렇게 데이터를 가져왔다.

 

이 데이터를 화면에 표시하기 위해서는 데이터를 state에 넣어주고, 해당 데이터를 컴포넌트에서 참조하면 된다.

 

    constructor(props) {
        super(props);
        this.state = {
            newsList: []
        }
    }

    componentDidMount() {
        this.callAPI()
    }    
    callAPI = async () => {
        const response = await (await fetch('http://localhost:3000/viewNews')).json()
        this.setState({ newsList: response });        
    }

바뀐 코드는 위와같다.

 

생성자에 뉴스 데이터를 가져올 수 있는 배열 newsList를 추가했고, callAPI에서 불러온 데이터를 setState했다.

 

 

 

이제 Component를 작성하고 App의 state를 전달해보자.

 

import React from 'react';
import logo from './logo.svg';
import NewsList from "./Components/NewsList";
import './App.css';

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            newsList: []
        }
    }

    componentDidMount() {
        this.callAPI()
    }    
    callAPI = async () => {
        const response = await (await fetch('http://localhost:3000/viewNews')).json()
        this.setState({ newsList: response });        
    }
    render() {
        return (
            <div className="App" >
                <NewsList newsArr={this.state.newsList} />
            </div>
        );
    }
}

export default App;

 <NewsList>는 뉴스 목록을 담을 컴포넌트이며, props으로 callAPI에서 가져온 newsList를 받는다.

최상단에 Components/NewsList 를 추가하고, render에 있는 모든 내용을 지운 뒤 NewsList를 추가한다.

 

import React from 'react';
function NewsList(props) {
    const arr = props.newsArr;
    const newsElement = arr.map((element, index) => {
        const style = {"fontWeight":"bold" }
        return <div key={index}>
                    <span style={style}>{element[0]}</span>
                    <br />
                    <span >{element[1]}</span>
                </div>
    });

    return <div>{newsElement}</div>
}
export default NewsList;

Components/NewsList.js 의 코드이다.

 

props로 받은 뉴스 목록을 map으로 순회하며 그리는 단순한 로직이다.

또한 스타일을 별도로 지정하여 제목과 내용을 시각적으로 구분할 수 있도록 했다.

 

여기서 key는 리스트를 그릴때 반드시 넣어주는것이 좋은데,

이유는 ko.reactjs.org/docs/reconciliation.html#recursing-on-children에서 확인할 수 있다.

 

재조정 (Reconciliation) – React

A JavaScript library for building user interfaces

ko.reactjs.org

 

 

결과이다.

 

 

이제 이 데이터를 예쁘게 표시해보도록 하겠다.

728x90