본문 바로가기
Frontend/Frontend 프로젝트

React App 만들기 - 시계 기능 구현하기

by 천우산__ 2023. 6. 15.

구현이 필요한 기능들

구현한 적 있는 기능

  1. 현재 시간 알려주는 기능 (시계)
  2. 날씨 정보를 반환하는 기능 (API)
  3. 할 일을 등록할 수 있는 기능 (Form)
  4. 할 일 리스트를 보여주는 영역 (Todo-list)
  5. 할 일을 지울 수 있는 기능

새롭게 구현해 보고 싶은 기능

  1. 만다라트 생성
  2. 날씨 현황에 따른 배경화면 이펙트

현재 시간을 반환하는 javascript 내장 함수를 통해 간단하게 구현할 수 있다.

let nowtime = new Data(); // 현재 시간 반환

이 기능을 이용해 아래와 같이 코드를 구성했다.

React 파일 내 자바스크립트 언어 삽입은 { } 안에 넣어주면 된다.

import './App.css';

function App() {
  let clock = new Date(); // 시간 반환

  return (
    <div className="App">
      <h1 className='clockInfo'> { clock } </h1>
    </div>
  );
}

export default App;

이렇게 한 후 화면을 확인해보니 에러가 난다.

무엇이 잘못된 걸까?

에러 메세지를 보니, Objects 타입의 데이터가 들어가서 그런것 같은데, new Date();로 저장한 변수의 타입을 알아보면 다음과 같다.

import './App.css';

function App() {
  let clock = new Date(); // 시간 반환

  return (
    <div className="App">
      <h1 className='clockInfo'> { console.log(typeof clock) } </h1> /* objects 반환 */
    </div>
  );
}

export default App;

저 타입으로 표기하지 못하는 것 같으니, 다른 방법으로 표기할 방법을 찾아보다가 변수 뒤 .toLocaleTimeString() 을 붙여주면

저장된 시간 값을 문자열으로 반환해줄 수 있다는 것을 알게 되어 아래와 같이 표기했다.

import './App.css';

function App() {
  let clock = new Date(); // 시간 반환

  return (
    <div className="App">
      <h1 className='clockInfo'> { clock.toLocaleTimeStirng() } </h1>
    </div>
  );
}

export default App;

정상적으로 표기되는데, '오후' 라는 단어가 붙은 걸로 봐서는 12시간 표기법인 것인 것 같다.

나는 12시간 표기가 아니라 24시로 표기하고 싶어서 아래와 같이 코드를 변경했다.

function App() {
  const nowTime = () => {
    let now = new Date(); // 현재 시간 반환
    let hour = now.getHours(); // 시간 값 저장
    let minute = now.getMinutes(); // 분 값 저장
    let second = now.getSeconds(); // 초 값 저장

    return `${hour} : ${minute} : ${second}` // 시간 정보 합쳐서 반환
  }
  
  return (
    <div className="App">
      <h1 className='clockInfo'> { nowTime } </h1>
      <h3 className='wheaterInfo'> wheater infomation will here</h3>
      <div className='todoList'> todo-list will here</div>
      <form> 
        <input type='text' placeholder='write your todoList'/>
      </form>
    </div>
  );
}

 

이제 원하는 대로 된 것 같다.

원하는 형식으로 표기는 됐지만 시간이 변하는게 표현이 되지 않는다. 주기적으로 (1초 단위) 값을 변경해주고 싶기 때문에

React 에서 제공하는 useState를 이용하여 코드를 추가했다. useState를 이용하면 특정 변수의 값을 다시 세팅할 수 있다.

이 과정에서 변경된 값들만 다시 랜더링 해주기 때문에, 불필요한 요소들의 re-rendering을 막을 수 있는 것 같다.

import './App.css';
import { useState } from 'react';

function App() {
  const nowTime = () => {
    let now = new Date();
    let hour = now.getHours();
    let minute = now.getMinutes();
    let second = now.getSeconds();

    return `${hour} : ${minute} : ${second}`
  }
  
  // useState 이용, 랜더링 후 첫 값은 nowTime return 값 사용
  const [clock, setclock] = useState(nowTime); 
  
  // 1초마다 clock의 값을 다시 계산 후 랜더링 (setClock 이용)
  setInterval(() => setclock(nowTime), 1000);

  return (
    <div className="App">
      <h1 className='clockInfo'> { clock } </h1>
      <h3 className='wheaterInfo'> wheater infomation will here</h3>
      <div className='todoList'> todo-list will here</div>
      <form> 
        <input type='text' placeholder='write your todoList'/>
      </form>
    </div>
  );
}

export default App;

위 코드 순서를 보면, 처음 clock 변수를 세팅할 때, nowTime의 결과인 현재 시간을 반환하고,

1000ms / 1초 마다 nowTime 함수를 재 생성하여 setClock 를 이용, clock 값을 변경한다. 이렇게 하면 내가 원했던 것 처럼1초마다 시간을 다시 가져오기 때문에, 현재 시간을 알기 위해서 새로고침을 할 필요가 없어진다.적용 이후 확인한 결과, 2자리수 단위가 아닐 때 (ex. 10분 미만 or 10초 미만) 앞에 0이 없어진다는 점을 확인했다.이대로 둬도 되지만 그래도 영역을 일정하게 차지하는 것이 보기 좋을 것 같아서 앞에 0을 붙여주기 위해서 시, 분, 초 단위의 type을 검사해보니Number 형식으로 나왔다. 이렇게 되면 앞에 0을 붙인다고 해도 자동으로 생략되므로, 문자열로 바꾼 후, 2자리로 반환하되,2자리가 되지 않으면 왼쪽부터 0으로 채워주는 방식으로 변경했다.

// 수정 후 코드

import './App.css';
import { useState } from 'react';

function App() {
  const nowTime = () => {
    let now = new Date();
    let hour = String(now.getHours()).padStart(2, "0"); // 수정됨
    let minute = String(now.getMinutes()).padStart(2, "0"); // 수정됨
    let second = String(now.getSeconds()).padStart(2, "0"); // 수정됨
    
    return `${hour} : ${minute} : ${second}`
  }
  const [clock, setclock] = useState(nowTime);
  setInterval(() => setclock(nowTime), 1000);

  return (
    <div className="App">
      <h1 className='clockInfo'> { clock } </h1>
      <h3 className='wheaterInfo'> wheater infomation will here</h3>
      <div className='todoList'> todo-list will here</div>
      <form> 
        <input type='text' placeholder='write your todoList'/>
      </form>
    </div>
  );
}

export default App;

위의 작업까지 마치고 확인해보니 내가 원했던 형식으로 데이터가 보이는 것이 확인되었다.

어느 정도 성공?

화면을 계속 보고있다 보니, 0으로 표기될 때 텍스트가 불규칙적으로 흔들리는 현상을 확인했는데,

이 부분은 추후에 보완하기로 하고 일단 다음 단계로 넘어가자.