임송재 - chungstar/hansei-study2 GitHub Wiki

github 사용법

  • git 설치 및 환경설정

    • Git 설치하기 : https://git-scm.com/
    • 설치 완료 후 Git bash 열기
    • git bash에서 환경설정하기
      • Step 1: 유저 이름 설정 ex) git config --global user.name "Songjae Lim"
      • Step 2: 유저 이메일 설정 ex) git config --global user.email "[email protected]"
      • Step 3: 정보 확인하기 ex) git config --list
  • Github에 코드 업로드

    1. 초기화 : git init
    2. 추가할 파일 더하기 : git add .
    3. 히스토리 만들기 ex) git commit -m "first history"
    4. Github repository와 내 로컬 프로젝트랑 연결 ex) git remote add origin [email protected]:LimSongJae/Blog.git
    5. 잘 연결됐는지 확인 : git remote -v
    6. Github로 올리기 : git push origin master -> master 자리에는 branch이름이 들어가면 된다. ex) branch 이름이 help라 하면 git push origin help 라고 써야함.
  • Github에 계속 업데이트 하는 법

    1. 추가할 파일 더하기 : git add .
    2. 히스토리 만들기 ex) git commit -m "first commit"
    3. Github로 올리기 : git push origin master
  • Github로 팀프로젝트 하는 법

    1. Github에서 소스코드 다운로드 : git clone 주소 폴더이름
      • 주소는 깃허브에서 들고와야 함
      • 폴더이름은 선택사항이다. 폴더이름을 줄 경우에는 그 폴더가 새로 생성이 되면서 그 안에 코드들이 다운로드가 되고 폴더이름을 안 줄 경우엔 깃허브 프로젝트 이름으로 폴더가 자동으로 생기고 그 안에 코드들이 다운로드 됨.
    2. Github에서 내 브렌치(branch) 만들기 : git checkout -b 브렌치이름
    3. 내 브렌치에 소스코드 업데이트하기
      • git add .
      • git commit -m "first commit"
      • git push origin 브렌치이름
    4. 마스터 브렌치에 소스 가져오기 (Pull) : git pull origin master
      • pull을 하기전에는 기존에 소스코드들을 commit을 먼저 해놔야 한다.
      • 자기가 하던 코드들을 날리지 않기 위해서 commit을 한다. !
    5. 브렌치끼리 이동하는 법 : git checkout 브렌치이름

블로그

관심사에 따라 자유롭게 글을 올릴 수 있는 웹 사이트

  • 가입형 블로그

    • 가입형 블로그는 회원 가입만 하면 손쉽게 블로그를 생성할 수 있다. 포털, 신문사, 인터넷 서점, 블로그 전문 웹사이트 등이 블로그 서비스를 제공한다. HTML, CSS를 고칠 수 있는 곳도 있고 없는 곳도 있다.
  • 설치형 블로그

    • 설치형 블로그는 서버에 블로그 저작 소프트웨어를 설치해서 운영할 수 있다. 서버의 다른 공간에 위키나 게시판을 운영할 수도 있고 플러그인 등을 사용할 수도 있다. 서버 컴퓨터를 운영하거나 웹호스팅을 해야 한다. 그래서 별도의 비용이 생기며, 컴퓨터, 네트워크 지식이 필요하다. 설치형 블로그 소프트웨어로 텍스트큐브, 워드프레스, 텍스타일, 무버블 타입 등이 있다.

블로그 웹 프레임워크

대표적으로 N블로그, 티스토리, 워드프레스가 있다. 블로그에 필요한 기능들이 어느 정도 구현되어 있다. 예외적으론 React 기반의 Gatsbyjs가 있다. 데이터접근은 GraphQL, UI는 React 컴포넌트로 구성되어 있다. Gatsbyjs는 일일이 기능을 다 구현해야 함으로 많은 시간과 노력이 필요한 것으로 보인다.

  1. 검색측면 : N블로그 > 티스토리 > 워드프레스
  2. 업체홍보/브랜드화 측면 : N블로그 > 티스토리 > 워드프레스
  3. 개설 비용 측면 : N블로그 = 티스토리 > 워드프레스(유료)
  4. 유지 관리 : N블로그 = 티스토리 > 워드프레스(유료)
  5. 디자인 측면(자율성): 워드프레스 > 티스토리 > N블로그
    • html, css, js을 조금은 다줄 줄 알아야 함 !
  6. 글쓰기 에디터 편리성: N블로그 = 티스토리 > 워드프레스
  7. 광고 수익면 : 티스토리 >= 워드프레스 > 블로그

비용이 안 들고 디자인하기도 비교적 편한 티스토리를 이용하여 블로그 개발을 하는 것이 좋아 보인다.

(1월 9일) 추가 : Bootstrap도 하나의 선택지가 될 수 있다.

Bootstrap

  • 프론트엔드 개발을 빠르고 쉽게 할 수 있는 프레임워크
  • HTML, CSS 기반의 템플릿 양식, 버튼, 네비게이션 및 기타 페이지를 구성하는 요소 포함
  • 자바스크립트를 선택적으로 확장 할 수 있음
  • Github의 오픈 소스로 사용 가능. 상업적 이용 가능
  • 부트스트랩을 사용하면 코딩량을 줄여 개발시간도 줄어들고 디자인도 깔끔하게 제작이 가능하다.
  • 부트스트랩 사용방법
    • CDN 방식으로 링크
    • 다운로드

SPA(Single Page Application) 프레임워크

대표적인 3가지 : Angular React Vue

최초 브라우저에 로드되고 나서 또 페이지 전체를 서버에 요청하는 것이 아닌 일단 최초에 한번 페이지 전체를 로딩한 이후부터는 단지 그 내부의 데이터만 변경해서 사용할 수 있는 모바일 네이티브 앱과 유사한 사용성을 제공하는 웹 애플리케이션

React

  • 웹 프레임워크로, 자바스크립트 라이브러리의 하나로서 사용자 인터페이스를 만들기 위해 사용된다.
  • React는 facebook에서 제공해주는 프론트엔드 라이브러리라고 볼 수 있다.
  • 싱글 페이지 애플리케이션이나 모바일 애플리케이션의 개발 시 토대로 사용될 수 있다.
  • 현재 많이 활용되고 있는 웹/앱의 View를 개발할 수 있도록 하는 인기있는 라이브러리다.

특징

  • Data Flow : 데이터의 흐름이 한 방향으로만 흐르는 단방향 데이터 흐름을 가진다.

  • Component 기반 구조

    • Component는 독립적인 단위의 소프트웨어 모듈을 말한다. 즉, 소프트웨어를 독립적인 하나의 부품으로 만드는 방법이라고 볼 수 있다.
    • React는 UI(View)를 여러 컴포넌트(component)를 쪼개서 만든다. 한 페이지 내에서도 여러 각 부분을 독립된 컴포넌트로 만들고, 이 컴포넌트를 조립해 화면을 구성한다.
    • 컴포넌트 단위로 쪼개져 있기 때문에, 전체 코드를 파악하기가 상대적으로 쉽다.
    • 기능 단위, UI 단위로 캡슐화시켜 코드를 관리하기 때문에 재사용성이 높다. 따라서 코드는 반복해 입력할 필요 없이 컴포넌트만 import해 사용하면 된다는 간편함이 있으며 애플리케이션이 복잡해지더라도 코드의 유지보수, 관리가 용이해지는 장점을 가진다.
  • Virtual Dom

  • Props and State

    • Props

      Props란 부모 컴포넌트에서 자식 컴포넌트로 전달해 주는 데이터를 말한다. 자식 컴포넌트에서 전달받은 props는 변경이 불가능하고 props를 전달해준 최상위 부모 컴포넌트만 props를 변경할 수 있다. JSX 문법 (JS + HTML) 중 하나이다.

    • State

      State는 컴포넌트 내부에서 선언하며 내부에서 값을 변경할 수 있다. state는 동적인 데이터를 다룰 때 사용하며 사용자와의 상호작용을 통해 데이터를 동적으로 변경할 때 사용한다. 클래스형 컴포넌트에서만 사용할 수 있고 각각의 state는 독립적이다. 함수형 컴포넌트에선 hook이라는 문법을 사용한다.

  • JSX

Javascript를 확장한 문법이다. JS + HTML이라고 생각하면 된다.

Firebase

백엔드 프레임워크로 서버를 따로 개발하지 않아도 이 프레임워크가 서버 역할을 해준다.

  • 장점

    • HTML, CSS, JS만 알아도 서비스 제작 가능.
    • Database 콘솔같은걸 다루기가 쉬움.
    • 프로젝트가 커지면 서버/DB 스케일업을 자동으로 해줌.
    • DB 데이터가 알아서 리얼타임으로 싱크해줌.
  • 단점

    • 보안에 취약하다.
    • 비싸다.

데스크탑+모바일 홈 화면 파트 구현





게시물 만든 시간 관련 핵심 코드

  • 변수 strPeriod는 msec로 받은 현재 시간 Date.now()와 필드값으로 만든 게시물의 시간 docID를 정수로 바꿔서 뺀 값이다.
  • 즉 strPeriod는 게시물을 만들고 난 뒤의 시간을 msec로 표현한 값이다.
  • 이걸 이용해 년, 월, 일, 초를 구할 수 있었다.
const timeFunc = (i) => {
      let strPeriod = Date.now() - parseInt(i);
      let strDay = 24 * 60 * 60 * 1000; // msec

      let pDay = strPeriod / strDay;
      strDay = parseInt(pDay);

      let pHour = (pDay - strDay) * 24;
      let strHour = Math.floor(pHour);

      let pMinute = (pHour - strHour) * 60;
      let strMinute = Math.floor(pMinute);

      let pSecond = (pMinute - strMinute) * 60;
      let strSecond = Math.floor(pSecond);

      let time = "";
      if (strDay != 0) {
        time += strDay + "일 ";
      }
      console.log("time is ", time);
      if (strHour !== 0) {
        time += strHour + "시간 ";
      }
      if (strMinute !== 0) {
        time += strMinute + "분 ";
      }
      if (strSecond !== 0) {
        time += strSecond + "초 전";
      }
      return time;
    };

매뉴바 눌렀을 때 모습



매뉴바 안에 있는 날짜별 댓글수 통계 관련 핵심 코드

  • firebase에 있는 firestore에 필드값 month와 date가 각각 조건에 맞는 문서들을 먼저 추린다
  • 그 추린 문서들의 필드값 commentNumber를 다 더하여 html에 있는 span태그의 스타일 height값을 score값으로 변경시켜준다.
  • 각 막대기 즉 각 span태그마다 각각의 날짜의 댓글값들을 가져와서 스타일 height값을 score값으로 변경시켜주어 통계표를 완성시켰다.
// 통계표
      const first = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() - 5 + "일");
      first
        .get()
        .then((res) => {
          let score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect1 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

      const second = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() - 4 + "일");
      second
        .get()
        .then((res) => {
          score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect2 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

      const third = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() - 3 + "일");
      third
        .get()
        .then((res) => {
          score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect3 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

      const fourth = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() - 2 + "일");
      fourth
        .get()
        .then((res) => {
          score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect4 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

      const fiveth = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() - 1 + "일");
      fiveth
        .get()
        .then((res) => {
          score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect5 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

      const sixth = db
        .collection("post")
        .where("month", "==", i.getMonth() + 1 + "월")
        .where("date", "==", i.getDate() + "일");
      sixth
        .get()
        .then((res) => {
          score = 0;
          res.forEach((i) => {
            score += i.data().commentNumber;
          });

          document.querySelector(".rect6 span").style.height = score + "%";
        })
        .catch((error) => {
          console.log("Error getting documents: ", error);
        });

모바일화면에서 정렬을 리스트 형식으로 했을 때 모습



주요 코드

const list = document.querySelector('.fa-list');
const line = document.querySelector('.fa-grip-lines');

list.addEventListener('click', () => {
	$('.mobile-box').css('display', 'block');
	$('.wrapper').css('display', 'none');
});

line.addEventListener('click', () => {
	$('.mobile-box').css('display', 'none');
	$('.wrapper').css('display', 'flex');
});

모바일화면에서 정렬을 인기순으로 했을 때 모습

인기정렬 관련 핵심 코드

  • recent.addEventListener("click", () => { 처럼 버튼을 클릭하면 발생하게 이벤트를 작성한다.
  • firebase에 있는 firestore에 'post'컬렉션에 접근한다.
  • 좋아요 순으로 문서들을 내림차순으로 정렬한다. 이 때 우리가 정한 필드값 'like'순으로 재나열했다.
  • 기존의 쓰여있던 HTML을 innerHTML 문법을 이용하여 공백화한다.
  • 좋아요 순으로 정렬된 문서들을 순서대로 읽어 다시 HTML을 자바스크립트를 써서 append한다.
  • 이 때 append하는 HTML 내용은 백픽을 이용하여 변수에 저장하여 변수를 append하는 방식이다.
  // 인기순 정렬
const Auth = firebase.auth();
const db = firebase.firestore();
const postsRef = db.collection("post");
const recent = document.querySelector(".recent");
const popular = document.querySelector(".popular");
const normal = document.querySelector(".normal");

    popular.addEventListener("click", () => {
      postsRef
        .orderBy("like", "desc")
        .get()
        .then((결과) => {
          document.querySelector(".wrapper").innerHTML = ``; // 공백화
          document.querySelector(".mobile-box").innerHTML = ``; // 공백화
          결과.forEach((i) => {
            const post = `
            <div class="main-box">
              <div class="info">
                <img src="${writerImage}" />
                <div class="nickname">
                  <p class="name">${userName}</p>
                  <p class="timer">${timeFunc(i.data().docId)}</p>
                </div>
              </div>
              <div class="title ">
                <h1><a href="./post.html?id=${i.data().docId}">${
                i.data().title
              }</a></h1>
                <ul class="hashtag">
                  <li><a href="#">${i.data().hashtag}</a></li>
               </ul>
              </div>
              <div class="content">
                <div class="greeting">
                  <p>${i.data().text}</p>
                </div>
                <img src="${i.data().firstImage}" />
              </div>
            </div>`;

            const MobileClick = `
            <div class="mobile-wrapper">
              <div class="mobile-main-box">
                <div><a href="./post.html?id=${i.data().docId}">${
                i.data().title
              }</a></div>
                <div>${i.data().hashtag}</div>
                <div>${timeFunc(i.data().docId)}</div>
                <div>
                  <i class="fas fa-heart"></i> ${i.data().like}
                  <i class="far fa-comment-dots"> ${i.data().commentNumber} </i>
                </div>
              </div>
              <div class="mobile-side-box"><img src="${
                i.data().imageUrl
              }" /></div>
            </div>`;

            $(".wrapper").append(post);
            $(".mobile-box").append(MobileClick);
          });
        });
    });

모바일화면에서 정렬을 최신순으로 했을 때 모습

최신순 정렬 관련 핵심 코드

  • recent.addEventListener("click", () => { 처럼 버튼을 클릭하면 발생하게 이벤트를 작성한다.
  • firebase에 있는 firestore에 'post'컬렉션에 접근한다.
  • 시간 순으로 문서들을 내림차순으로 정렬한다. 이 때 우리가 정한 필드값 'docID'를 이용했다.
  • 기존의 쓰여있던 HTML을 innerHTML 문법을 이용하여 공백화한다.
  • 시간 순으로 정렬된 문서들을 순서대로 읽어 다시 HTML을 자바스크립트를 써서 append한다.
  • 이 때 append하는 HTML 내용은 백픽을 이용하여 변수에 저장하여 변수를 append하는 방식이다.
   // 최신순 정렬
const Auth = firebase.auth();
const db = firebase.firestore();
const postsRef = db.collection("post");
const recent = document.querySelector(".recent");
const popular = document.querySelector(".popular");
const normal = document.querySelector(".normal");
    recent.addEventListener("click", () => {
      postsRef
        .orderBy("docId", "desc")
        .get()
        .then((결과) => {
          document.querySelector(".wrapper").innerHTML = ``; // 공백화
          document.querySelector(".mobile-box").innerHTML = ``; // 공백화
          결과.forEach((i) => {
            const post = `
            <div class="main-box">
              <div class="info">
                <img src="${i.data().writerImage}" />
                <div class="nickname">
                  <p class="name">${i.data().writer}</p>
                  <p class="timer">${timeFunc(i.data().docId)}</p>
                </div>
              </div>
              <div class="title">
                <h1><a href="./post.html?id=${i.data().docId}">${
                i.data().title
              }</a></h1>
                <ul class="hashtag">
                  <li><a href="#">${i.data().hashtag}</a></li>
               </ul>
              </div>
              <div class="content">
                <div class="greeting">
                  <p>${i.data().text}</p>
                </div>
                <img src="${i.data().firstImage}" />
              </div>
            </div>`;

            const MobileClick = `
            <div class="mobile-wrapper">
              <div class="mobile-main-box">
                <div><a href="./post.html?id=${i.data().docId}">${
                i.data().title
              }</a></div>
                <div>${i.data().hashtag}</div>
                <div>${timeFunc(i.data().docId)}</div>
                <div>
                  <i class="fas fa-heart"></i> ${i.data().like}
                  <i class="far fa-comment-dots"> ${i.data().commentNumber} </i>
                </div>
              </div>
              <div class="mobile-side-box"><img src="${
                i.data().imageUrl
              }" /></div>
            </div>`;

            $(".wrapper").append(post);
            $(".mobile-box").append(MobileClick);
          });
        });
    });

index 화면 관련 모든 코드

  <header>
    <div class="MenuButton">
      <input type="checkbox" id="menuicon" />
      <label for="menuicon">
        <span></span>
        <span></span>
        <span></span>
      </label>
      <div class="sidebar">
        <div class="sidebar-box1">
          <button id="logInBtn">Google 로그인</button>
          <div id="Myinfo">
            <p class="nickname"></p>
          </div>
          <button id="logOutBtn" style="display: none; margin-left: auto">
            로그아웃
          </button>
        </div>

        <ul class="sidebar-box2">
          <li>
            <a href="#"><i class="far fa-bell"></i></a>내소식
          </li>
          <li>
            <a href="#"><i class="fas fa-child"></i></a>이웃목록
          </li>
          <li>
            <a href="#"><i class="fas fa-chart-line"></i></a>통계
          </li>
          <li>
            <a href="write.html"><i class="fas fa-pen"></i></a>글쓰기
          </li>
        </ul>

        <div class="sidebar-box3">
          <div>
            <span>날짜별 댓글수</span>
            <span class="date"></span>
            <script>
              let i = new Date();
              let date = i.getMonth() + 1 + "월 " + i.getDate() + "일";
              document.querySelector(".date").innerHTML = date;
              console.log(date)
            </script>
          </div>
            <ul class="graph">
              <li>
                <div class="rect1">
                  <span></span>
                </div>
                <p id="one"></p>
                <script>
                  i = new Date();
                  date = i.getMonth() + 1 + "월 " + (i.getDate() - 5) + "일";
                  document.querySelector("#one").innerHTML = date;
                </script>
              </li>
              <li>
                <div class="rect2">
                  <span></span>
                </div>
                <p id="two"></p>
                <script>
                  date = i.getMonth() + 1 + "월 " + (i.getDate() - 4) + "일";
                  document.querySelector("#two").innerHTML = date;
                </script>
              </li>
              <li>
                <div class="rect3">
                  <span></span>
                </div>
                <p id="three"></p>
                <script>
                  date = i.getMonth() + 1 + "월 " + (i.getDate() - 3) + "일";
                  document.querySelector("#three").innerHTML = date;
                </script>
              </li>
              <li>
                <div class="rect4">
                  <span></span>
                </div>
                <p id="four"></p>
                <script>
                  date = i.getMonth() + 1 + "월 " + (i.getDate() - 2) + "일";
                  document.querySelector("#four").innerHTML = date;
                </script>
              </li>
              <li>
                <div class="rect5">
                  <span></span>
                </div>
                <p id="five"></p>
                <script>
                  date = i.getMonth() + 1 + "월 " + (i.getDate() - 1) + "일";
                  document.querySelector("#five").innerHTML = date;
                </script>
              </li>
              <li>
                <div class="rect6">
                  <span></span>
                </div>
                <p id="six"></p>
                <script>
                  date = i.getMonth() + 1 + "월 " + i.getDate() + "일";
                  document.querySelector("#six").innerHTML = date;
                </script>
              </li>
            </ul>
          </div>

        <div class="sidebar-box4">
          <ul>
            <a href="#">
              <li><i class="fas fa-desktop"></i>내 동영상</li>
            </a>
            <a href="#">
              <li><i class="fas fa-bolt"></i>내 모먼트</li>
            </a>
            <a href="#">
              <li><i class="far fa-clock"></i>지난 오늘 글</li>
            </a>
          </ul>
          <ul>
            <a href="#">
              <li><i class="fas fa-box"></i>마켓 플레이스</li>
            </a>
            <a href="#">
              <li><i class="fas fa-box-open"></i>마켓 구매내역</li>
            </a>
          </ul>
          <ul>
            <a href="#">
              <li><i class="fas fa-blog"></i>블로그 홈</li>
            </a>
            <a href="#">
              <li><i class="fab fa-blogger"></i>블로그팀 공식블로그</li>
            </a>
            <a href="#">
              <li><i class="fab fa-microblog"></i>이달의 블로그</li>
            </a>
            <a href="#">
              <li><i class="fas fa-check"></i>공식 블로그</li>
            </a>
          </ul>
        </div>
        <div class="sidebar-box5">
          <ul>
            <a href="#">
              <li>공지사항</li>
            </a>
            <a href="#">
              <li>환경설정</li>
            </a>
            <ul>
              <a href="#">
                <li>로그인정보</li>
              </a>
              <li>songjae99</li>
            </ul>
            <a href="#">
              <li>PC버전으로 보기</li>
            </a>
            <a href="#">
              <li>블로그 고객센터</li>
            </a>
          </ul>
        </div>
      </div>
    </div>
    <div class="mobile-searching">
      <a href="search.html"><i class="fas fa-search"></i> </a>
    </div>
    <div class="blogname">MBTI과몰입 인간의 블로그</div>
    <div class="mobile-category">
      <input type="checkbox" id="category" />
      <label for="category">
        <img src="image/fa-regular_list-alt.png" />
      </label>
      <div>
        <div>
          <label for="category">
            <i class="fas fa-times"></i>
          </label>
          카테고리
        </div>
        <ul>
          <li><a href="#">전체글</a><span>6</span></li>
          <li><a href="#">주절주절 감성글</a><span>2</span></li>
          <li><a href="#">맛집 로그들</a><span>4</span></li>
          <li><a href="#">여행 로그들</a><span>0</span></li>
          <li><a href="#">이도저도 아님..</a><span>3</span></li>
          <li><a href="#">읽기</a><span>2</span></li>
          <li><a href="#">메모글</a><span>1</span></li>
        </ul>
      </div>
    </div>
    <div class="icons">
      <a href="search.html"><i class="fab fa-sistrix"></i></a>
    </div>
  </header>

  <!-- 모바일 전용 정렬 방법 -->
  <div class="range">
    <div>
      <span class="normal">전체글</span> <span class="popular">인기순</span>
      <span class="recent">최신순</span>
    </div>
    <div class="range-icon">
      <i class="fas fa-list"></i><i class="fas fa-grip-lines"></i>
    </div>
  </div>
  <script type="text/javascript" src="range.js"></script>

  <div class="wrapper">
    <!-- <div class="main-box">
      <div class="info">
        <img src="image/ticket.jpg" />
        <div class="nickname">
          <p class="name">집사는 괴로워</p>
          <p class="timer">2시간 전</p>
        </div>
      </div>
      <hr>
      <div class="title">
        <h1><a href="write.html">고양이 두부모래 추천!</a></h1>
        <ul class="hashtag">
          <li><a href="#">#고양이</a></li>
          <li><a href="#">#집사</a></li>
          <li><a href="#">#두부모래</a></li>
          <li><a href="#">#쿠팡</a></li>
          <li><a href="#">#내돈내산</a></li>
        </ul>
      </div>
      <div class="content">
        <div class="greeting">
          <span>안녕하세요 !!</span>
          <span>집사는 괴로워입니다:)</span>
          <span>날씨가 추워지는 요즘 잘 지내고 계신가요?</span>
        </div>
        <img src="image/5.jpg" />
      </div>
    </div> -->
  </div>

  <div class="mobile-box">
    <!-- <div class="mobile-wrapper">
        <div class="mobile-main-box">
          <div>고양이 두부모래 추천</div>
          <div>#고양이 #집사 #두부모래 #쿠팡 #내돈내산</div>
          <div>2021.12.24</div>
          <div>
            <i class="fas fa-heart"></i> 1
            <i class="far fa-comment-dots"> 45 </i>
          </div>
        </div>
        <div class="mobile-side-box"><img src="image/5.jpg" /></div>
      </div> -->
  </div>
* {
	margin: 0;
	padding: 0;
	box-sizing: border-box;
}
body {
	background: #e5e5e5;
}
header {
	display: flex;
	justify-content: space-between;
	padding: 25px 60px;
	align-items: center;
	background: #fff;
	/* background-color: #c4c4c4; */
	position: relative;
}
header .mobile-searching {
	font-size: 30px;
	display: none;
}
header .mobile-searching a {
	text-decoration-color: none;
	color: black;
}
header .mobile-category {
	display: none;
}
header .mobile-category img {
	height: 30px;
	width: 30px;
}
header .mobile-category input {
	display: none;
}

header .mobile-category label:active {
	transform: translate(5%, 5%);
}
header .mobile-category label:hover {
	color: #27a3ca;
	cursor: pointer;
}
header .mobile-category > input:checked + label + div {
	display: block;
}
header .mobile-category label + div > div {
	border-bottom: 1px solid #c4c4c4;
	display: flex;
	align-items: center;
	padding: 4px 15px;
	font-weight: 900;
	font-size: 20px;
}
header .mobile-category label + div > div .fas {
	font-size: 25px;
	padding: 10px 10px;
	margin-right: 10px;
}
header .mobile-category label + div ul {
	list-style: none;
	padding: 0px 10px;
}
header .mobile-category label + div ul li {
	display: flex;
	padding: 10px 0px;
	justify-content: space-between;
	border-bottom: 0.5px solid #c4c4c4;
}
header .mobile-category label + div ul li:hover {
	font-weight: 900;
}
header .mobile-category label + div ul li a {
	text-decoration: none;
	color: black;
}
header .mobile-category label + div ul li:nth-child(1),
header .mobile-category label + div ul li:nth-child(7) {
	border-bottom: 0.5px solid gray;
}
header .blogname {
	font-size: 30px;
	font-weight: 900;
	font-family: inherit;
	overflow: hidden;
	white-space: nowrap;
	text-overflow: ellipsis;
	position: absolute;
	left: 50%;
	top: 50%;
	transform: translate(-50%, -50%);
}
header .blogname a {
	text-decoration: none;
	color: #000;
}
header .icons {
	font-size: 30px;
	display: flex;
	align-items: center;
	position: relative;
}
header .icons a {
	text-decoration-color: none;
	color: black;
}
/* header .icons .fab {
	position: absolute;
	top: 5px;
	right: 4px;
}
header .icons input {
	height: 35px;
	border: 3px solid black;
	font-size: 14px;
} */
.range {
	display: none;
	justify-content: space-between;
	align-items: center;
	width: 100%;
	padding: 4px 37px;
	border-bottom: 0.5px solid #f2f3f4;
	font-family: 'inherit';
	font-size: 14px;
}
.range span:hover {
	font-weight: 900;
	cursor: pointer;
}
.range .range-icon i {
	border-radius: 100%;
	padding: 10px 10px;
}
.range .range-icon i:hover {
	cursor: pointer;
	background-color: #979797;
}

.wrapper {
	display: flex;
	justify-content: space-evenly;
	animation: motion 1s ease-out;
	flex-wrap: wrap;
	margin-top: 30px;
}
.wrapper .main-box {
	width: 80%;
	background-color: #fff;
	padding: 15px 20px 90px 20px;
	margin-bottom: 40px;
}
.wrapper .main-box:hover {
	cursor: pointer;
}
.wrapper .main-box .info {
	padding-bottom: 15px;
	display: flex;
}
.wrapper .main-box .info img {
	width: 60px;
	height: 70px;
	border-radius: 70%;
}
.wrapper .main-box .info .nickname {
	padding-top: 5px;
	padding-left: 5px;
}
.wrapper .main-box .info .nickname .name {
	font-weight: 900;
}
.wrapper .main-box .info .nickname .timer {
	margin-top: 11px;
	font-size: 9px;
	color: #979797;
}
.wrapper .main-box .title {
	margin-bottom: 55px;
}
.wrapper .main-box .title .hashtag {
	list-style: none;
	display: flex;
}
.wrapper .main-box .title .hashtag a {
	text-decoration: none;
	color: #27a3ca;
}
.wrapper .main-box .title .hashtag li {
	margin-right: 5px;
	font-size: 12px;
}
.wrapper .main-box .title h1 {
	margin-top: 20px;
	margin-bottom: 20px;
}
.wrapper .main-box .title a {
	text-decoration: none;
	color: black;
}
.wrapper .main-box .content {
	text-align: center;
}
.wrapper .main-box .content .greeting {
	display: flex;
	flex-direction: column;
	text-align: center;
	margin-bottom: 50px;
	font-size: 13px;
	font-family: Arial, Helvetica, sans-serif;
}
.wrapper .main-box .content .greeting p {
	width: 60%;
	margin: auto auto;
}
.wrapper .main-box .content img {
	width: 40%;
}

.wrapper .side-box {
	width: 10%;
}
.wrapper .side-box .writer {
	width: 100%;
	height: 60px;
	background-color: #979797;
	text-align: center;
	font-size: 20px;
	font-weight: 900;
	border: 1px solid black;
	margin-bottom: 13px;
}
.wrapper .side-box .writer:hover {
	cursor: -webkit-grab;
}
.wrapper .side-box .writer:active {
	transform: translate(5%, 5%);
}
.wrapper .side-box .writer span {
	line-height: 54px;
}
.wrapper .side-box .advertise img {
	width: 100%;
	height: 300px;
	animation: motion 5s ease-out;
	margin-bottom: 13px;
}
.wrapper .side-box .advertise img:hover {
	cursor: -webkit-grab;
}
@keyframes motion {
	from {
		opacity: 0;
	}
	to {
		opacity: 1;
	}
}
.wrapper .side-box .alert {
	text-align: center;
	margin-bottom: 13px;
	animation: motion 5s ease-out;
	height: 300px;
	background-color: #c4c4c4;
}
.wrapper .side-box .alert h2 {
	background-color: #c4c4c4;
	padding-bottom: 10px;
	padding-top: 10px;
}
.wrapper .side-box .alert .alert-list {
	width: 100%;
	display: flex;
	justify-content: center;
	list-style: none;
	background-color: #d8d8d8;
}
.wrapper .side-box .alert .alert-list li {
	width: 33%;
}
.wrapper .side-box .alert .alert-list button {
	width: 100%;
}
.wrapper .side-box .alert .alert-list li button:hover {
	background-color: #86888a;
}
.wrapper .side-box .alert .alert-content {
	width: 100%;
	height: 185px;
	background-color: #d8d8d8;
}
.wrapper .side-box .visitor {
	text-align: center;
	background-color: #c4c4c4;
	animation: motion 5s ease-out;
}
.wrapper .side-box .visitor h3 {
	padding-top: 25px;
}
.wrapper .side-box .visitor h2 {
	padding-bottom: 25px;
}
.wrapper .side-box .visitor .visitor-list {
	list-style: none;
}
.wrapper .side-box .visitor li {
	display: flex;
	align-items: center;
	justify-content: space-evenly;
	padding-top: 5px;
	padding-bottom: 5px;
}
.wrapper .side-box .visitor li img {
	width: 40px;
	height: 40px;
	border-radius: 70%;
}
.wrapper .side-box .visitor #plus {
	position: relative;
	bottom: 12px;
	left: 41px;
	color: #979797;
	text-decoration: none;
	font-size: 9px;
}

.mobile-box {
	display: none;
	width: 80%;
	margin: 0 auto;
	background: #fff;
}
.mobile-wrapper {
	margin: 30px 0;
	height: 200px;
	display: flex;
	flex-wrap: wrap;
	padding: 30px 20px;
	border-bottom: 0.5px solid gray;
}
.mobile-wrapper:hover {
	cursor: pointer;
}
.mobile-wrapper .mobile-main-box {
	width: 70%;
}
.mobile-wrapper .mobile-main-box a {
	text-decoration: none;
	color: black;
}
.mobile-wrapper .mobile-main-box div:nth-child(1) {
	font-weight: 900;
	margin-bottom: 12px;
	font-size: 26px;
}
.mobile-wrapper .mobile-main-box div:nth-child(2) {
	color: #27a3ca;
	font-size: 12px;
	margin-bottom: 28px;
}
.mobile-wrapper .mobile-main-box div:nth-child(3),
.mobile-wrapper .mobile-main-box div:nth-child(4) {
	font-size: 12px;
	color: gray;
	margin-bottom: 3px;
}
.mobile-wrapper .mobile-side-box {
	width: 30%;
	height: 100%;
}
.mobile-wrapper .mobile-side-box img {
	width: 100%;
	height: 100%;
	border-radius: 30%;
}
#menuicon {
	display: none;
}
#menuicon + label {
	display: block;
	width: 30px;
	height: 25px;
	position: relative;
	cursor: pointer;
}
#menuicon + label > span {
	display: block;
	position: absolute;
	width: 100%;
	height: 5px;
	border-radius: 30px;
	background: #000;
	transition: all 0.35s;
}
#menuicon + label span:nth-child(1) {
	top: 0;
}
#menuicon + label span:nth-child(2) {
	top: 50%;
	transform: translateY(-50%);
}
#menuicon + label span:nth-child(3) {
	bottom: 0;
}

#menuicon:checked + label span:nth-child(1) {
	top: 50%;
	transform: translateY(-50%) rotate(45deg);
	z-index: 2;
}
#menuicon:checked + label span:nth-child(2) {
	z-index: 2;
	opacity: 0;
}
#menuicon:checked + label span:nth-child(3) {
	z-index: 2;
	bottom: 50%;
	transform: translateY(50%) rotate(-45deg);
}
#menuicon:checked + label + div {
	opacity: 1;
	left: 0;
}

.sidebar {
	width: 320px;
	height: 1800px;
	background: white;
	position: absolute;
	top: 85px;
	left: -300px;
	z-index: 1;
	opacity: 0;
	transition: all 0.35s;
	display: flex;
	flex-direction: column;
}
.sidebar a {
	text-decoration: none;
	color: black;
}
.sidebar ul {
	list-style: none;
}
.sidebar .sidebar-box1 {
	display: flex;
	padding: 16px 13px;
	border-bottom: 2px solid gray;
	align-items: center;
}
.sidebar .sidebar-box1 .far {
	font-size: 34px;
	margin-right: 5px;
}
.sidebar .sidebar-box1 .Myinfo p:nth-child(2) {
	color: #979797;
	font-size: 12px;
}
.sidebar .sidebar-box1 button {
	background: #fff;
	border: none;
	font-size: 15px;
	font-weight: bold;
}
.sidebar .sidebar-box1 button#logInBtn {
	margin: auto;
	width: 100%;
	height: 100%;
}
.sidebar .sidebar-box1 button:hover {
	cursor: pointer;
}
.sidebar .sidebar-box2 {
	display: flex;
	padding: 16px 13px;
	border-bottom: 2px solid gray;
	align-items: center;

	justify-content: space-evenly;
}
.sidebar .sidebar-box2 li {
	display: flex;
	flex-direction: column;
	align-items: center;
}
.sidebar .sidebar-box2 li i {
	padding: 15px 15px;
	border-radius: 100%;
	background-color: blanchedalmond;
}
.sidebar .sidebar-box3 {
	padding: 16px 13px;
	border-bottom: 2px solid gray;
	display: flex;
	flex-direction: column;
}
.sidebar .sidebar-box3 > div {
	display: flex;
	justify-content: space-between;
	margin-bottom: 20px;
}
.sidebar .sidebar-box3 > div span:nth-child(1) {
	font-weight: 900;
	font-size: 14px;
}
.sidebar .sidebar-box3 > div span:nth-child(2) {
	color: #979797;
	font-size: 12px;
}
.sidebar .sidebar-box3 .graph {
	/* position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%); */
	display: flex;
}
.sidebar .sidebar-box3 .graph li {
	padding: 0 5px;
	text-align: center;
	font-size: 11px;
}
.sidebar .sidebar-box3 .graph li div {
	position: relative;
	width: 4px;
	height: 150px;
	border-radius: 4px 4px 0 0;
	margin: 0 auto;
}
.sidebar .sidebar-box3 .graph li div span {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	background-color: #5e86ff;
	border-radius: 4px 4px 0 0;
}
.sidebar-box4 {
	padding: 0px 13px;
}
.sidebar-box4 ul {
	padding: 10px 0px;
	border-bottom: 0.3px solid gray;
}
.sidebar-box4 ul li,
.sidebar-box5 ul li {
	padding: 10px 0px;
}
.sidebar-box4 ul li:hover {
	padding: 10px 0px;
	font-weight: 900;
}
.sidebar-box4 ul li i {
	margin-right: 11px;
	width: 18px;
}
.sidebar-box5 {
	padding: 0px 13px;
}
.sidebar-box5 ul > ul {
	display: flex;
	justify-content: space-between;
}
@media screen and (max-width: 991px) {
	header {
		position: relative;
		padding: 25px, 60px;
		justify-content: space-between;
	}
	header .icons {
		position: static;
		display: none;
	}
	header .mobile-searching {
		font-size: 30px;
		display: block;
		position: absolute;
		left: 110px;
		top: 20px;
	}
	header .mobile-category {
		display: block;
	}
	header .mobile-category label + div {
		width: 100%;
		height: 362px;
		position: absolute;
		top: 85px;
		left: 0;
		display: flex;
		flex-direction: column;
		background-color: white;
		font-family: monospace;
		display: none;
	}
	.wrapper {
		display: block;
	}
	.wrapper .main-box {
		margin-left: auto;
		margin-right: auto;
		width: 80%;
	}
	.wrapper .main-box .contents-box {
		margin-bottom: 30px;
	}
	.wrapper .side-box {
		display: none;
	}
}

@media screen and (max-width: 700px) {
	.range {
		display: flex;
	}
	.sidebar {
		top: 72px;
	}
	#menuicon + label {
		width: 13px;
		height: 13px;
	}
	#menuicon + label > span {
		height: 2px;
	}
	header .blogname {
		font-size: 13px;
	}
	header .mobile-category img {
		height: 13px;
		width: 13px;
	}
	header .mobile-searching {
		font-size: 13px;
		top: 27px;
		left: 80px;
	}
	header .mobile-category label + div {
		top: 72px;
	}
}
⚠️ **GitHub.com Fallback** ⚠️