여는 글


 

어쨌든 주문 기능이 있으니 주소 입력도 있으면 좋을 것 같고 그러면 주소 API 써보고 싶었기도 해서 연동하려는 데 생각만큼 뚝딱 되진 않았다.

 

잘안되니까 막 module 다운로드하고 컴포넌트 연결하고 package 형태로 된 것도있어서 그것도 다운로드하고 연결하는 코드 집어넣고 그러니까 어느 순간부터 vue 웹 페이지가 갱신이 안되기 시작했다.

 

정확하게 말하면, vue에서 코드를 고쳤는데 웹 페이지에서는 고친 코드가 반영이 안됐다.

 

이 상황이 이틀 동안 계속됐고 코드가 반영이 안되면 vue cache 문제라는 글이 대부분이길래 크롬 캐시도 지우고 meta태그 넣어서 cache 사용 안하도록 코드 넣고 했는데도 안됐다.

 

생각해보면 그 전에도 새로고침은 알아서 잘만 됐는데 갑자기 이런 코드 넣는다고 되면 그 전부터 안돼야 했다.

 

어쩔 수 없이 코드를 롤백하기 시작했는데 역시나...

 

롤백하니까 새로고침이 알아서 잘 된다.

 

내 생각엔 vue.config.js에서 module 설치했던 부분을 지웠던 게 해결 원인이 된 것 같다.

 

진짜 왜 이러는 지 몰라서 다 엎을까 생각하기도 했는데 이제 해결됐으니 api 연동을 해보겠다.

 

 

 

Vue.js - 다음 주소 API 연동


 

코드 출처 https://postcode.map.daum.net/guide

 

Daum 우편번호 서비스

우편번호 검색과 도로명 주소 입력 기능을 너무 간단하게 적용할 수 있는 방법. Daum 우편번호 서비스를 이용해보세요. 어느 사이트에서나 무료로 제약없이 사용 가능하답니다.

postcode.map.daum.net

 

 

참고한 블로그 https://chlost.tistory.com/53

 

다음주소 API VUE에서 사용하기

안녕하세요. 클로스트입니다 ^-^. 오늘은 다음주소 API를 vue 에서 사용하기에 대해서 포스팅하겠습니다. 기존에 이미 한번 포스팅한 내용인데요. 이 방법은 순수 JS와 HTML의 조합으로 쓸 수 있는

chlost.tistory.com

 

 

공식 사이트에서 제공하는 코드에서 진짜 약간만 수정하면 된다.

 

Vue에 맞게 약간 코드를 바꾼 부분은 6번, 20번, 22번 줄을 참고하면 된다.

 

나머지는 제공하는 코드와 동일하다.

 

++아래 코드는 컴포넌트 파일에 넣으면 에러가 나므로 frontend/public/index.html에 넣어야 한다.

    <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script>

 

전체코드

components/Address.vue

<template>
  <div class="address">
      <h3>ADDRESS</h3>
    <input type="text" id="postcode" placeholder="우편번호">
    <button @click="search()">우편번호 찾기</button><br>
    <!--onclick이 아니라 @click으로 바꿔야한다. -->
    <input type="text" id="roadAddress" placeholder="도로명주소">
    <input type="text" id="jibunAddress" placeholder="지번주소">
    <span id="guide" style="color:#000;display:none"></span>
    <input type="text" id="detailAddress" placeholder="상세주소">
    <input type="text" id="extraAddress" placeholder="참고항목">
  </div>
</template>

<script>

export default {
  name: "Address",
    methods : {
        search(){ //@click을 사용할 때 함수는 이렇게 작성해야 한다.
            new window.daum.Postcode({
            oncomplete: (data) => { //function이 아니라 => 로 바꿔야한다.
                // 팝업에서 검색결과 항목을 클릭했을때 실행할 코드를 작성하는 부분.

                // 도로명 주소의 노출 규칙에 따라 주소를 표시한다.
                // 내려오는 변수가 값이 없는 경우엔 공백('')값을 가지므로, 이를 참고하여 분기 한다.
                var roadAddr = data.roadAddress; // 도로명 주소 변수
                var extraRoadAddr = ''; // 참고 항목 변수

                // 법정동명이 있을 경우 추가한다. (법정리는 제외)
                // 법정동의 경우 마지막 문자가 "동/로/가"로 끝난다.
                if(data.bname !== '' && /[동|로|가]$/g.test(data.bname)){
                    extraRoadAddr += data.bname;
                }
                // 건물명이 있고, 공동주택일 경우 추가한다.
                if(data.buildingName !== '' && data.apartment === 'Y'){
                   extraRoadAddr += (extraRoadAddr !== '' ? ', ' + data.buildingName : data.buildingName);
                }
                // 표시할 참고항목이 있을 경우, 괄호까지 추가한 최종 문자열을 만든다.
                if(extraRoadAddr !== ''){
                    extraRoadAddr = ' (' + extraRoadAddr + ')';
                }

                // 우편번호와 주소 정보를 해당 필드에 넣는다.
                document.getElementById('postcode').value = data.zonecode;
                document.getElementById("roadAddress").value = roadAddr;
                document.getElementById("jibunAddress").value = data.jibunAddress;
                
                // 참고항목 문자열이 있을 경우 해당 필드에 넣는다.
                if(roadAddr !== ''){
                    document.getElementById("extraAddress").value = extraRoadAddr;
                } else {
                    document.getElementById("extraAddress").value = '';
                }

                var guideTextBox = document.getElementById("guide");
                // 사용자가 '선택 안함'을 클릭한 경우, 예상 주소라는 표시를 해준다.
                if(data.autoRoadAddress) {
                    var expRoadAddr = data.autoRoadAddress + extraRoadAddr;
                    guideTextBox.innerHTML = '(예상 도로명 주소 : ' + expRoadAddr + ')';
                    guideTextBox.style.display = 'block';

                } else if(data.autoJibunAddress) {
                    var expJibunAddr = data.autoJibunAddress;
                    guideTextBox.innerHTML = '(예상 지번 주소 : ' + expJibunAddr + ')';
                    guideTextBox.style.display = 'block';
                } else {
                    guideTextBox.innerHTML = '';
                    guideTextBox.style.display = 'none';
                }
            }
        }).open();
        
        
        }
    }
}
</script>

 

나는 컴포넌트로 만들어서 끼워넣었다.

 

 

닫는 글


 

이제 로그인 기능이랑 회원가입할 때 아이디중복체크 기능 만들고 나면 드디어 결제 기능을 구현하면 된다.

 

 결제 기능 너무 구현해보고 싶다...

 

완성된 페이지

 

여는 글


 

5일 동안 계속 붙잡고 있다가 해결해서 까먹기 전에 글로 써둔다.

 

붙잡고 있을 때는 진짜 힘들었는데 어느 순간 갑자기 되니까 기쁘다기 보다는 어안이 벙벙하다.

 

드디어 됐다... 이런 느낌?

 

 

Vue.js + Node.js + MongoDB 연동


 

 찾고 찾아서 연동되는 코드를 찾았다.

 

https://gnaseel.tistory.com/29

 

[ MEVN 스택 ] 3. Mongoose DB + Express 연결하기 (1)

1. vsCode에 vue, express 프로젝트를 생성한다. 2. vue와 express를 연동한다. 3. Mongoose DB를 생성한다. (로컬이 아닌 클라우드 서비스 이용할 예정) - 현재 포스트 4. 웹 프로젝트와 DB를 연동한다. 5. Googl..

gnaseel.tistory.com

 

여기서 나는 클라우드가 아니라 로컬(Compass)을 사용했는데 코드 차이는 없는 듯 하다.

 

 

 

Vue.js + Node.js + MongoDB 값 넣기


 

 

input태그에서 v-model 쓰지말고 name으로 써야 동작한다.... 전체코드는 아래에 있다. (8.18일 해결)

 

참고한 파일은 frontend/src/pages/Blog-Develop.vuebackend/index.js

 

https://ms4hat.tistory.com/17

 

1인 1프로젝트 Vue Js 백엔드와 프론트엔드 간의 데이터 통신

이번에는 관리자 페이지에 쓰일 기능인 프론트 엔드에서 input box에 데이터 title과 author를 입력한 후 그 데이터가 backend에서 db로 전송되고 다른 주소의 프론트 엔드에서 데이터를 받아 사용할 수

ms4hat.tistory.com

 

 

<전체 코드>

 

 

++21년 12.31 추가

this.axios 사용 금지. https://codelist.tistory.com/83 참고

frontend/components/SignUpPage.vue  (내 경우에는 이 컴포넌트를 views에 넣어 사용한다)

<template>
    <form action="/signup" method="post">
      <input type="text" name="id"> <!-- 여기를 v-model로 하면 안된다! -->
      <input type="text" name="password"> <!-- 여기를 v-model로 하면 안된다! -->
      <input type="text" name="name"> <!-- 여기를 v-model로 하면 안된다! -->
      <input type="text" name="address"> <!-- 여기를 v-model로 하면 안된다! -->
      <button @click="signup()">제출</button>
    </form>
</template>

<script>


export default {
    name : "SignUpPage",
    data (){
        return {
            id : '',
            password : '',
            name : '',
            address : '',
            output : ''

        }
    },

    methods : {
        signup() {
            this.axios.post('http://localhost:3000/signup',  { 
            headers : {
                "Content-Type" : "application/x-www-form-urlencoded"
            },
            id : this.id,
            password : this.password,
            name : this.name,
            address : this.address
                
            }).then((response) => { 
                console.log(response)
            })
            .catch((error) => {  
                this.output = error
            }) 

        }
    }, 



}


</script>

<style>

</style>

 

 

 

backend/routes/index.js

var express = require('express');
var router = express.Router();
router.use(express.urlencoded({extended:true}));
router.use(express.json())
var User = require('./mongodbuser');


/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});


/* 봐야할 부분 */
router.post('/signup', (request, response) => {
  console.log('success served');
  console.log(request.body);
  User.create ({
    id:request.body.id,
    password:request.body.password,
    name:request.body.name,
    address:request.body.address
  });
});

module.exports = router;

 

 

 

결과 (고치기 전에는 undefined 또는 {} 로 떠서 프론트엔드에서 값을 못 넘긴건지 백엔드에서 못 가져오는 건지 고민을 많이 했다.)

 

 

 

MongoDB Compass에서 확인한 결과

 

 

 

 

닫는 글


 

5일이나 걸렸던 이유를 생각해보면 문제 위치를 잘못 파악하고 있었던 게 크다.

 

Node->DB 에서 기능이 동작하지 않는 줄 알고 이에 대한 구글링을 열심히 했으나

 

알고보니 애초에 Vue->Node에서 안되는 거였다. 

 

이 부분이 문제라는 것을 아는데 3일 걸렸고 해결하는데 2일이 걸렸다.

 

 원래는 어느 부분 문제인지 위치 파악부터 하는데 멘탈이 털려서 그랬나보다. (급하기도 했고..)

 

 

상품 페이지

 

이제 로그인, 회원가입, DB, 결제, 배포만 남았다.

 

드디어 백엔드!

 

여는 글


 

제품 판매 사이트 포트폴리오를 만드는 목적은 결제 시스템을 구현하고 싶었기 때문이다.

 

그래서 그냥 아무 물건 올려놓고 결제 구현에 집중해야지 했다가 기왕 이렇게 된거 브랜드 명, 컨셉, 제품에 디테일까지 정해볼까? 라는 생각이 들어서 어쩌다보니 브랜드 기획까지 해버렸다.

 

진짜 브랜드 하나 런칭하는 듯한 느낌이 들어서 설렜다.

 

 

올랑올랑 기획


 

어차피 판매하는 제품이 아니므로 일반 제품이 아니라 판타지적 요소를 가미해 게임에 있는 HP 포션처럼 포션들을 팔자! 가 시작점이었다.

 

그래서 포션들을 기획하고 포션이라고 하니 포션 제조하는 마녀 생각도 나고 그래서 컨셉은 몽환, 보라색 위주의 디자인으로 결정했다.

 

이름을 정할때는 순우리말이었으면 좋겠다는 생각이 들어 순우리말로 지었다.

 

기업이면 당연히 기업의 슬로건도 있어야 해, 하면서 메인 페이지에 슬로건도 써놓고.

 

 

 

닫는 글


 

이렇게 해서 완성된 메인 페이지

 

 

 

여는 글


 

Vue 파일구조 이해하느라 하루가 꼬박 걸렸고 html에서 많이 막혔다.

 

그냥 돼야 정상인데 왜 여기서만 안되는 지... 

 

결국엔 <template>을 이해하는 계기가 되긴 했다.

 

아 그리고 참고한 블로그들이 있는데 크롬에 고정시켜둔 페이지가 다 날라갔다.

 

작년에도 이랬던 적이 있는데 1년에 한 번씩은 꼭 이러는 듯...

 

 

Vue 파일 구조


 

 

먼저 나는 frontend는 vue, backend는 node.js를 사용하므로 둘을 연동해놨다. (이것도 참고한 블로그 날아감) 구글링하면 많이 나와있다.

 

일단 둘다 cmd에서 설치하고 그 경로에서 vscode로 열면 아래처럼 되어 있다.

 

 

나는 이미 메인페이지까지는 만들어둔 상태라 좀 더 파일이 많지만 네모박스만 집중해서 보면 된다.

 

components는 이해하기 쉽게 표현하자면 플러그인이다. 별도의 파일로 만들어놓고(html, css, javascript) views 아래에 있는 서브페이지들에 끼워넣는 식이다.

 

이게 Vue가 권장하는 개발 방식이라고 한다.

 

 예를 들어, 어떤 웹 페이지에 왼쪽 상단 브랜드 로고가 있다. 이 브랜드 로고는 어느 서브페이지를 가던 상단에 항상 떠있어야 한다.

 

근데 그걸 모든 서브페이지에 따로 코드를 작성하는 것이 귀찮기도 하고 코드가 길어진다.

 

이때 components에 상단 로고를 화면에 출력하는 html, css 코드를 작성했고 이 component 이름이 Logo라고 하면, 모든 서브페이지들에는 <Logo></Logo> 이것만 넣어주면 끝이다.

 

앞서 설명했듯이 views는 페이지들이 있는 폴더고 그 안에 있는 Home.vue는 html로 말하면 index.html이다. 

 

이 메인페이지에 Logo를 넣고 싶다면 <template> 안에 넣어주면 된다.

 

App.vue는 최상위 틀이라고 보면 된다. 결국에는 Home.vue도 여기에 속해있다.

 

이런 구조를 이해한다면 개발하는데 큰 무리는 없다.

 

 

Template 사용하기


 


나는 template를 사용해본 기억이 없다. 

 

눈치껏 html 태그들을 넣으면 되는 건가? 하고 넣었다가 html처럼 내가 원하는대로 안되길래 열심히 구글링해서, 아직도 완벽히 이해한 것 같지는 않지만 아는 만큼 설명해보기로 한다.

 

리스트를 작성하면 html에서는 단순히 <ul>, <li> 태그들을 사용하면 된다.

 

근데 vue 공식 사이트에서는 v-for 사용을 권장한다. 

 

처음에는 단순 list 출력하는 건데 함수까지 써야해, 라는 거부감이 들어서 안 쓰려고 했는데 결국엔 쓰게 됐다...

 

내 생각에는 vue의 template는 단순 html처럼 쓰는 게 아닌 것 같다.

 

링크를 걸때도 <a>에다가 v-bind를 사용한다.

 

예를 들어, components 에서 메인으로 가는 링크가 있는 컴포넌트를 작성한다고 가정해보자.

 

    <template>
    	<div>
    		<a v-bind:href="main.url">{{main.message}}</a>
        </div>
    </template>
    
    <script>

export default {
  name: "Header",
  data () {
    return {
    main : {
     message : '올랑올랑', 
     url:'/'  ,
    },

    }
  }
};


</script>

 

이렇게 쓴다. 계속 쓰다보면 익숙해지기도 하고 그러려니 하고 쓸 것 같긴 하다...

 

이것 외에도 많은 태그들이 있다. <router-link> (페이지 이동) 등. 공부해야 할 것이 꽤 있다.

 

++지금 생각해보니 컴포넌트라 템플릿 내 코드 깔끔 + 재사용이 쉽도록 하기 위한 목적인 것 같기도 하다. 특히 v-for 같은 경우에는 재사용 시 html 요소는 그대로 두고 함수 message만 바꿔주면 되니까 더 편한 것 같기도 하다. 

 

 

닫는 글


 

React와 Vue가 많이 비교되는 데 둘 다 써본 내 입장에서는

 

React는 진입 장벽이 낮은 것이 장점, 코드가 깔끔하지 않다는 것이 단점(마찬가지로 메인 코드는 깔끔한데 component를 별도 파일로 분리하지 않으므로)인 것 같다.

 

Vue는 코드가 깔끔한 것이 장점, 단점은 처음에 알아야 할 것이 많다는 것이다.

 

어떻게 표현할 지 생각해봤는데 이렇게 정의할 수 있겠다.

 

내가 개발할 때는 React, 누군가 짜놓은 코드를 봐야할 때는 Vue 구조가 좋다.

 

 

 

여는 글


 

++2022.2.26 추가

AWS로 배포하는 과정에서 로컬에서 mariaDB -> AWS RDS 로 변경했다.

 

또한 음성인식이므로 마이크를 써야하는 데 AWS 환경에서 오디오 장치 설치하는 시도에만 일주일을 들였지만 오디오 장치가 설치조차 안돼서 웹에서 마이크를 쓰고 저장된 음성파일을 서버에서는 TEXT로 변환만 하는 것으로 방식을 바꾸려했으나 크롬 마이크 인식은 따로 외부 API를 쓰지 않고 음성->텍스트 변환이 가능한 모양이라 내가 쓰던 Google Cloud Platform의 Speech-to-Text API의 필요성도 없어지게 되었다...

 

대신 크롬이랑 오페라에서만 음성변환을 쓸 수 있다는 단점이 있지만 일단 구현에 초점을 두기로 했다.

크롬에서 마이크를 쓰기 위해서는 https를 사용해야했고 일단 상업용 페이지가 아니라서 아래 포스팅을 참고해서 ssl을 만들어서 사용했다.

https://velog.io/@wlgns410/django-ssl-%EC%A0%81%EC%9A%A9

 

 

배포 전 해야할 일


 

 나는 회원가입 기능이 있기 때문에 개인정보를 저장하지만 개인정보는 Django에서 제공하는 userDB를 사용하기 때문에 따로 암호화할 필요는 없었다.

 

Django에서는 SHA256을 사용한다고 한다.

 

 

 

 

닫는 글


 

이 글이 마지막 포스팅이다.

 

모든 코드(GitHub)와 포트폴리오 주소

 

웹 애플리케이션 포트폴리오(Full Stack)

GitHub https://github.com/codelistwriter/portfolio 메인 페이지 : 자기 소개 (https://codelistwriter.github.io/portfolio/) (JavaScript, React, Node.js, GitHub) 서브 페이지 1 : 4학년 졸업작품 리뉴얼 (D..

codelist.tistory.com

 

 

바로 앞에서 CSS를 열심히 썼더니 익숙해져서 재디자인은 아주 쉽게 끝냈다.

 

 

다음은 배포, 보안에 대한 내용이다

 

++폰트는 전부 https://blog.naver.com/hp0/221372793233

'포트폴리오(종료) > 졸업작품 리뉴얼 제작 과정 (완료)' 카테고리의 다른 글

[Django] 배포  (0) 2021.07.30
진행 과정  (0) 2021.07.23

 

 

졸업작품 리뉴얼은 아래와 같이 진행


 

0. 아이디어 공개 X. 기능만 구현

 

1. 재디자인(디자인은 팀원이 개발했기 때문)

 

2. 코드 리팩토링 (급하게 만드느라 보안, 최적화 안되어 있음)

 

3. 내가 개발했던 부분만 리뉴얼

 

여는 글


 

재디자인한 메인 페이지에서 가장 어려울 것이라고 예상했던 효과다.

 

div 위에 마우스를 올리면 div가 천천히 커지면서 안의 내용물이 보이게 하고 싶었다.

 

프로젝트 페이지들을 이런식으로 보여주고 싶었는데 생각보다 쉽게 구현해냈다.

 

 

CSS + div 커지는 효과 구현


 

먼저 div를 만든다.

 

App.js

export default class Mainpage extends Component {
  render() {
    return (
    
        
   { /* 생략 */ }
        
        
        <div>
          <Project />

        </div>
        
        
  { /* 생략 */ }
  
  
  
  
  class Project extends Component {
  render(){
    return( 
      <div className="project">
        <div className="project1">
          <h1>Capstone Renewal</h1> 
          <img alt= "aws" src={process.env.PUBLIC_URL+"/img/awsicon.png"} /> 
        <img alt= "linux" src={process.env.PUBLIC_URL+"/img/linuxicon.png"} /> 
        {/* 위의 이미지태그는 테스트용 */}
          {/* 추후 따로 클래스 써서 깔끔하게 코드 넣고 이미지, 링크, 소개글 작성 */}

        </div>
        <div className="project2">
          <h1>Showpping Mall</h1>
          {/* 추후 따로 클래스 써서 깔끔하게 코드 넣고 이미지, 링크, 소개글 작성 */}

        </div>
        <div className="project3">
          <h1>Naver Renewal</h1>
          {/* 추후 따로 클래스 써서 깔끔하게 코드 넣고 이미지, 링크, 소개글 작성 */}

        </div>


      </div>

);
  }
}

 

주석때문에 코드가 길어보이는 거지 별 내용도 없다.

 

CSS로 보면 그냥 project 안에 project 1,2,3이 있는 형식이다.

 

나도 처음엔 이렇게 1,2,3 나눌 생각이 없었는데 배경색이 각각 다르다보니 따로 구현해야 했다.

 

 

App.css

.project {
  position: relative;
  width: 80%;
  margin-left: 20%;
  font-size: large;
  margin-bottom: 10%;
}

.project img{
  visibility: hidden; /* 핵심코드 */
}

.project1 {
  width: 70%;
  height: 100px;
  background-color: #fffd9e;
  transition: all 1.5s ease-in-out; /* 핵심코드 */
}


.project1:hover{ /* 핵심코드 */
  width: 90%;
  height: 700px;
  background-color: #fffd9e;
  border-radius: 5%;
}


.project1:hover img{ /* 핵심코드 */
  visibility: visible; /* 핵심코드 */
  transition-delay: 0.5s; /* 핵심코드 */
}


.project2 {
  width: 70%;
  height: 100px;
  background-color: #adbdda;
  transition: all 1.5s ease-in-out;
}


.project2:hover{
  width: 90%;
  height: 700px;
  background-color: #adbdda;
  border-radius: 5%;
}


.project2:hover img{
  visibility: visible;
  transition-delay: 0.5s;
}


.project3 {
  width: 70%;
  height: 100px;
  background-color: #abda8a;
  transition: all 1.5s ease-in-out;
}


.project3:hover{
  width: 90%;
  height: 700px;
  background-color: #abda8a;
  border-radius: 5%;
}


.project3:hover img{
  visibility: visible;
  transition-delay: 0.5s;
}

 

project 1. 2. 3은 백그라운드 컬러만 다르고 똑같기 때문에 핵심코드라고 주석표시 해놓은 project1만 보면 된다.

 

마우스를 올려 div가 커지기 전에는 div 안 내용물이 보이지 않아야한다. 그래서 부모에게 hidden 값을 줘서 전체 기본값이 hidden이 되도록 했다. img 테스트용으로 img를 지정했지만 h1 등 다른 태그를 써도 무방하다.

.project img{
  visibility: hidden; /* 핵심코드 */
}

 

 

 

이해가 쉽도록 아래 코드를 먼저 가져왔으나 위는 project img이고 아래 코드는 project1:hover img인 것을 주의해야 한다.

hover는 마우스 올렸을 때 효과가 발생하도록 하는 코드다.

마우스를 올렸을 때는 다시 이미지가 보여야하므로 hover에서 다시 이미지가 보이도록 한다.

delay를 준이유는 내 코드는 천천히 커지도록 구현했기 때문에 어느정도 커지고 나서 이미지가 보이도록 하기 위해서 delay를 줬다.

.project1:hover img{ /* 핵심코드 */
  visibility: visible; /* 핵심코드 */
  transition-delay: 0.5s; /* 핵심코드 */
}

 

 

 

 

transition을 주지 않으면 마우스 올리거나 내리면 바로 크기가 변한다. 그러면 뚝뚝 끊기는 느낌이 나서 별로이므로 천천히 커지거나 작아지도록 효과를 줬다.

 

여기서 주의할 점은 project1,2,3을 감싸고있는 project에 적용하지 않도록 주의해야한다. project는 그냥 이 3개를 감싸고 있는 틀에 불과하므로 적용하면 제대로 구현되지 않는다. (이거때문에 1시간 날림)

.project1 {
  width: 70%;
  height: 100px;
  background-color: #fffd9e;
  transition: all 1.5s ease-in-out; /* 핵심코드 */
}

 

 

마우스 올리는 효과를 hover라고 한다. 위 코드를 보고 비교해보면 알겠지만 width가 20%, height가 600px이 커지도록 했다. border-radius는 값이 클 수록 모서리가 둥글어진다.

.project1:hover{ /* 핵심코드 */
  width: 90%;
  height: 700px;
  background-color: #fffd9e;
  border-radius: 5%;
}

 

 

 

닫는 글


 

이번 포스팅이 마지막이다.

 

나중에도 따로 포스팅하진 않을 것 같지만 모바일 최적화를 위해 CSS @media를 사용했다.

 

 

원래는 메인페이지를 지난주에 끝냈어야하는데 재디자인 한다고 오래걸렸다.

 

 

 

모든 코드(GitHub)와 포트폴리오 주소

 

웹 애플리케이션 포트폴리오(Full Stack)

GitHub https://github.com/codelistwriter/portfolio 메인 페이지 : 자기 소개 (https://codelistwriter.github.io/portfolio/) (JavaScript, React, Node.js, GitHub) 서브 페이지 1 : 4학년 졸업작품 리뉴얼 (D..

codelist.tistory.com

 

 

여는 글


 

애니메이션 구현방식에는 크게 JavaScript랑 CSS가 있는 것 같은데 차이점은 JavaScript는 좀 더 적용범위가 넓고 구현할 수 있는 기능이 다양하다, CSS는 구현이 쉽다 정도라고 한다.

 

이번에 메인페이지를 구현하면서 CSS에 익숙해진 만큼 끝까지 CSS를 사용하기로 하고 다른 페이지를 구현할 때는 최대한 JavaScript를 사용해보기로 했다.

 

 

CSS 텍스트 나타나기 효과


 

구현이 매우 쉽다.

 

App.js

class Profile extends Component {
  
  render() {
    return(
       
    <div className="fadein">

      <h1> ⸢ 2019 한국형 사물이미지 인공지능 학습데이터 활용 아이디어 공모전 ⸥ 우수상</h1>
      <h1> 2021년 2월 19일, 컴퓨터공학과 학사 취득</h1>
      <h1> 2021년 자격증 취득</h1>
      <h1> 2021년 9월 토익 000점</h1><br></br>
      <h1> #98년생 #ISTP #취미는_Unity_공부</h1>

   </div>

    );
  }
}

 

나는 h1에 적용했다.

 

App.css

.fadein{
  font-size: medium;
  position: relative;
  overflow: hidden;
  animation: fadein 7s ease-in-out;


}


@keyframes fadein{
  0% {
    opacity: 0;
    transform: translateY(20px);
  }
  100% {
    opacity: 1;
    transform: none;
  }

}

 

출처  

 

CSS 글 목록이 아래에서 위로 올라오는 기능 fadeIn

@keyframes fadeIn { from { opacity: 0; transform: translateY(20px); } to { opacity: 3; transform: none; } } main { animation: fadeIn 0.5s ease-in-out; } 글 목록이 아래에서 위로 올라오는 기능 fadeIn

windorsky.tistory.com

 

 

닫는 글


 

이번 구현부터 모바일화면도 같이 띄워놓고 구현하기 시작했는데 둘 다 신경쓰려니 확실히 오래걸린다.

 

거의 동적으로만 개발해야하니 결과적으론 좋을 것 같긴 하다.

 

 

 

모든 코드(GitHub)와 포트폴리오 주소

 

웹 애플리케이션 포트폴리오(Full Stack)

GitHub https://github.com/codelistwriter/portfolio 메인 페이지 : 자기 소개 (https://codelistwriter.github.io/portfolio/) (JavaScript, React, Node.js, GitHub) 서브 페이지 1 : 4학년 졸업작품 리뉴얼 (D..

codelist.tistory.com