[작성자:] 수수께끼

  • [Linux] 리눅스 MySQL 시작, 정지, 재시작, 상태확인

    [Linux] 리눅스 MySQL 시작, 정지, 재시작, 상태확인

    리눅스 MySQL 시작, 정지, 재시작, 상태확인

    작업우분투 명령어CentOS6 명령어CentOS7 명령어
    시작# service mysql start# service mysqld start# systemctl start mysqld
    정지# service mysql stop# service mysqld stop# systemctl stop mysqld
    재시작# service mysql restart# service mysqld restart# systemctl restart mysqld
    상태확인# service mysql status# service mysqld status# systemctl status mysqld

    References

    리눅스 MySQL 시작, 정지, 재시작, 상태확인

  • [Nginx] Nginx 명령어

    [Nginx] Nginx 명령어

    명령어동작
    # systemctl status nginx상태 확인
    # sudo systemctl stop nginx웹서버 정지
    # sudo systemctl start nginx웹서버 재시작
    # sudo systemctl reload nginx설정 리로드
  • [Terminal] 맥 터미널 명령어

    [Terminal] 맥 터미널 명령어

    명령어Windows 커맨드Mac OS 터미널
    현재 디렉토리cdpwd
    현재 디렉토리 파일 리스트 보기dirls
    디렉토리 이동cdcd
    디렉토리 생성mkdirmkdir
    디렉토리 삭제rmdirrmdir
    화면 클리어clsclear
    null 파일 생성type NUL >touch
    파일 삭제delrm
    파일 이동movemv
    디렉토리 이름 바꾸기renmv
    Explorer/Finder 에서 열기startopen
  • [Terminal] 맥 터미널 쉘 접속

    [Terminal] 맥 터미널 쉘 접속

    윈도우에서는 Putty라는 프로그램으로 ssh접속을 하였지만 맥에서는 터미널로 바로 접속이 가능하다.

    $ ssh [ID]@[HOST]
    

    예를들어 webapp이 아이디이고 127.0.0.1가 호스트 번호 라면

    $ ssh webapp@127.0.0.1
    

    라고 입력한 뒤 패스워드를 입력하면 된다.

  • [JavaScript] 크롬으로 디버깅하기

    [JavaScript] 크롬으로 디버깅하기

    크롬 개발자 도구의 Sources패널로 디버깅을 할 수 있다.

    예제

    function hello() {
        return 'hello';
    }
    
    function world() {
        return 'world';
    }
    
    function greetinf() {
        var h = hello();
        var w = world();
        document.getElementById('msg').setAttribute('value', h + w);
    }
    
    <input type="text" id="msg" />
    <button type="button" onclick="greetinf()">click</button>
    

    버튼을 클릭하면 greetinf함수가 실행되며, h, w변수에 차례대로 값이 할당된 후 인풋 태그에 결과 값(helloworld)이 출력되는 구문이다.

    결과

    디버깅

    크롬 개발자 도구의 소스탭을 들어가면 아래 처럼 확인할 수 있다.

    개발자 도구는 특정 라인이 아닌 글로벌한 이벤트에 대해 중단점을 만들 수 있다. 좌측 하단의 Event Listener Breakpoints탭으로 들어가 Mouse > click를 체크해준다. 화면으로 넘어가 버튼을 클릭하면 이벤트가 실행되면서 이벤트가 실행된 코드를 소스탭에서 확인할 수 있다.

    1. Breakpoints

    중단점을 이용하면 실행이 중지된 시점에 변수가 어떤 값을 담고 있는지 알 수 있다. 또한 실행이 중지된 시점을 기준으로 명령어를 실행할 수도 있다.

    2. Pretty Print

    압축 파일(min)을 보기 좋게 정렬하여 볼 수 있다.

    3. Resume Script Execution(단축키: F8)

    스크립트 실행을 다시 시작한다. 추가 중단점이 없는 경우, 실행이 쭉 이어지고 디버거는 동작하지 않는다.

    4. Step (단축키 F9)

    다음 명령어를 실행한다. Step버튼을 계속 누르면 스크립트 전체를 문 단위로 하나하나 실행할 수 있다.

    5. Step over next function call(단축키 F10)

    다음 명령어를 실행하되, 함수 안으로 들어가진 않는다. Step과 유사하지만, 다음 문이 함수 호출일 때 Step과는 다르게 동작한다.(alert 같은 내장함수에는 해당하지 않고, 직접 작성한 함수일 때만 동작이 다르다.) Step은 함수 내부로 들어가 함수 본문 첫 번째 줄에서 실행을 멈춘다. 반면 Step over next function call은 보이지 않는 곳에서 중첩 함수를 실행하긴 하지만 함수 내로 진입하지 않는다. 함수 호출 시 내부에서 어떤 일이 일어나는지 궁금하지 않을 때 유용하다. 실행은 함수 실행이 끝난 후에 즉시 멈춘다.

    6. Step into next function call(단축키 F11)

    Step과 유사한데, 비동기 함수 호출에서 Step과는 다르게 동작한다. StepsetTimeout(함수 호출 스케줄링에 쓰이는 내장 메서드)같은 비동기 동작은 무시한다. 반면 Step into next function call는 비동기 동작을 담당하는 코드로 진입하고, 필요하다면 비동기 동작이 완료될 때까지 대기한다.

    7. Step out of current function(단축키 shift + F11)

    현재 실행 중인 함수의 실행을 계속 이어가다가 함수 본문 마지막 줄에서 실행을 멈춘다. 실수로 Step을 눌러 내부 동작을 알고 싶지 않은 중첩 함수로 진입했거나 가능한 한 빨리 함수 실행을 끝내고 싶은 경우 유용하다.

    8. Deactivate breakpoints

    모든 중단점을 일시적으로 활성화/비활성화한다.(실행에는 영향이 없음)

    9. Pause on excepoints

    활성화되어 있고, 개발자 도구가 열려있는 상태에서 스크립트 실행 중에 에러가 발생하면 실행이 자동으로 멈춘다. 실행이 중단되었기 때문에 변수 등을 조사해 어디서 에러가 발생했는지 찾을 수 있게 된다. 개발하다가 에러와 함께 스크립트가 죽었다면 디버거를 열고 이 옵션을 활성화한 후, 페이지를 새로고침하면 에러가 발생한 곳과 에러 발생 시점의 컨텍스트를 확인할 수 있다.

    10. Scope

    현재 정의된 모든 변수를 출력한다. Local은 함수의 지역변수를 보여준다. 지역 변수 정보는 소스 코드 영역에서도 확인(강조 표시)할 수 있다. Global은 함수 바깥에 정의된 전역 변수를 보여준다. Local 하위 항목으로 this에 대한 정보도 출력된다.

    11. Watch

    표현식을 평가하고 결과를 보여준다. Add watch expression 버튼을 클릭해 원하는 표현식을 입력한 후 Enter를 누르면 중단 시점의 값을 보여준다. 입력한 표현식은 실행 과정 중에 계속해서 재평가된다.

    Call Stack

    코드를 해당 중단점으로 안내한 실행 경로를 역순으로 표시한다.

    References

    Chrome으로 디버깅하기
    Chrome DevTools에서 자바스크립트 디버깅 시작하기
    크롬 개발자 도구를 이용한 자바스크립트 디버깅
    생활코딩 – Sources

  • [JavaScript] 자바스크립트 클로저

    [JavaScript] 자바스크립트 클로저

    정의

    중첩함수에서 내부함수가 외부함수의 환경을 기억하는것을 클로저라고 한다.

    function func() {
        var foo = 'data';
        return function() {
            return foo;
        }
    }
    

    func라는 함수를 선언하고 foo변수에 ‘data’문자열을 추가한 뒤 foo변수를 리턴하는 익명함수를 선언하였다.

    var closure = func();
    console.log(closure());
    // 'data'
    

    func함수의 리턴값을 closure변수에 할당한 뒤 closure를 실행한 값을 콘솔로 찍어보았다. 결과는 ‘data’라는 문자열이 출력되었다. func의 지역변수로 있는 foo는 func함수가 끝나면서 소멸되어야하지만 값을 잃지 않고 ‘data’값을 가지고 있다. 이 현상을 클로저라 한다. 다른 구문도 살펴보겠다.

    function count() {
        var num = 0;
        return function() {
            num++;
            return num;
        }
    }
    
    var closure = count();
    console.log(closure());
    console.log(closure());
    console.log(closure());
    // 1
    // 2
    // 3
    

    count함수의 지역변수인 num값이 소멸되지 않고 계속 카운트되는 것을 확인해 볼 수 있다.

    특징

    변수의 은닉화

    자바스크립트에서는 인스턴스를 생성할때 Private Variables에 대한 접근 권한 문제가 있다.

    function Create(name) {
        this._name = name;
    }
    
    var obj = new Create('민수');
    console.log(obj._name);
    // 민수
    

    위에서 생성된 obj객체의 _name프로퍼티는 변수명 앞에 _를 포함하였기 때문에 Private Variables로 쓰고싶다는 의도를 알 수 있다. 하지만 _name프로퍼티는 동적으로 변경될 수 있다.

    obj._name = '인성';
    console.log(obj._name);
    // 인성
    

    이 경우 클로저를 사용하여 외부에서 내부변수에 접근하는것을 제한할 수 있다.

    function create(name) {
        var _name = name;
        return function() {
            console.log(_name);
        }
    }
    
    var hello = create('민수');
    hello();
    // 민수
    

    여기서는 외부에서 _name에 접근할 방법이 전혀 없다. 이렇게 클로저를 활용하여 은닉화를 해결할 수 있다.

    고유한 환경

    클로저는 고유한 환경을 가지고 있다.

    function func(name) {
        var txt = name;
        return function() {
            return txt;
        }
    }
    
    var closure01 = func('민수');
    var closure02 = func('인성');
    var closure03 = func('한나');
    
    console.log(closure01()) // 민수
    console.log(closure02()) // 인성
    console.log(closure03()) // 한나
    

    위의 구문을 보면 txt변수가 동적으로 변화하는 것처럼 보이지만, 실제로는 txt변수 자체가 여러번 생성된 것이다. 즉, closure01(), closure02(), closure03()은 서로 다른 환경을 가지고 있다. 서로 다른 환경을 가지고 있다는것은 그만큼 메모리면에서 큰 비효율을 낳는다.

    function Func(input) {
        this.name = input;
        this.get = function() {
            return this.name;
        }
        this.set = function (rename) {
            this.name = rename;
        }
    }
    
    var obj = new Func('민수');
    console.log(obj.get());
    

    위 코드는 생성자함수를 사용하여 인스턴스를 생성하는 구문인데, 클로저가 두번(get, set)이나 생성되었다. 이 상태에서 인스턴스를 계속 만들면 같은일을 하는 클로저가 중복으로 생성되고 메모리낭비가 심해질 것이다.
    따라서 클로저는 객체의 prototype안에 저장함으로써 같은 기능을 모든 인스턴스가 공유하는 형태로 코드를 만들어야한다.

    function Func(input) {
        this.name = input;
    }
    Func.prototype.get = function() {
        return this.name;
    };
    Func.prototype.set = function(rename) {
        this.name = rename;
    };
    
    var obj = new Func('민수');
    console.log(obj.get());
    

    이렇게 prototype안에 클로저를 넣으면, 인스턴스가 생성되더라도 중복으로 메모리를 낭비하지 않고, 생성자 내부의 prototype안의 클로저를 참조하기 때문에 메모리낭비를 방지할 수 있다.

    정리

    • 클로저는 독립적인(자유) 변수를 가리키는 함수 또는 클로저 안에 정의된 내부함수는 만들어진 환경을 기억한다.
    • 클로저는 외부함수의 스코프 영역에 접근할 수 있고, 그것을 기억하고 있어야 한다.
    • 외부함수가 종료된 후에도 내부함수는 외부함수를 계속 참조하고 있어야 한다.
    • 데이터의 캡슐화 및 정보은닉에도 사용 가능하다.

    References

    JavaScript 클로저(Closure)

  • [JavaScript] 자바스크립트 모듈 패턴

    [JavaScript] 자바스크립트 모듈 패턴

    모듈 패턴이란?

    모듈이란 전제 어플리케이션의 일부를 독립된 코드로 분리하여 만들어 놓은 것이다.

    모듈화를 했을 때 장점

    • 자주 사용되는 코드를 별도의 파일로 만들어서 필요할 때마다 활용할 수 있다.
    • 코드를 개선하면 이를 사용하고 있는 모든 애플리케이션의 동작이 개선된다.
    • 코드 수정 시에 필요한 로직을 빠르게 찾을 수 있다.
    • 필요한 로직만을 로드해서 메모리의 낭비를 줄일 수 있다.
    • 한번 다운로드된 모듈은 웹브라우저에 의해서 저장되기 때문에 동일한 로직을 로드할 때 시간과 네트워크 트래픽을 절약할 수 있다.(브라우저에서만 해당)

    객체 리터럴을 사용한 모듈 패턴

    자바스크립트에서 모듈을 구현하는 가장 쉬운 방법은 객체 리터럴을 사용하는 방법이다.

    var module = {
        key: 'data',
        publicMethod: function() {
            return this.key;
        }
    }
    
    console.log(module.key); // data
    console.log(module.publicMethod()); // data
    

    객체 리터럴은 모듈 패턴이기도 하며, 하나의 객체라는 점에서 싱글톤 패턴이라고도 할 수 있다. 동일한 코드를 어떠한 관점에서 보느냐에 따라 다양한 패턴이 될 수 있다. 객체 리터럴은 간단하지만 모든 속성이 공개되어있다는 단점이 있다. 독립된 모듈은 자체적으로 필요한 내부 변수 및 내부 함수를 모두 갖고 있어야 하므로 클로저를 이용해야 한다.

    아래는 클로저를 활용한 모듈패턴이다.

    클로저를 활용한 모듈 패턴

    var module = (function() {
    
        /**
            * -----------------------
            * 모듈 패턴을 구현할 클로저 코드
            * -----------------------
            */
    
        // 은닉될 멤버 정의
        var privateKey = 0;
        function privateMethod() {
            return privateKey++;
        }
    
        // 공개될 멤버(특권 메서드) 정의
        return {
            publicKey: privateKey,
            publicMethod: function() {
                return privateMethod();
            }
        }
    
    })();
    
    console.log(module.publicMethod()); // 0
    console.log(module.publicMethod()); // 1
    

    모듈 패턴의 반환값은 함수가 아닌 객체이다. 위의 코드를 순서대로 보면 익명함수가 자동으로 실행되고 반환된 객체를 module 변수에 할당한다. 따라서 module.publicMethod()처럼 메서드를 호출할 수 있다. 자동 호출되는점을 제외하고 클로저와 유사하다.

    클로저 경우

    function func() {
        var private = 0;
        return function() {
            private++;
            return private;
        }
    }
    var val = func();
    console.log(val()); // 1
    console.log(val()); // 2
    

    그리고 인스턴스를 여러개 만들어 낼 수 있는 구조라는 점에서 싱글톤 패턴과 차이가 있다.

    싱글톤 패턴 경우

    var singleton = (function() {
    
        var instance;
        var private = 0;
        function init() {
            return {
                publicKey: private,
                publicMethod: function() {
                    return publicKey;
                }
            }
        }
        return function() {
    
            // 싱글톤 패턴은 아래 조건문에서 처음 인스턴스가 선언되면 다시 인스턴스를 만들지 않고 기존의 인스턴스를 리턴한다.
            if (!instance) {
                instance = init();
            }
            return instance;
        }
    })()
    
    var singleton1 = singleton();
    var singleton2 = singleton();
    console.log(singleton1 === singleton2); // true
    

    하나의 인스턴스를 선언하지 않고 여러개의 인스턴스를 생성하려면 익명함수를 사용하지 않고 생성자 함수 방식으로 만들면 된다.

    var Module = function() {
    
        var privateKey = 0;
        function privateMethod() {
            return privateKey++;
        }
    
        return {
            publicKey: privateKey,
            publicMethod: function() {
                return privateMethod();
            }
        }
    
    }
    
    var obj1 = Module();
    console.log(obj1.publicMethod()); // 1
    console.log(obj1.publicMethod()); // 2
    
    var obj2 = Module();
    console.log(obj2.publicMethod()); // 1
    console.log(obj2.publicMethod()); // 2
    

    위처럼 Module 함수를 정의하여 함수를 호출하면 여러개의 인스턴스를 생성할 수 있다. 클로저 인스턴스와 유사하지만, 한가지 차이점은 내부의 익명함수에서 반환값이 함수가 아니라 객체를 반환한다는 점이다.

    모듈 패턴과 네임 스페이스 패턴을 함께 사용하면 더욱 깔끔한 코드가 완성된다.

    var app = app || {};
    app.module = (function() {
    
        var privateKey = 0;
        function privateMethod() {
            return privateKey++;
        }
    
        return {
            publicKey: privateKey,
            publicMethod: function() {
                return privateMethod();
            }
        }
    })();
    
    console.log(app.module.publicMethod()); // 0
    console.log(app.module.publicMethod()); // 1
    

    References

    module pattern (모듈패턴) #1
    [JS_Design Pattern] 2. 모듈 패턴 (Module Pattern)

  • [JavaScript] ES6 클래스(Class)

    [JavaScript] ES6 클래스(Class)

    ES6에서 class라는 문법이 추가되었고, 기존의 prototype 기반으로 클래스를 선언하는 것보다 명료하게 클래스를 선언할 수 있게 되었다.

    기존(ES5) 클래스(생성자)

    함수를 만들 때는 함수 표현식과 선언식이 있으며, 선언식으로 작성한 클래스는 호이스팅이 일어난다. 여기서 호이스팅이란 함수를 선언했을 때 값들이 유효범위 최상단에 선언되는 것을 말한다.

    함수 표현식

    클래스가 선언되기 전에 인스턴스를 생성하여 에러가 뜬다.

    var obj = new Person('한나');
    obj.getName(); // TypeError
    
    var Person = function(name) {
        this.name = name;
        Person.prototype.getName = function() {
            console.log(this.name);
        }
    }
    

    함수 선언식

    인스턴스를 함수 선언 전에 생성해도 오류가 나지 않는다. 클래스를 선언식으로 작성하여 호이스팅되었기 때문이다.

    var obj = new Person('한나');
    obj.getName(); // 한나
    
    function Person(name) {
        this.name = name;
        Person.prototype.getName = function() {
            console.log(this.name);
        }
    }
    

    새로운(ES6) 클래스(생성자)

    class Person {
        constructor(name) {
            this.name = name;
        }
        getName() {
            console.log(this.name);
        }
    }
    
    const obj = new Person('민수');
    obj.getName(); // 민수
    

    위 코드는 새로운 클래스 키워드로 클래스를 선언하고 인스턴스를 만든 것이다. 함수 선언이 표현식과 선언식이 있듯이 클래스 키워드도 선언식과 표현식 두가지 방법으로 정의가 가능하다.

    const obj = new Person('민수');
    obj.getName(); // ReferenceError
    
    class Person {
        constructor(name) {
            this.name = name;
        }
        getName() {
            console.log(this.name);
        }
    }
    

    위 코드는 에러를 출력하고 있다. 이유는 새로운 클래스는 호이스팅이 일어나지 않는다. 아니 엄밀히 말해 호이스팅이 발생하지 않는 것처럼 동작하는건데 이거는 추후에 알아보도록 하겠다.

    constructor

    constructor는 인스턴스를 생성하고 클래스 필드를 초기화하기 위한 특수한 메서드이다.

    클래스 필드(class field) 클래스 내부의 캡슐화된 변수를 말하며, 데이터 혹은 멤버 변수라고 부른다. 자바스크립트의 생성자 함수에서 this에 추가한 프로퍼티를 클래스 기반 객체지향 언어에서는 클래스 필드라고 부른다.

    class Person {
        constructor(name) {
            // 여기서 this는 생성될 인스턴스를 바라보고 있다.
            this.name = name;
        }
    }
    

    constructor는 클래스 내에 한 개만 존재할 수 있으며 이 함수 안에 프로퍼티를 작성하면 되며, 이 안에서 this는 생성될 인스턴스를 바라보고 있다.

    메서드 정의

    class Person {
        constructor(name) {
            this.name = name;
        }
        // 클래스 몸체에는 메서드만 선언할 수 있다.
        getName() {
            console.log(this.name);
        }
    }
    

    클래스 몸체 안에는 메서드만 선언할 수 있다. 클래스 몸체 안에 프로퍼티를 선언하면 오류를 출력한다.

    extends

    ES6 클래스는 extends키워드로 상속을 구현한다.

    class Wrap {
        constructor(name) {
            this.name = name;
        }
        getName() {
            console.log(this.name + ' 슈퍼');
        }
    }
    
    class Inner extends Wrap {
        getName() {
            super.getName()
            console.log(this.name + ' 상속 받은 클래스');
        }
    }
    
    var obj = new Inner('안녕');
    obj.getName();
    
    // 결과
    // 안녕 슈퍼
    // 안녕 상속 받은 클래스
    

    위 코드를 보면 InnerWrap를 상속 받았으며, new Inner('안녕')를 실행하면 아래의 과정을 거치게 된다.

    1. Inner클래스의 constructor를 호출
    2. Inner클래스의 constructor를 작성하지 않았기 때문에 super클래스(Wrap)의 constructor가 호출됨(내부적으로 프로토타입 체인으로 인해)
    3. super클래스의 constructor에서 this는 현재의 인스턴스를 참조하므로 인스턴스의 name프로퍼티로 전달받은 값을 설정
    4. 생성한 인스턴스를 Inner에 할당

    super

    위에 코드에서도 잠깐 나왔지만 super키워드는 슈퍼 클래스의 메서드를 호출할 수 있다.

    class Wrap {
        msg() {
            console.log('안녕');
        }
    }
    
    class Inner extends Wrap {
        msg() {
            // 슈퍼 클래스의 msg메서드를 실행한다.
            super.msg();
        }
    }
    
    var obj = new Inner();
    obj.msg();
    

    static

    static키워드는 클래스를 위한 정적(static) 메서드를 정의한다. 정적 메서드는 prototype에 연결되지 않고 클래스에 직접 연결되기 때문에 클래스의 인스턴스 없이 호출되며, 클래스의 인스턴스에서는 호출할 수 없다.

    class Inner {
    
        // 인스턴스 없이 클래스에 바로 메서드를 선언해줌
        static msg() {
            console.log('안녕');
        }
    }
    
    Inner.msg(); // 안녕
    
    var obj = new Inner();
    obj.msg(); // TypeError
    

    동일한 클래스 내의 다른 정적 메서드 내에서 정적 메서드를 호출하는 경우 키워드 this를 사용할 수 있다.

    class Inner {
        static msg() {
            console.log('안녕');
        }
        static msg2() {
            this.msg();
        }
    }
    
    Inner.msg2(); // 안녕
    

    정적 메서드는 어플리케이션을 위한 유틸리티 함수를 생성하는데 주로 사용된다.

    References

    [JS] javascript – OOP Class, Super
    ES6 Class 파헤치기
    super
    클래스

  • [Git] 터미널 계정 변경 방법(Windows)

    [Git] 터미널 계정 변경 방법(Windows)

    1. 현재 깃에 설정된 계정/메일 확인

    $ git config user.name
    $ git config user.email
    

    터미널에서 위 명령어로 현재 설정된 계정/메일을 확인할 수 있다.

    2. 원하는 깃 계정/메일 변경

    $ git config --global user.name 변경을 희망하는 계정
    $ git config --global user.email 변경을 희망하는 이메일
    

    위 명령어로 계정/메일을 변경할 수 있다.

    3. Push 오류 확인

    계정을 변경하고 푸쉬를 하면 아래와 비슷한 오류가 나온다.
    아래 오류를 해결하러면 Windows 자격 증명을 변경해야 한다.

    remote: Permission to bitnaleeeee/bitnaleeeee.github.io.git denied to recordboy.
    fatal: unable to access 'https://github.com/bitnaleeeee/bitnaleeeee.github.io.git/': The requested URL returned error: 403
    

    4. Windows 자격 증명 변경

    자격 증명 변경 경로

    제어판 > 사용자 계정 > 자격 증명 관리자 > Windows 자격 증명

    자격 증명 변경 과정

    1. 제어판 > 사용자 계정

    2. 제어판 > 사용자 계정 > 자격 증명 관리자

    3. 자격 증명 관리자 > Windows 자격 증명 > 일반 자격 증명 > git:https://github.com 제거

    4. 자격 증명 관리자 > Windows 자격 증명 > 일반 자격 증명 > 일반 자격 증명 추가

    5. 일반 자격 증명 추가 > 정보 입력하고 확인

    1. 인터넷 또는 네트워크 주소: https://api.github.com/변경할 계정
    2. 사용자 이름: 변경할 계정
    3. 암호: 변경할 계정 암호

    6. 깃허브 인증 팝업 출력 > Sign in with your browser 클릭

    7. 깃허브 인증 팝업 출력 > Authorize GitCredentialManager 클릭하면 인증 성공

    8. 다시 Git Push 제대로 되는지 확인

    References

    [Git] Git Bash 터미널 계정 변경 방법! (Windows)

  • [Server] Vercel에 JSON Server 배포

    [Server] Vercel에 JSON Server 배포

    Heroku는 2022년 11월을 기준으로 유로로 변경되었기 때문에 무료로 서버를 배포할 플랫폼을 찾던중 Vercel를 알게되었다. JSON Server와 Vercel를 이용하면 간략한 서버를 구축 및 배포할 수 있다.

    JSON Server

    내부적으로 Low DB 라는 단순한 데이터베이스를 이용하며 최소한의 REST API를 기본 지원한다. 프로토타입을 만들거나 토이프로젝트를 만들때 유용하게 사용할 수 있다.

    공식 홈페이지: json-server

    Vercel

    Next.js 개발 팀에서 만든 클라우트 플랫폼으로 빌드/배포/호스팅 서비스를 제공한다. GitHub 저장소와 연결하면 매번 Push를 진행할 때 마다 배포할 수 있다.

    공식 홈페이지: Vercel

    JSON Server 만들기

    1. 프로젝트 생성

    $ mkdir json-server-exam && cd json-server-exam
    $ npm init -y
    $ npm install json-server --save-dev
    

    json-server-exam 디렉토리 생성 && 프로젝트 초기화를 한 뒤 JSON Server를 설치한다.

    2. server.js 추가

    const jsonServer = require('json-server')
    const server = jsonServer.create()
    const router = jsonServer.router('db.json')
    const middlewares = jsonServer.defaults()
    
    // Set default middlewares (logger, static, cors and no-cache)
    server.use(middlewares)
    
    // Add custom routes before JSON Server router
    server.get('/echo', (req, res) => {
      res.jsonp(req.query)
    })
    
    // To handle POST, PUT and PATCH you need to use a body-parser
    // You can use the one used by JSON Server
    server.use(jsonServer.bodyParser)
    server.use((req, res, next) => {
      if (req.method === 'POST') {
        req.body.createdAt = Date.now()
      }
      // Continue to JSON Server router
      next()
    })
    
    // Use default router
    server.use(router)
    server.listen(3001, () => {
      console.log('JSON Server is running')
    })
    

    서버로 사용할 server.js파일을 루트 경로에 추가해 준다.

    3. db.json 추가

    {
      "todos": [
        {
          "id": 1,
          "content": "HTML",
          "completed": true
        },
        {
          "id": 2,
          "content": "CSS",
          "completed": false
        },
        {
          "id": 3,
          "content": "Javascript",
          "completed": true
        }
      ],
      "users": [
        {
          "id": 1,
          "name": "bitna",
          "role": "developer"
        },
        {
          "id": 2,
          "name": "seongju",
          "role": "designer"
        }
      ]
    }
    

    DB로 사용할 db.json 파일을 루트 경로에 추가해준다.

    4. 서버 실행

    $ npm start
    

    서버를 실행하고 http://localhost:3001경로에 들어가면 실행된 JSON Server를 확인할 수 있다. 이제 아래와 같은 REST API를 이용할 수 있다.

    REST API

    기능MethodPath
    목록조회GET/todos
    추가POST/todos
    삭제DELETE/todos/:id
    수정PUT/todos/:id

    REST API 요청 예시(Fetch API 사용)

    GET(조회)

    fetch("http://localhost:3001/todos",)
    .then((response) => response.json())
    .then((data) => {
        // code..
    });
    

    POST(추가)

    fetch("http://localhost:3001/todos", {
        method: "POST",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            "id": 5,
            "content": "React",
            "completed": true
        }),
    })
    .then((response) => response.json())
    .then((data) => {
        // code..
    });
    

    DELETE(삭제)

    fetch("http://localhost:3001/todos/1", {
        method: "DELETE"
    });
    

    PUT(수정)

    fetch("http://localhost:3001/todos/2", {
        method: "PUT",
        headers: {
            "Content-Type": "application/json",
        },
        body: JSON.stringify({
            "id": 2,
            "content": "Linux",
            "completed": false
        }),
    })
    .then((response) => response.json())
    .then((data) => {
        // code..
    });
    

    Vercel 배포하기

    1. 배포하기 전에 추가 설정파일 만들기

    배포하기 전에 몇가지 설정파일을 추가해 준다.

    깃 이그노 추가

    GitHub 저장소에 올리기전에 루트 경로에 꼭 .gitignore 파일을 추가하고 아래 리스트를 추가해 준다.

    /node_modules
    

    Vercel 설정 파일 추가

    Vercel 배포 설정을 위해 루트 경로에 vercel.json 파일을 추가하고 아래 내용을 넣어준다.

    {
      "version": 2,
      "builds": [
        {
          "src": "server.js",
          "use": "@vercel/node",
          "config": {
            "includeFiles": ["db.json"]
          }
        }
      ],
      "routes": [
        {
          "src": "/(.*)",
          "dest": "server.js"
        }
      ]
    }
    

    2. GitHub 저장소에 올리기

    GitHub 저장소에 새로운 저장소를 만든 뒤 프로젝트를 올려준다.(GitHub에 프로젝트를 올리는 설명은 생략한다.)

    3. 회원 가입

    Vercel 공식 홈페이지(https://vercel.com)에서 회원가입을 한다. GitHub 계정으로 로그인 해준다.

    4. 새로운 프로젝트 추가하기

    Add New >> Project 버튼을 클릭한다.

    추가했던 프로젝트(저장소)를 import 한다.

    5. 옵션 설정 및 배포하기

    Build and Output Settings 메뉴에서 빌드 및 배포 설정을 할 수 있다. 여기서는 따로 vercel.json 파일을 추가했으니 설정은 건너 뛰고 바로 배포(Deploy) 버튼을 클릭한다.

    6. 배포 완료

    배포가 잘 되었다면 위처럼 화면을 확인할 수 있다.

    References

    JSON Server
    How to deploy an Express API to Vercel
    14.3 JSON Server
    30초 안에 RESTful API서버 만들기