본문 바로가기

📢 들어가며

그동안 게을러져서 포스팅이 살짝 늦었다... 다시 화이팅해보자!

 

이번 포스팅은 지난 포스팅에서 이어진다.

지난 포스팅에선 화면에 지도를 띄우고 대략적인 UI 틀을 잡았었다.
이번 포스팅에선 구체적인 UI 를 구현해볼 것이다.

 

모든 소스코드는 깃헙에서 확인할 수 있다.

🍜 UI 설계

이번에도 대충 그려 설계를 해보았다.
지도에서 특정 위치를 선택하고 나면 좌측 사이드바가 활성화되고 위 이미지와 같은 정보를 입력할 수 있게 된다.

사이드 바에선 음식점의 이름, 이미지, 위치정보, 별점, 평가를 보여준다.

🍜 Bootstrap 설치

본격적인 UI 구현을 위해서 Bootstrap을 사용할 것이다.
Bootstrap 을 설치해보자.

vue add bootstrap-vue

Vue CLI3로 설치를 했기 때문에 Vue CLI 플러그인을 활용해 Bootstrap을 설치해주는 것이다.
별다른 설정없이 bootstrap을 주입할 수 있다.

🍜 사이드바 UI 구현

이제 버튼으로 사이드바를 펼쳤다 접었다하고,
접혀진 상태에서 지도를 클릭했을 때 사이드바가 활성화 되도록 구현해 볼 것이다.

Bootstrap 을 설치하고 나면 <BButton> 같은 Bootstrap에서 제공하는 Components들을 쓸 수 있다.
사이드 바 옆에 사이드바를 활성화할 수 있는 버튼을 만들어 보자.

<template>
  <div class="side-bar-wrapper">
    <VueResizable
        class="resizable-side-bar"
        :width="500"
        :min-width="500"
        :max-width="Infinity"
        :active="['r']"
        v-if="isVisibleSideBar"
    >
      <div class="side-bar">
      </div>
    </VueResizable>
    <BButton
        class="side-bar-active-btn"
        size="sm"
        @click="showSideBar"
    >
      {{ isVisibleSideBar ? '닫힘' : '열림' }}
    </BButton>
  </div>
</template>

<script>
import VueResizable from 'vue-resizable';

export default {
  name: 'SideBar',
  components: {
    VueResizable
  },
  data() {
    return {
      isVisibleSideBar: true
    }
  },
  methods: {
    showSideBar() {
      this.isVisibleSideBar = !this.isVisibleSideBar;
    }
  }
}
</script>

<style lang="scss" scoped>
.side-bar-wrapper {
  display: flex;

  > .resizable-side-bar {
    > .side-bar {
      background-color: rgba(0, 0, 0, 0.5);
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
    }
  }

  > .side-bar-active-btn {
    flex-shrink: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #000000;
    padding: 0;
    border: none;
    border-radius: unset;
    color: #fff;
    opacity: 0.5;
    width: 40px;
    height: 40px;
  }
}
</style>

frontend/src/components/SideBar.vue

결과화면

버튼 위치를 잡기 위해 flex 를 쓰고, Side Bar와 똑같이 opacity를 줘서 구현했다.
showSideBar() 메소드로 사이드바가 열고 닫힐 수 있도록 하였고, 열고 닫을 때 버튼의 글씨가 바뀌게 했다.

 

이제 사이드바 내 UI 를 구현해보자

<template>
  <div class="side-bar-wrapper">
    <VueResizable
        class="resizable-side-bar"
        :width="500"
        :min-width="500"
        :max-width="Infinity"
        :active="['r']"
        v-if="isVisibleSideBar"
    >
      <div class="side-bar">
        <div class="title-area">
          <BInput placeholder="맛집 이름을 입력해주세요."/>
        </div>
        <div class="image-area">
          <div class="iw-file-input">
            사진을 업로드 해주세요
          </div>
        </div>
        <div class="location-info-area">
          <BInput placeholder="위치 정보 직접 입력하기"/>
        </div>
        <div class="rate-area">
          <BFormRating />
        </div>
        <div class="review-area">
          <BFormTextarea
              ref="textarea"
              placeholder="후기를 입력해주세요."
          />
        </div>
      </div>
    </VueResizable>
    <BButton
        class="side-bar-active-btn"
        size="sm"
        @click="showSideBar"
    >
      {{ isVisibleSideBar ? '닫힘' : '열림' }}
    </BButton>
  </div>
</template>

<script>
import VueResizable from 'vue-resizable';

export default {
  name: 'SideBar',
  components: {
    VueResizable
  },
  data() {
    return {
      isVisibleSideBar: true
    }
  },
  methods: {
    showSideBar() {
      this.isVisibleSideBar = !this.isVisibleSideBar;
    }
  }
}
</script>

<style lang="scss" scoped>
.side-bar-wrapper {
  display: flex;
  color: #fff;

  > .resizable-side-bar {
    > .side-bar {
      background-color: rgba(0, 0, 0, 0.5);
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      padding: 10px;

      > .title-area {
        padding: 20px 10px;

        input, input::placeholder, input:focus {
          font-size: 2rem;
          font-weight: bold;
          color: #fff;
          box-shadow: none;
          background: none;
          border: none;
        }
      }

      > .image-area {
        padding: 0 10px;

        > .iw-file-input {
          display: flex;
          justify-content: center;
          align-items: center;
          font-size: 1.3rem;
          border: 5px dashed rgb(255, 255, 255, 0.5);
          border-radius: 10px;
          height: 250px;
          background-color: rgb(255, 255, 255, 0.5);
        }
      }

      > .location-info-area {
        padding: 10px;

        input, input::placeholder, input:focus {
          font-size: 1rem;
          color: #fff;
          box-shadow: none;
          background: none;
          border: none;
        }
      }

      > .rate-area {
        padding: 0 20px;
        text-align: center;

        output {
          font-size: 2rem;
          color: #ffdd00;
          background: none;
          border: none;
          box-shadow: none;
        }
      }

      > .review-area {
        padding: 20px 10px;

        textarea, textarea::placeholder {
          min-height: 300px;
          resize: none;
          color: #fff;
          background: none;
          border: none;
          box-shadow: none;
        }

        /* width */
        ::-webkit-scrollbar {
          width: 10px;
        }

        /* Track */
        ::-webkit-scrollbar-track {
          background: #f1f1f1;
        }

        /* Handle */
        ::-webkit-scrollbar-thumb {
          background: #888;
        }

        /* Handle on hover */
        ::-webkit-scrollbar-thumb:hover {
          background: #555;
        }
      }
    }
  }

  > .side-bar-active-btn {
    flex-shrink: 0;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: #000000;
    padding: 0;
    border: none;
    border-radius: unset;
    color: #fff;
    opacity: 0.5;
    width: 40px;
    height: 40px;
  }
}
</style>

frontend/src/components/SideBar.vue

 

사이드바 UI 구현 결과

설계했던 이미지 대로 UI를 구현해보았다. 대부분 Bootstrap을 활용했다.
input 은 네모 박스가 아니라 글씨만 보이도록 구현했고,
파일 업로드 부분은 아직 잘 모르겠어서 일단 UI 틀만 잡아놨다.

 

UI 구현 부분은 딱히 설명할 것이 없어보이지만,
신경 쓴 부분에 대해서만 살짝 언급해보자면...

 

textarea에 스크롤이 생긴 모습

개인적으로 위 그림과 같은 스크롤바 디자인이 굉장히 보기 싫었다.
브라우저마다 스크롤바가 다르게 보이는 것도 맘에 들지 않아,

W3School 를 참고하여 스크롤바 디자인을 바꿔 주었다.

/* width */
::-webkit-scrollbar {
  width: 10px;
}

/* Track */
::-webkit-scrollbar-track {
  background: #f1f1f1;
}

/* Handle */
::-webkit-scrollbar-thumb {
  background: #888;
}

/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
  background: #555;
}

frontend/src/components/SideBar.vue

 

스크롤바 디자인을 바꿔준 모습

🍜 사이드바 UI 디테일 살리기

뭔가 지금 UI는 허전해보여서, 아이콘을 추가하고 글꼴을 바꿔주기로 했다.

🍬 Font Awesome 아이콘 추가

Bootstrap에서 Icon을 제공해주긴 하지만, 나는 Font Awesome Icon 이 좀 더 익숙해서 이를 사용하기로 했다.

설치

$ npm i @fortawesome/vue-fontawesome
$ npm i @fortawesome/fontawesome-svg-core
$ npm i @fortawesome/free-solid-svg-icons
  • @fortawesome/fontawesome-svg-core
    • Fontawesome의 SVG파일을 던져주는 역할을 한다.
    • 반드시 필요!
  • @fortawesome/vue-fontawesome
    • 던져준 SVG파일을 Vue에서 사용할 수 있게 해주게 한다.
    • 반드시 필요!
  • @fortawesome/free-solid-svg-icons
    • 아이콘 모음이라고 생각하면 된다.
    • 종류(무료)에는 solid, regular, brands 가 있다.
    • solid 는 색이 채워진? 두꺼운? 느낌의 아이콘 모음이다.

설치 후 package.jsondependecies를 보면 잘 설치된 것을 확인할 수 있다.

 

package.json

설치된 FontAwesome Icon을 관리하는 파일을 만들어줄 것이다.

src 디렉토리 아래에 common 폴더를 파고 Icons.js 파일을 생성하자.

import Vue from 'vue';

// 0. 편의를 위해 아이콘은 알파벳 순서대로 추가하자.
// 1. 설치했던 fontawesome-svg-core 와 vue-fontawesome
import { library } from '@fortawesome/fontawesome-svg-core';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';

// 2. 설치했던 아이콘 파일에서 원하는 아이콘 불러오기
import {
  faAngleLeft,
  faAngleRight,
  faLocationDot,
} from "@fortawesome/free-solid-svg-icons";

// 3. 불러온 아이콘을 라이브러리에 담기
library.add(faAngleLeft);
library.add(faAngleRight);
library.add(faLocationDot);

// 4. fontawesome 아이콘을 Vue 템플릿에서 사용할 수 있도록 등록
Vue.component("FontAwesomeIcon", FontAwesomeIcon);

frontend/src/common/Icons.js

 

생성한 Icons.js 를 전역에서 사용할 수 있도록 main.js 에 아래 코드를 추가하면 끝.

import '@/common/Icons.js';

frontend/src/main.js

 

이제 아이콘 사용할 일이 있으면 /src/common/Icons.js 에서 원하는 아이콘을 import 해오고, libraryadd 시켜주기만 하면된다.
Vue.component("FontAwesomeIcon", FontAwesomeIcon); 를 통해 Vue component로 등록해줬기 때문에 <FontawesomeIcon icon="location-dot" /> 과 같이 구현할 수 있다.

 

이제 아이콘을 적용해보자.
열림, 닫힘 버튼을 화살표 아이콘으로 변경하고,
위치 정보 입력란 앞쪽에 아이콘을 추가해줄 것이다.

// ...
    <div class="location-info-area">
      <FontAwesomeIcon icon="location-dot" />
      <BInput placeholder="위치 정보 직접 입력하기"/>
    </div>
// ...
    <BButton
        class="side-bar-active-btn"
        size="sm"
        @click="showSideBar"
    >
      <FontAwesomeIcon :icon="isVisibleSideBar ? 'angle-left' : 'angle-right'" />
    </BButton>
// ... 

// css
    > .location-info-area {
        padding: 10px 20px;
        display: flex;
        align-items: center;
    // ...
    }

frontend/src/components/SideBar.vue

 

아이콘 적용 후 결과

확실히 아이콘을 추가하는 편이 더 예뻐보인다!

🍬 Font 적용

Font를 적용하기 위한 방법에는 3가지가 있다

 

1. 로컬PC에 설치하기

2. font 파일들을 보관하여 불러오기

3. Web CDN

인터넷이 안되는 환경에서도 동작하기 위해, 그리고 로컬PC에 설치할 수 없는 경우를 대비하여 font 파일들을 따로 보관하여 불러오는 방식으로 진행했다.

 

src/assets 폴더 하위에 fonts 폴더를 파고 원하는 폰트를 다운로드하여 추가한다.

frontend/src/assets/fonts

나는 '나눔스퀘어'와 '나눔바른고딕'을 추가했다.

frontend/src/assets/scss/vendors/bootstrap-vue

frontend/src/assets/scss/vendors/bootstrap-vue 를 보면 _custom.scss 라는 파일이 보일 것이다.
이는 부트스트랩으로부터 추가된 커스텀 css 파일로, bootstrap 이 외의 css를 전역적으로 추가해주고 싶을 때 사용할 수 있다.
아래 코드를 추가하여 추가한 폰트를 사용할 수 있게 하자

//======================= CUSTOM ==================================
// 글꼴
@font-face {
  font-family: 'Nanum Square';
  src: url('~@/assets/fonts/NanumSquare_acEB.ttf') format('truetype');
}
@font-face {
  font-family: 'Nanum Barun Gothic';
  src: url('~@/assets/fonts/NanumBarunGothic.ttf') format('truetype');
}

frontend/src/assets/scss/vendors/bootstrap-vue/_custom.scss

 

'나눔스퀘어'는 제목부분의 폰트를 변경해주는 데에 사용할 것이고,

'나눔바른고딕'은 전역적으로 선언해줄 것이다.

// ...
    > .title-area {
        // ...

        input, input::placeholder, input:focus {
          font-family: 'Nanum Square', serif;
// ...
        }
    }

frontend/src/components/SideBar.vue

 

// ...
<style lang="scss">
@import "~@/assets/scss/vendors/bootstrap-vue/index";
#app {
// ...

frontend/src/App.vue

 

font 추가 후 결과 화면

글꼴이 제대로 적용된 것을 확인할 수 있었다!🎉

 


 

이번 포스팅에선 사이드 바의 UI를 구현해보았다.

다음 포스팅에선 이번 포스팅을 통해 알게된 _custom.scss 파일로 재사용가능한 기능을 구현해보고,
지도를 클릭하여 위치 정보를 입력할 수 있는 기능을 구현해보도록하겠다.

 

댓글, 하트, 피드백은 언제나 환영입니다!😇

Seize the day!

Spring MVC | Spring Boot | Spring Security | Mysql | Oracle | PostgreSQL | Vue.js | Nuxt.js | React.js | TypeScript | JSP | Frontend | Backend | Full Stack | 자기계발 | 미라클 모닝 | 일상