위키백과에서 먼저 정의를 살펴보았습니다.

 

 

"라이브러리는 주로 소프트웨어를 개발할 때 컴퓨터 프로그램이 사용하는 비휘발성 자원의 모임이다.

여기에는 구성 데이터, 문서, 도움말 자료, 메시지 틀, 미리 작성된 코드, 서브루틴, 클래스, 값, 자료형 사양을 포함할 수 있다."

 

"컴퓨터 프로그래밍에서, 소프트웨어 프레임워크는 복잡한 문제를 해결하거나 서술하는 데 사용되는 기본 개념 구조이다.

간단히 뼈대, 골조, 프레임워크라고도 한다."

 

글만 간단히 보아도 두 개념이 많이 다른 것을 알 수 있습니다.

라이브러리는 프레임워크에 비해 작은 개념입니다.

 

 

프론트개발을 할때 쉽게 접하는 것을 예로 들어보자면 jQuery, React 같은 것들이 라이브러리입니다.

엥? 왜 React가 라이브러리이지? 프레임워크 아니었어? 하는 사람이 있을 수도 있습니다.

과거의 저도 헷갈렸었는데, 정확히 리액트의 생태계는 프레임워크이지만 리액트만은 라이브러리라고 합니다.

 

프레임워크로 분류되기 위해서는 필수로 충족해야하는 것들이 있습니다. 

다른 많은 프레임워크들이 기본적으로 내장하고 있는 기능들말이죠.. (예를 들어 라우터 기능이라던가)

 

리액트에서 이러한 기능들을 구현하기 위해서는 여러가지 추가적인 라이브러리를 같이 사용해야합니다.

(react-router, react-redux, react-saga 등....) 

그렇기 때문에 React는 프레임워크로 분류되지 않고 라이브러리로 분류됩니다.

 

react 공식사이트 메인 캡쳐

 

 

물론 공식사이트에도 라이브러리로 소개되고 있습니다.^^

 

 

 

 

저는 DB를 공부한 사람이 아닙니다.

포트폴리오 사이트 제작을 하면서 겪었던 것에 대한 기록 글입니다.^^

 

 

 

 

들어가기 전에 잡담.

Sequelize를 통해 db 작업을 한 상태였는데, db의 d자도 모르다보니 

매번 정적인 데이터를 손으로 삽입하고는 했습니다.

(명령어를 치거나, 워크벤치 들어가서 작업하거나, 하다하다 안되서 어드민을 만들어서 데이터를 입력해서 db로 저장했습니다.)

근데 이게 db를 지워야하는 경우가 생기고, 배포 후에 운영db에 또 똑같은 일을 작업해야하고...

끝이 없는 이 작업 속에서 미치겠네라고만 생각했는데, (검색해볼 정도는 아니었나 ㅋ;;;;;)

 

여튼 그러다가 우연히 (Sequelize를 통해 작업한) back 폴더 안에서 seeders라는 폴더를 발견했고,

내가 만든 적도 없는데? 이게 뭥ㅈㅣ? 하다가 검색을 통해 알게되었습니다. 

seeders 폴더

Sequelize를 통해 더미데이터를 넣을 수 있다는 것을!!!!!!!!

자 매뉴얼을 참고하거나 아래 블로그 글을 일거보세요(전 처음부터 적지 않기 때문에)

 

매뉴얼

sequelize.org/master/manual/migrations.html

 

참고

any-ting.tistory.com/53

 

[Node.js] Sequelize Seeders 사용법

- 개요 안녕하세요. 이번 시간에는 Sequelize에 Seeders라는 기술에 대해 알아보겠습니다. 우리는 어떤 기능 개발을 하다 보면 테스트 데이터가 필요할 때가 있습니다. 필요할 때마다 우리는 데이터

any-ting.tistory.com

 

 

 

Sequelize Seed

만약, 모르고 seeders 폴더를 삭제했다면 아래 명령어로 init 하세요.

npx sequelize init:seeders 

 

 

 

DB 생성

- model 작업 후 db 생성 후의 상태를 전제로 합니다.

- seed를 통해 create하면서 진행할 수도 있는 것 같은데, 이러한 경우라면 매뉴얼을 참고하세요.

(model 작업 후 npx sequelize db:create를 통해 db 생성까지 할 수 있습니다.)

 

 

 

Migrate 하기 

npx sequelize-cli db:migrate

// [D] 가장 최근 migration 돌리기(취소)
npx sequelize-cli db:migrate:undo

 

 

 

Seeder 파일 만들기

파일명에 본인이 생성할 파일 명을 적어주세요.

npx sequelize seed:generate --name 파일명

 

예시

catchmind 데이터를 관리할 것이어서 catchmind를 파일명으로 지정했습니다.

npx sequelize seed:generate --name catchmind

seeder 만들기 결과

명령어를 통해 파일이 생성되는데, 앞에 생성한 날짜?와 같은 숫자들이 적힌채로 생성됩니다.

 

 

 

seeders 파일 내용 작성

파일로 들어가보면 코드들이 작성되어있습니다.

up은 실행 시 seeder를 수행할때 실행되는 로직이고 down은 실행 취소 시 실행되는 로직입니다.

'use strict';

module.exports = {
  up: async (queryInterface, Sequelize) => {
    /**
     * Add seed commands here.
     *
     * Example:
     * await queryInterface.bulkInsert('People', [{
     *   name: 'John Doe',
     *   isBetaMember: false
     * }], {});
    */
  },

  down: async (queryInterface, Sequelize) => {
    /**
     * Add commands to revert seed here.
     *
     * Example:
     * await queryInterface.bulkDelete('People', null, {});
     */
  }
};

 

예시

컬럼이나, 데이터 타입 같은 것들을 안 맞추면 실패합니다.

string으로 넣어야하는데 실수로 json으로 넣었더니 fail이 되었습니다.

이때는 터미널에서 알려줍니다.

 

[데이터베이스]

db를 테이블 캡쳐를 보면, 저에게 필요한 것은 id, question, correct, incorrect 네가지인 것 같습니다.

id는 자동으로 증가해서 추가하지 않아도 되지만, 문제 번호로써 그냥 추가했습니다.

만약 id를 작업하지 않으면 자동으로 삽입이 됩니다만, undo후 seed를 반복하면 0로 reset되는 것이아니라 계속 증가하는 번호로 삽입됩니다. (저는 reset하는 것을 찾지 못했습니다 ㅜ)

catchmind db 캡쳐

 

[models/catchMind.js]

모델에서 데이터 타입을 다시한 번 확인해봤습니다.

const DataTypes = require('sequelize');
const { Model } = DataTypes;

module.exports = class CatchMind extends Model {
    static init(sequelize) {
        return super.init({
            question: {
                type: DataTypes.TEXT,
                allowNull: false, 
            },
            correct: {
                type: DataTypes.STRING(100),
                allowNull: false,
            },
            incorrect: {
                type: DataTypes.TEXT,
                allowNull: false, 
            },
        }, {
            modelName: "CatchMind", 
            tableName: "CatchMind", 
            timestamps: false,
            charset: 'utf8mb4', 
            collate: 'utf8mb4_general_ci',
            sequelize,
        });
    }

    static associate(db) {}
};

 

[seeders/XXXXXXXXXXXXXX-catchmind.js]

'use strict';

module.exports = {
    up: async (queryInterface, Sequelize) => {
        await queryInterface.bulkInsert('catchmind', [
            {
            	id: '1',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz00.png',
                correct: '가로수',
                incorrect: '["공","장","소","궁","한","이","야","기","잼","난","사","건"]',
            },
            {
            	id: '2',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz01.png',
                correct: '견인차',
                incorrect: '["강","초","숭","구","리","당","하","늘","개","퍼","풍","사"]',
            },
            {
            	id: '3',
                question: 'https://okayoon-bucket.s3.ap-northeast-2.amazonaws.com/game/catchmind/quiz/img_quiz02.png',
                correct: '도시',
                incorrect: '["강","초","숭","구","리","당","기","잼","난","사","수","김"]',
            },
        ], {});
    },

    down: async (queryInterface, Sequelize) => {
        await queryInterface.bulkDelete('catchmind', null, {});
    }
};

up

- await queryInterface.bulkInsert('테이블명', [{}] 을 통해 테이블 명을 적어줍니다.

- models에서 지정한 type에 맞춰 데이터를 넣어줍니다.

 

down

- await queryInterface.bulkDelete('테이블명', [{}] 을 통해 테이블 명을 적어줍니다.

- 저렇게 쓰면 전체 초기화 됩니다.

 

 

 

Seed 실행

위에 작업을 모두 마쳤다면 실행해보겠습니다.

seed 명령어를 입력하면 데이터가 여러번 중복해서 들어갈 수 있습니다.

 

 

전체 파일 seed 실행

npx sequelize-cli db:seed:all

 

 

단일 파일 seed 실행

파일명에 날짜까지 다 입력해줘야합니다.

npx sequelize db:seed --seed 파일명

// [D] 예시
// npx sequelize db:seed --seed 20210406123050-catchmind.js

 

결과

seed 실행 후 결과 창

 

 

그 외 명령어 입니다.

 

 

 

저는 외래키도 없고 단순한 테이블에 하는 작업이어서 어려움이 없었지만, 복잡할 수록 작업이 복잡해지니,

꼭 매뉴얼을 확인하시길 바랍니다.

 

 

 

개발일때에는 development, 배포일때에는 productionprocess.env.NODE_ENV를 구분해서 webpack의 설정을 진행해야하는 경우들이 있다.

예를 들면... 보안에 안좋아서 옵션을 달리해야한다던가..?

 

맥에서는 명령어만 삽입해도 진행이 되는데, windows에서는 라이브러리를 사용해줘야한다.

 

cross-env는 이때 운영체제나 플랫폼에 종속되지 않고 동일한 방법으로 env 변수를 주입해주는 패키지이다.

이것을 사용하면 동적으로 process.env(환경 변수)를 변경할 수 있다.

 

 

설치

npm i cross-env

 

사용할 커맨드 앞에 cross-env 를 붙여주기만 하면 된다.

 

 

 

package.json

사용 전 

"scripts": {
    "dev": "next -p 3060",
    "build": "ANALYZE=true NODE_ENV=production next build",
 },

 

 

사용 후

"scripts": {
    "dev": "next -p 3060",
    "build": "cross-env ANALYZE=true NODE_ENV=production next build",
 },

 

 

이렇게 간단하게 해결해주는 패키지이기 때문에 많은 사람들이 사용하고,

그렇기 때문에 비슷한 이름으로 해서 사용자를 헷갈리게 하여 설치하는 순간 정보를 빼가는 해커들도 있었다.

 

 

보안뉴스 캡쳐

 

보안뉴스

https://www.boannews.com/media/view.asp?idx=56184&skind=O

 

개발자는 속이기 쉽다? 자바스크립트 저장소 npm 감염되다

해커들에게 공격 툴이 있는 것처럼 개발자들에게도 소프트웨어 개발 툴이 있다. 그리고 그런 개발 툴들을 단위 단위로 묶어서 관리하는 체계도 있다. 자바스크립트라는 프로그래밍 언어의 패키

www.boannews.com

 

 

해커가 crossenv 라는 패키지를 배포하였고, 개발자가 install시 실수로 '-'를 빼고 설치하게되면 .env 파일을 가져가는 사건도 있었다.

.env에는 보안적인 정보들이 담겨있으니...

 

 

npm 블로그

https://blog.npmjs.org/post/163723642530/crossenv-malware-on-the-npm-registry.html

 

npm Blog Archive: `crossenv` malware on the npm registry

npm Blog (Archive); updates from the npm team are now published on the GitHub Blog and the GitHub Changelog

blog.npmjs.org

 

 

오늘도 이렇게 좋은 패키지를 알아간다ㅎㅎ

 

사이트에 Form을 만들고 이것을 통해 '사이트 주인에게 메일 발송'하는 기능을 작업해보도록하겠습니다.

 

 

EmailJS

- http://www.emailjs.com/

 

Send email from Javascript - no server code required | EmailJS

Send email directly from your client-side Javascript code – no server side code required. Add static or dynamic attachments, dynamic parameters, captcha code and more. Start with our free tier!

www.emailjs.com

- 무료는 텍스트만 가능, 파일전송 X

 

 

 

1. 가입

EmailJS 메인

 

 

 

2. Email Services 페이지

Add New service를 클릭해줍니다.

메일을 발송하고, 받을 수 있는 플랫폼을 선택하고 연동하는 작업입니다.

Email services 페이지

 

 

저는 Gmail를 선택했습니다.

Service ID는 옆에 키 모양 아이콘을 누르면 변경 가능합니다.

(이 key가 공개되면 제 메일을 이용할 수 있을 것이므로, 저는 캡쳐에 나온 키 안썼습니다.)

service 선택 팝업

 

 

Connect Account 눌러서 계정 연동해줍니다.

이때, 팝업이 뜨는데 허용 버튼을 눌러줍니다.

EmailJS 권한 팝업

 

 

안내 문구를 읽어보면 발신자가 본인이 된다는 의미입니다.

허용을 모두 마쳤다면, Create Service 버튼을 클릭합니다.

 

대시보드의 Email Services에 내가 방금 생성한 것이 확인됩니다.

Email Services 대시보드 생성예시

 

 

그리고 연동한 메일에도 관련 Test 메일이 와있습니다.

EmailJS 테스트 메일

 

 

허용 누를때 안내나왔던대로 내가 발신자가 됩니다.

이후, 대시보드에서 보낸 히스토리나 이벤트 같은 것들을 확인할 수 있습니다.

Events에서 방금 테스트메일에 대한 Events를 확인할 수 있습니다.

Events 페이지

 

 

 

3. Email Templates 페이지

Create New Template를 클릭해서 템플릿을 만들어줍니다.

Email Templates 페이지 create 버튼

 

일단, 뭐가 뭔지 모르니 그냥 오른쪽 위에 있는 Save버튼을 눌러줍니다...

 

 

 

4. Integration 페이지

본격적으로 작업을 해보겠습니다.

NPM, Browser, API 버튼을 누르면 각 설명이 적혀있습니다.

 

저는 npm을 통해 작업하겠습니다.

integration 페이지

 

자세한 내용은document을 한번 읽어보세요.

https://www.emailjs.com/docs/sdk/installation/

 

SDK Installation | EmailJS

Guide goes through the various methods used to install EmailJS SDK

www.emailjs.com

 

 

 

5. npm install 및 예제 코드 확인

npm install emailjs-com --save

 

document에 적혀있는 예제

import React from 'react';import emailjs from 'emailjs-com';
import './ContactUs.css';

export default function ContactUs() {
  function sendEmail(e) {
    e.preventDefault();

    emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', e.target, 'YOUR_USER_ID')
      .then((result) => {
          console.log(result.text);
      }, (error) => {
          console.log(error.text);
      });
  }

  return (
    <form className="contact-form" onSubmit={sendEmail}>
      <input type="hidden" name="contact_number" />
      <label>Name</label>
      <input type="text" name="user_name" />
      <label>Email</label>
      <input type="email" name="user_email" />
      <label>Message</label>
      <textarea name="message" />
      <input type="submit" value="Send" />
    </form>
  );
  }

 

이 부분이 주의깊게 봐야하는 부분입니다.

 emailjs.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', e.target, 'YOUR_USER_ID')
   .then((result) => {
   	console.log(result.text);
    
   }, (error) => {
   	console.log(error.text);
    
   });
 }

sendForm 메서드에는 3개의 id와 함께 form을 넘겨줘야합니다.

(form data가 아니라 form 엘리먼트입니다.)

 

 

3개의 ID를 발급 받을 수 위치입니다.

  • YOUR_SERVICE_ID : Email Services 페이지에서 발급
  • YOUR_TEMPLATE_ID : Email Templates 페이지에서 발급
  • YOUR_USER_ID : Integration 페이지에서 API Keys에 User ID 확인

 

 

 

6. 코드

Email.JS

import React, { useCallback } from 'react';
import useInput from '../hooks/useInput';
import emailjs from 'emailjs-com';
import styled from 'styled-components';

const Form = styled.form`   
    margin: 0 auto;
    padding: 20px;  
    width: 400px;
    background: #ccc;
    text-align: center;

    input {
        padding: 5px 10px;
        width: 100%;
        border: 1px solid #666;

        & + input,
        & + textarea {
            margin-top: 20px;
        }
    }

    textarea {
        padding: 5px 10px;
        width: 100%;
        min-height: 100px;
        outline: none;
        resize: none;
        IME-MODE: auto;
    }

    button {
        margin-top: 20px;
        padding: 5px 15px;
        background: #fff;
        border: 1px solid #666;
        outline: none;
        cursor: pointer;
    }
`;

const Email = () => {
    const [name, onChangeName] = useInput('');
    const [email, onChangeEmail] = useInput('');
    const [text, onChangeText] = useInput('');

    const onSubmit = useCallback((e) => {
        e.preventDefault();

        const inputNum = e.target.childElementCount - 1; // [D] 버튼한개 제외
        const data = new FormData(e.target);
        const entries = data.entries();
        let failNum = 0;

        for (let i = 0; i < inputNum; i++) {
            const next = entries.next();
            const key = next.value[0];
            const value = next.value[1];

            if (!value) {
                failNum++;
                alert(`${key} 비어있습니다.`);
                break;
            }
        }

        if (!failNum) {
            emailjs.sendForm(
            	'YOUR_SERVICE_ID', 
                'YOUR_TEMPLATE_ID', 
                e.target, 
                'YOUR_USER_ID'
                
            ).then((result) => {
                console.log('result.text', result.text);

            }, (error) => {
                console.log(error.text);
            });
        }
    }, []);

    return (
        <Form onSubmit={onSubmit}>
            <input
                type="text"
                name="name"
                placeholder="이름"
                value={name}
                onChange={onChangeName}
            />

            <input
                type="text"
                name="email"
                placeholder="이메일"
                value={email}
                onChange={onChangeEmail}
            />

            <textarea
                name="text"
                placeholder="메세지"
                value={text}
                onChange={onChangeText}
            />

            <button type="submit">
                발송
            </button>
        </Form>
    );
};

export default Email;

 

 

 

useInput

커스텀 훅입니다.

import { useState, useCallback } from 'react';

export default (initialValue = null) => {
    const [value, setValue] = useState(initialValue);
    const handler = useCallback(({target}) => {
        setValue(target.value);
    }, []);

    return [value, handler, setValue];
};

 

 

 

7. 템플릿 수정 (EmailJS 대시보드 Email Templates 페이지)

코드 작업이 끝났으니 초반에 만들었던 Email Templates를 수정해줍니다.

input의 name값과 맞춰서 key 값을 삽입해주면 됩니다.

 

 

수정 아이콘을 눌러서 수정페이지로 이동합니다.

Email Tempalte 수정 방법

 

 

제목, 컨텐츠 모두 수정해주었습니다.

수정을 완료하였다면 Save를 눌러주세요.

Template 수정 페이지

 

 

 

8. 메일 발송 확인

이제 폼을 작성하여 발송을 눌러봅니다.

예시 폼

 

그 후 내가 서비스로 선택한 플랫폼의 메일함을 보면 메일이 도착합니다.

 

emailJS 템플릿 테스트 메일

 

 

내용도 수정된 것이 확인됩니다.

정상적으로 동작ㅎㅎ!

emailJS 템플릿 테스트 메일 컨텐츠

 

 

+ Recent posts