관리 메뉴

SIMPLE & UNIQUE

1-3강 : html, css, img파일 세팅, 공공데이터 API 호출 본문

탈잉 강의 자료/2021_비전공자도 가능한 웹 프로젝트

1-3강 : html, css, img파일 세팅, 공공데이터 API 호출

착한코딩 2021. 3. 27. 23:48

1-3강_완료코드.zip
0.89MB
1-3강_완료 덮어쓰기 코드.zip
0.25MB

1_3 목표 : 공통영역(header, footer)을 별도로 구현하고, header와 footer 사이에 라우팅된 페이지를 노출시킨다. 공공데이터 포털에 가입해서 API KEY를 발급 받는다. 발급 받은 KEY를 사용해 코로나19 예방접종센터 조회 API를 호출한다.

 

1. css, img파일 경로를 확인한다.

C:\react200\client\src에 css와 img폴더를 아래와 같이 위치 시킨다.

css와 img파일을 컴포넌트에서 상대경로로 import할 것이다. Footer폴더, Header폴더, App.js가 같은 경로(components폴더)에 위치해 있는 것을 확인한다. css폴더, img폴더가 components폴더와 같은 경로(src폴더)에 있는 것을 확인한다.

 

2. App.js 파일에 css와 header, footer 파일을 import한다.

App.js파일에서 상위 경로(부모)에 위치한 css폴더는 앞에 ../붙여 import한다.

App.js파일과 동일 경로(형제)에 위치한 Header와 Footer폴더을 앞에 ./붙여 import한다.

2단계 상위경로(할아버지)일 경우  ./../../를 붙이면 된다.

Route태그를 확인해보면, 루트 경로(/)로 호출될 경우 LoginForm컴로넌트를

Vaccination_CenterList경로를 호출할 경우 /Vaccination_Center/Vaccination_CenterList 컴포넌트를 라우팅해준다.

Route태그를 사용하지 않은 Headerd와 Footer 컴포넌트는 호출 경로와 상관없이, 항상 화면에 노출된다.

import React, { Component } from 'react';
import { Router, Route, Switch } from "react-router";

import Api_test from './Api_test'
// css
import '../css/new.css';
// header
import HeaderAdmin from './Header/Header admin';
// footer
import Footer from './Footer/Footer';
// login
import LoginForm from './LoginForm';
// Vaccination_CenterList
import Vaccination_CenterList from './Vaccination_Center/Vaccination_CenterList';


class App extends Component {
  constructor (props) {
    super(props);
    this.state = {
    }
  }

  componentDidMount() {}

  render () {
    return (
      <div className="App">
          <HeaderAdmin/> 
          <Switch>
            {/* <Route exact path='/' component={Api_test} /> // root 경로일 경우 라우팅 */}
            <Route exact path='/' component={LoginForm} />
            <Route path='/Api_test' component={Api_test} />
            <Route path='/Vaccination_CenterList' component={Vaccination_CenterList} />
          </Switch>
          <Footer 
            footer_address={this.props.footer_address} 
            footer_tel={this.props.footer_tel}  
            footer_email={this.props.footer_email} 
            footer_mobile={this.props.footer_mobile} 
          />
      </div>
    );
  }
}

App.defaultProps = {
  // footer value
  footer_address: '[34234] 서울특별시 강남구 삼성동 111-114',
  footer_tel: '02-1234-5678',
  footer_email: 'ljung5@naver.com',
  footer_mobile: '010-3288-3398',
};


export default App;

 

3. header 파일을 확인한다.

C:\react200\client\src\components\Header\Header admin.js

헤더는 페이지 변경과 상관없이 항상 상단에 노출되는 영역이다. 회원 정보, 로그인, 로그아웃, 페이지 네비게이션을 구현한다. img태그와 Link태그 활용법을 확인한다.

import React, {Component} from 'react';
import { Link } from 'react-router-dom';

class Header extends Component {
    constructor(props) {
        super(props);
        this.state = {
            usernm:'',
        };
    }
    render () {
        return(
            <header className="gnb_box">
            <div className="hd_top">
                <div className="top_wrap ct1 af">
                <ul className="hd_left af">
                <li className="my1" onMouseEnter={this.myInfoHover} onMouseLeave={this.myInfoLeave}><b>내정보</b>
                        <div className="box0 box1">
                            <ul>
                            <li><a>내 정보 수정</a></li>
                            <li><a href="javascript:" onClick={this.logout}>로그아웃</a></li>
                            </ul>
                        </div>
                        </li>
                    <li className="my2"><b><span>0</span>알림</b>
                    </li>
                </ul>
                <div className="hd_right">
                    <p><span>'홍길동'</span>님 반갑습니다.</p>
                </div>
                </div>
            </div>
                <div className="h_nav ct1 af">
                    <div className="logo">
                        <Link to={'/'}><img src={require("../../img/layout/logo.jpg").default} height="65px" width="200px" alt=""/></Link>
                    </div>
                    <nav className="gnb gnb_admin">
                    <ul className="af">
                        <li className="menulist">
                            <Link to={'/UserApproval'}>사용자 관리</Link>
                        </li>
                        <li className="menulist">
                            <Link to={'/AdminResearchProject'}>Research Projects 관리</Link>
                        </li>
                        <li className="menulist">
                            <Link to={'/SoftwareList'}>Software Tools 관리</Link>
                        </li>
                        <li className="menulist">
                            <Link to={'/AdminDataSourceList'}>Data Sources 관리</Link>
                        </li>
                        {/* 드롭다운 이벤트 */}
                        <li  className="menulist"><Link to={'/Vaccination_CenterList'}>백신 센터 조회</Link>
                        <ul className="gn_2">
                            <li><Link to={'/community/notice'}>공지사항</Link></li>
                        </ul>
                        </li>
                        <li  className="menulist">
                            <Link to={'/SubCodeManage'}>Sub code 관리</Link>
                        </li>
                    </ul>
                    </nav>
                </div>
            </header>
        );
    }
}

export default Header;

4. footer 파일을 확인한다.

C:\react200\client\src\components\Footer\Footer.js

푸터도 헤더와 마찬가지로 페이지 변경과 상관없이 항상 하단에 노출되는 영역이다. 사이트 관련 정보를 노출한다.

상위 컴포넌트인 App.js에서 전달받은, props변수의 사용법을 확인한다.

import React, { Component } from 'react';

class Footer extends Component {
  render () {
    return (
        <footer className="footer">
            <ul>
              <li className="priv"><a href="#n">개인정보처리방침</a></li>
              <li className="em_bt"><a href="#n">이메일주소무단수집거부</a></li>
            </ul>
            <div className="ft_p">
              <span>주소 : {this.props.footer_address}</span>
              <span>Tel : {this.props.footer_tel}</span>
              {/* <span>Email : {props.footer_email}</span> */}
              {/* <span>Mobile : {props.footer_mobile}</span> */}
            </div>
            <p>COPYRIGHT &copy; 2019 RT-ROD, ALL RIGHTS RESERVED.{this.props.name}</p>
        </footer>
    );
  }
}

export default Footer;

5. 로그인(home) 화면을 세팅한다.

C:\react200\client\src\components\LoginForm.js

import React, { Component } from 'react';
import { Link } from 'react-router-dom';

class LoginForm extends Component {
    render () {
        return (
            <section className="main">
                <div className="m_login signin">
                <h3><span><img src={require("../img/main/log_img.png").default} alt="" />
                </span>LOGIN</h3>
                <div className="log_box">
                    <div className="in_ty1">
                        <span><img src={require("../img/main/m_log_i3.png").default} alt="" /></span>
                        <input type="text" id="email_val" placeholder="이메일" />
                    </div>
                    <div  className="in_ty1">
                        <span className="ic_2">
                            <img src={require("../img/main/m_log_i2.png").default} alt="" />
                        </span>
                        <input type="password" id="pwd_val" placeholder="비밀번호" />
                    </div>
                    <ul className="af">
                        <li><Link to={'/register'}>회원가입</Link></li>
                        <li className="pwr_b" onClick={this.pwdResetClick}><a href="#n">비밀번호 재설정</a></li>
                    </ul>
                    <div className="s_bt" type="" onClick={(e) => this.submitClick(e)}>로그인</div>
                </div>
                </div>
                <div className="m_login m_pw chgpw">
                <h3 className="pw_ls">비밀번호 재설정 <span className="compl1">완료</span></h3>
                <div className="log_box">
                    <div className="pw_one">
                        <div className="in_ty1">
                        <span><img src={require("../img/main/m_log_i3.png").default} alt="" /></span>
                        <input type="text" id="reset_email_val" name="" placeholder="이메일"/>
                        </div>
                        <div  className="in_ty1">
                        <span className=""><img src={require("../img/main/m_log_i1.png").default} alt="" /></span>
                        <input type="text" id="reset_name_val" name="" placeholder="성명"/>
                        </div>
                        <div className="btn_confirm btn_confirm_m">
                        <div className="bt_ty bt_ty_m bt_ty1 cancel_ty1" 
                        onClick={this.pwdResetCancleClick}>취소</div>
                        <a href="#n" className="bt_ty bt_ty_m bt_ty2 submit_ty1" 
                        onClick={this.pwdResetConfim}>확인</a>
                        </div>
                    </div>
                </div>
                </div>
            </section>
        );
    }
}

export default LoginForm;

6. header, footer, home 화면이 세팅되면 아래와 같은 화면을 확인할 수 있다.

 

7. 외부 Api(코로나 19 예방접종센터 정보)를 호출해, 데이터를 확인한다.

아래 사이트에 회원가입을 하고, 코로나 19 예방접종센터 조회 데이터를 [활용신청] 한다. 활용신청이 승인되면, Api키가 발급되는데 [마이페이지] > [오픈API] > [인증키 발급현황]에서 확인 가능하다. 승인 후 1~2시간 정도 후에 api호출이 가능하다.

 

공공데이터활용지원센터_코로나19 예방접종센터 조회서비스 링크

www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15077586

 

공공데이터 포털

국가에서 보유하고 있는 다양한 데이터를『공공데이터의 제공 및 이용 활성화에 관한 법률(제11956호)』에 따라 개방하여 국민들이 보다 쉽고 용이하게 공유•활용할 수 있도록 공공데이터(Datase

www.data.go.kr

크롬 브라우저에서 api url을 호출하면 다음과 같이 json형태의 데이터를 확인할 수 있다. 이 데이터를 react페이지에 노출할 것이다.

8. Vaccination_CenterList.js파일에서 api를 호출하고, 데이터를 화면에 그려준다.

C:\react200\client\src\components\Vaccination_Center\Vaccination_CenterList.js

axios로 api url을 호출하는데, http get방식을 사용한다. 가져온 데이터를 Vaccination_CenterListAppend함수에서 반복문을 돌려 tr태그 array를 생성한다. 생성한 배열을 state변수에 넣어 table태그 사이에 노출시킨다.

import React, { Component } from 'react';
import axios from "axios";

class Vaccination_CenterList extends Component {
    constructor(props) {
        super(props);

        this.state = {
            responseFPList: '',
            append_FPList: '',
        }
    }

    componentDidMount() {
        this.callVaccinationCenterListApi()
    }

    callVaccinationCenterListApi = async () => {
            axios.get('https://api.odcloud.kr/api/15077586/v1/centers?page=1&perPage=10&serviceKey=aMzxu1mdVjayU%2FMAf%2F7%2FBYHlEFpoNJmp2Y%2FeKgea98%2BsVNCZj%2FDXGldRUMXqWFb6t5NtxP8NcsgK%2FWu7XcfWyQ%3D%3D', {
            })
            .then( response => {
                try {
                    this.setState({ responseFPList: response });
                    this.setState({ append_FPList: this.VaccinationCenterListAppend() });
                } catch (error) {
                    alert(error)
                }
            })
            .catch( error => {alert(error);return false;} );
    }

    VaccinationCenterListAppend = () => {
        let result = []
        var json = this.state.responseFPList.data

        for(let i=0; i<json.data.length; i++){
            var data = json.data[i]
            var idx = i+1
            result.push(
                <tr class="hidden_type">
                    <td>{idx}</td>
                    <td>{data.address}</td>
                    <td>{data.centerName}</td>
                    <td>{data.centerType}</td>
                    <td>{data.facilityName}</td>
                    <td>{data.org}</td>
                    <td>{data.sido} {data.sigungu}</td>
                    <td>{data.zipCode}</td>
                </tr>
            )
        }
        return result
    }

    render () {
        return (
            <section class="sub_wrap" >
                <article class="s_cnt mp_pro_li ct1 mp_pro_li_admin">
                    <div class="li_top">
                        <h2 class="s_tit1">코로나19 예방접종센터 정보</h2>
                        {/* api 상세 : https://www.data.go.kr/tcs/dss/selectApiDataDetailView.do?publicDataPk=15077586 */}
                    </div>
                    <div class="list_cont list_cont_admin">
                        <table class="table_ty1 fp_tlist">
                            <tr>
                                <th>Row</th>
                                <th>주소</th>
                                <th>센터명</th>
                                <th>센터타입</th>
                                <th>시설명</th>
                                <th>기관명</th>
                                <th>시군구</th>
                                <th>우편번호</th>
                            </tr>
                        </table>	
                        <table class="table_ty2 fp_tlist">
                            {this.state.append_FPList}
                        </table>
                    </div>
                </article>
            </section>
        );
    }
}

export default Vaccination_CenterList;

9. 정상적으로 데이터를 불러왔다면, 아래와 같은 화면을 확인할 수 있다.

https://taling.me/Talent/Detail/19341

 

[비전공자도 가능한 웹 프로젝트] REACTJS NODEJS MYSQL AWS 웹개발 | 탈잉

✔ 수업 목표 & 5주 뒤 결과물 만들고 싶은 서비스를 직접 구현하게 됩니다. 사람들이 방문하고 액션을 할 수 있는 웹 페이지를 제작 & 배포하는 것까지 진행됩니다. 여러분이 개발 경험이 있든

taling.me:443

 

Comments