갑자기 잘 사용하던 소스트리를 클릭했을 때 로고만 나오고 실행되지 않았다.

 

여러 가지 방법을 사용했지만 끝끝내 되지 않아서 

 

C:\Users\username\AppData\Local\Atlassian\

내에 있는 Url 어쩌구 폴더 내 모든 파일을 삭제했더니 해결됐다 ㅠ

 

username은 개인마다 다르므로 참고.

(나는 해당 폴더내 파일을 다 지우고도 local 저장소나 세팅값은 그대로였다)

 

 

▲ 위 폴더 들어가서 파일 전체 삭제 후 재실행

 

 Destructuring이 마치 냉장고에서 샌드위치 재료를 꺼내듯 원하는 프로퍼티(속성)을 추출해서 손쉽게 사용한다(변수에 바인딩 한다)는 개념을 이전 글에서 배웠습니다. 쉽게 말해, Object Destructuring은 냉장고(객체) 속 음식재료(프로퍼티)를 변수(냄비)에 넣어 사용한다고 볼 수 있습니다.

 

 Array Destructuring에 대해 짧게 알아봤지만, Array도 중요하지만 Object Destructuring 또한 너무나 중요한 개념이기 때문에 이번에 배워보겠습니다. 먼저, JavaScript에서의 'Object'는 무엇일까요?

 

 

Object


먼저 객체에 대해 짧게 알아보겠습니다.

JavaScript는 객체기반 프로그래밍이라고도 하죠. 자바스크립트를 구성하는 거의 모든 것들은 객체라고 할 수 있습니다. 객체는 최종적으로 0개 이상의 프로퍼티 집합으로 볼 수 있으며, 프로퍼티란 {Key:Value}라고 볼 수 있습니다.

 

Object(객체) : 키(key)와 값(value)으로 구성된 프로퍼티(property)정렬되지 않은 집합

 

  • JavaScript의 기본 타입(data type)은 객체(Object)입니다.
  • JavaScript에서 숫자, 문자열, 불리언, undefined 타입 (즉, 원시 타입)을 제외한 모든 것이 객체입니다.
  • 숫자, 문자열, 불리언, undefined과 같은 원시 타입은 객체가 아니지만, 값이 정해진 객체로 간주되어 객체로서의 특성도 가집니다.
  • 프로퍼티의 값으로 함수(function)이 올 수 있는데, 이 때 이 것을 메서드(method)라고 부릅니다.
// 객체 person
var person = {
	// 프로퍼티 키(Key) : 프로퍼티 값(Vaule)
	name: 'hwonda',		// 프로퍼티 1
	age: 30			// 프로퍼티 2
}

△ 위와 같이 객체는 프로퍼티 집합으로 볼 수 있습니다.

 

var person = {
    distance: 0,
    // 객체 속 프로퍼티 키가 '함수'인 경우, 이를 '메서드'라고 부른다.
    // 객체 'person' 내의 메서드 'walking'
    walking: function() {
    	distance++;
    }
}

△ 이처럼 메서드는 프로퍼티(key:value형태의 data)를 참조하고 조작할 수 있는 동작(like function)입니다.  

 

// ES6
let a = 0;
let b = 1;

// ES6 문법으로 프로퍼티 값으로 변수를 사용할 때
// 변수이름 == 프로퍼티 키라면
// 프로퍼티 키를 생략할 수 있습니다.
const obj = {a, b};

console.log(obj);  // {a: 0,b: 1}

이 내용을 잘 기억해주세요! 아래 Object Destructuring ES6문법에서 참고할 예정입니다.

 

 

Object Destructuring


 객체 추출은 다음과 같이 진행됩니다.

// 변수선언 = 객체 혹은 프로퍼티
//
// 그러면 내가 만든(객체의 필요한 data를 가지는) 새 변수를 마음껏 쓸 수 있지.

 

 ES5 문법으로 객체 추출을 하기 위해서는 프로퍼티 키(Key)를 사용합니다.

// ES5
var obj = {a: 1, b: 2};

var one = obj.a;
var two = obj.b;

console.log(one, two);	// 1 2

위와 같은 경우, 마침표 프로퍼티 접근 연산자(.)를 사용했습니다.

 

 마침표 외에 대괄호 프로퍼티 접근 연산자([ ])도 사용 가능합니다.

// ES5
var obj = {a: 1, b: 2, 10: '이것도 돼?'}

// 대괄호로 프로퍼티를 가져오는 경우, 프로퍼티 키는 '따옴표' 안에 넣어야 합니다.
var one = obj['a'];
console.log(one);	// 1

// 그렇지 않는 경우 다음과 같은 에러가 뜹니다.
var two = obj[b];
console.log(two);	// Uncaught ReferenceError: b is not defined

// 신기하게도, 프로퍼티 키가 숫자인 경우 '따옴표'는 생략 가능합니다.
var ten = obj[10];
console.log(ten);	// '이것도 돼?'

 

ES6 문법에서의 Object Destructuring 방법은 다음과 같습니다.

const obj = {a: 1,b: 2}

const {one, two} = obj;

console.log(one, two);	// undefined undefined

아차! ES6 문법에서 축약식 표현을 하기 위해서는 프로퍼티 키와 변수명을 동일하게 해줘야 했습니다.

const obj = {a: 1,b: 2}

// 변수명의 순서를 바꿔도, 프로퍼티 키를 기준으로 할당(추출)되므로 a=1, b=2가 됩니다.
const {b, a} = obj;

console.log(a, b);	// 1 2

 

그렇다면 변수를 객체로 준다면 어떻게 될까요?

// ES5
// one이라는 변수에 'a'값을, two라는 변수에 'b'값을 넣어준다.
const {prop1:one, prop2:two} = {prop1:'a', prop2:'b'}
console.log(one, two);	// a b

// ES6에서는 변수명과 프로퍼티 키만 동일하게 설정해주면 된다.
const {one, two} = {one:'a', two:'b'}
console.log(one, two);	// a b

 

객체 추출 중 가장 현업에서 자주 사용하는 기능은 필요한 프로퍼티 값만 추출하는 것입니다. 예제는 다음과 같습니다.

const weather = [
	{ id: 'sunny', image: 'sun', isToday: false},
    { id: 'rainy', image: 'rain', isToday: false},
    { id: 'windy', image: 'wind', isToday: true}
];

const todayWeather = weather.filter(({isToday}) => isToday);
console.log(todayWeather)  
// 먼저 원하는 객체가 결과로 나온다.
//{id: 'windy', image: 'wind', isToday: true}
// 객체 단 1개이므로, length는 1이다.
//length: 1
//[[Prototype]]: Array(0)

 

 우리는 이전 글을 통해

  1. 원격 저장소에 있는 리파지토리를 로컬 저장소로 가져오는 방법(clone, pull)
  2. 로컬 저장소와 원격 저장소를 연결하는 방법(remote) 

에 대해 알아보았습니다.


 그런데 git clonegit pull, 이 둘은 어떤 차이가 있고 언제 사용하는 걸까요? 결론부터 말씀드리겠습니다.

git clone은 로컬 히스토리를 유지하지 않고, git pull은 로컬 히스토리를 유지합니다.

 

  특징 기존추적기록 remote merge 사용시기
git clone 원격 리파지토리를 그대로 복붙한다(copy). X O X 프로젝트 시작 시
git pull 내 상태를 유지하면서 원격 리파지토리 내용을 내려받는다. O X O 프로젝트 진행 중(작업 전)

 

 

 다음과 같이 git clone은 원격 저장소의 내용을 로컬 저장소에 그대로 이전시켜 버립니다. 이 때, 자동으로 원격 저장소(remote)의 이름이 'origin'으로 저장됩니다. 따라서 나중에 git fetch origin을 한다면 clone 이후 수정된 사항에 대해 업데이트할 수 있습니다.

 

git clone했을 때, 원격저장소 이름은 origin이 됩니다.

 

 

 git pull은 git clone과 비슷하게 내용을 이전시키는 것은 맞지만, 나의 branch의 상태를 유지하면서 내용만 내려받습니다. 이 때, 내 로컬 히스토리가 유지되는 상태이기 때문에 히스토리 싱크가 맞지 않으면 오류가 발생합니다. (병합 충돌)

→ 이로 인해 초보자의 경우, branch가 꼬이는 경우가 많아 git pull보다 git clone을 해버리는 경우가 왕왕 있습니다.

 

▽ git pull의 형식은 다음과 같습니다.

$ git pull [remote] [branch]

▽ 그리고 git clone과 동일한 작업을 수행하려면 다음과 같습니다.

$ git pull origin master

: remote의 이름을 origin, branch 이름을 master로 하면, 로컬의 master가 원격의 master를 추적하는 git clone과 동일한 작업을 수행할 수 있습니다.

 


git fetch


 사실 git clone과 git pull을 비교하기보다 git fetch와 git pull를 비교하는 게 일반적입니다.

 

$ git fetch [remote]

 : 로컬에는 없지만 원격 저장소에 있는 모든 데이터를 가지고 옵니다. 하지만, 자동으로 로컬 branch에 merge시키는 git pull과는 달리, 내용만 가져오는 것이기 때문에 merge를 따로 수행해야 합니다.

 

$ git checkout [병합할 줄기 branch]
$ git merge [병합당하는 가지 branch]

: 가지 branch 줄기 branch로 병합됩니다.

 

error : git add이 안되고 다음과 같은 메세지가 출력됩니다.

 

reason : git 리파지토리(.git 폴더)가 없기 때문입니다.

 

solution : git init 명령어를 이용해 git repository를 생성 후 git add를 진행합니다.

 

$ git init

 

git init 전
git init 후

 ※ Mac을 쓰는 경우, 해당 디렉토리에서 command + shift + . 을 누르면 숨김폴더(.git 등)을 볼 수 있습니다.

 

git init 후 정상적으로 git add가 동작함

'etc > git fatal' 카테고리의 다른 글

[Git Error] fatal: Not a valid object name: 'master'.  (0) 2023.01.07

 

 이전 글을 통해 우리는 git clone, git pull을 이용해 원격 저장소에 있는 프로젝트를 로컬 저장소인 내 컴퓨터로 옮겨보았습니다.

 

그러면 내가 로컬 저장소에서 작업한 내용은 원격저장소까지 어떤 방식으로 업로드할 수 있을까요?

 

제목에서 알 수 있듯, git add, git commit, git push를 통해 우린 로컬저장소 → 원격저장소로 작업 내용을 업로드할 수 있습니다.

 

  • Working Directory : 작업 공간. 파일의 생성/수정/삭제가 이루어지는 공간.
  • Staging Area : 버전이 될 후보들이 올라오는 공간. commit을 하기 전 임시 저장되는 세이브 포인트.
  • Local Repository : 로컬 저장소. 
  • Remote Repository : 원격 저장소.

 

위의 일련의 과정을 과일추수에 빗대어 설명하자면, 다음과 같습니다.

 

git add : 다 익은 과일만(저장하고자 하는 파일)을 선별해 상자(임시저장소)에 담음.

git commit : 상자에 담긴 과일들을 창고(로컬 저장소)에 쌓음.

git push : 창고에 있는 과일상자들을 모두가 살 수 있는 마트(github-원격저장소)로 이동시킴.

 

(git pull은 과일 반품..?)

 

git status


 사실 git add, commit, push를 진행하기 전에 수행해야될 일들이 있습니다.

$ git status

: git status는 현재 git의 파일 관리상태를 알려줍니다.

 

▽ 현재 상태를 파악하게 해주는 3 문단.

 

  • 1문단 : 현재 당신의 branch는 origin/master입니다.
  • 2문단 : Staging Aread에 commit되지 않은 다음 파일(README.md)이 있습니다. 
  • 3문단 : Untracked files나 변경사항에 대해 알려줍니다. 또 이 파일들을 추가하기 위해 git add나 git commit -a를 이용하라고 설명합니다.

위 내용을 토대로 현재 나의 branch가 어떠한지, 어떤 파일이 commit되지 않았는지, 관리대상에 포함되지 않은 파일들은 없는지 확인이 가능합니다.

 

 

git add


 git add내가 추가하고자 하는 파일을 선택하는 과정으로 볼 수 있습니다.

 아직 관리 대상은 아니지만, 앞으로 관리할 대상을 선별하는 것이죠.

 

 

$ git add 파일경로

: 해당 경로에 있는 파일을 add합니다.

 

▽README.md를 수정한 뒤 status를 확인해보면, README.md가 Staged된 것을 볼 수 있습니다.

 

만약 잘못 add 했다면, 다음과 같은 명령어를 실행하면 됩니다.

$ git restore --staged 파일경로

: 해당 경로에 있는 파일의 staged 상태를 unstaged 상태로 변경합니다.

 

$ git add .

: 현재 디렉토리에 있는 모든 파일을 add합니다.

 

$ git add -A

: 프로젝트 내 모든 파일을 add합니다. (현재+상위 디렉토리)

 

 

 

git commit


 git add를 통해 선별된 파일들을 git commit을 이용하여 소스 관리 대상에 올립니다.(로컬 저장소에 저장됨)

commit에는 커밋 메세지가 들어갑니다. 이 메세지를 통해 팀원들이 해당 파일들이 어떤 기능 혹은 어떤 수정 등이 이루어졌는지 알 수 있습니다. 따라서 커밋 메세지는 현재 버전에 대한 내용을 명확하게 전달해야하기에 어느정도 정해진 형식을 지켜야 합니다.

 

$ git commit -m "커밋메세지"

: -m은 commit의 대표적인 옵션입니다. commit message가 중요한만큼 에디터를 통해 작성하는 경우가 있기 때문입니다.

  • -m : vim(에디터)에서 별도의 메세지를 작성할 필요없이 인라인 형식으로 바로 커밋 메세지 작성합니다.
  • -a : 수정된 파일에 대한 add와 commit을 한꺼번에 수행합니다. (한 번도 add되지 않은 파일은 add 후 -a 옵션적용이 가능합니다.)
  • -am : -m과 -a의 옵션을 합친 것입니다.

그러나 통상적으로 인라인(In-line)형식으로 작성하기 때문에 자세히 알 필요는 없습니다.

 

 

 

git push


git push를 통해 우리는 드디어 로컬 저장소에 저장된 파일을 원격 저장소(github, google drive 등)에 업로드할 수 있습니다. 

 

$ git push [remote] [branch]

: git push를 하는 경우 뒤에 현재 remote, branch 값을 적어주는데, 위 예제와 같이 origin/master라면 다음과 같이 명령하면 됩니다.

$ git push origin master

 

▽ README.md에 'this is hwonda' 문구를 넣고 add / commit / push 를 진행합니다.

 

▽ add / commit / push 하기 전.

 

▽ push 이후에 원격 저장소에 변경 사항이 적용됩니다.

 

error : git branch 명령을 통해 새로운 branch를 만드려고 했지만, 위와 같은 메세지가 출력되면서 branch는 만들어지지 않습니다.

 

reason : master branch에서 commit을 수행하지 않았기 때문입니다.

 

solution : master branch에서 git add, git commit을 수행합니다.

 

$ git add .

$ git commit -m "[커밋내용]"

$ git branch [새 branch 이름]

$ git checkout [새 branch 이름]

// 모든 branch 확인
$ git branch

 

 

 깃허브에 있는 코드를 내 컴퓨터로 가져오고 싶으신가요? 그렇다면 아래 내용을 잘 읽어보시기 바랍니다.

 

 깃허브(github.com) 사이트 내에 있는 레파지토리는 이전 글에 설명한 바와 같이 원격저장소에 저장됩니다. 내 PC에서 작업하는 내용은 로컬저장소에 저장됩니다. 원격저장소 -> 로컬저장소로 파일을 이동하고 싶으면, git clone 혹은 git pull을 하면 됩니다. 이 둘은 비슷하지만 약간의 차이점이 있습니다. git pull은 merge를 자동진행하는 특징을 가지는데, 이 것은 다음 글에 설명하도록 하겠습니다.

 

 먼저, 다음과 같이 로컬저장소(내 PC)에 폴더를 3개 만들어 진행해보겠습니다.

  • helloworld_01 : Terminal을 이용하여 git clone
  • helloworld_02 : VScode를 이용하여 git clone
  • helloworld_03 : Terminal을 이용하여 git pull

 

 

Terminal로 git clone


 

△ 1. github에서 복제하고싶은 레파지토리의 주소를 복사합니다. 긴 네모상자의 주소를 드래그해서 복사하거나, 화살표 부분의 버튼을 누르면 자동 복사됩니다.

 

 

△ 2. helloworld_01 폴더를 열고 들어가 Terminal을 엽니다. 그리고 다음과 같은 명령을 입력합니다.

$ git clone [복사한 레파지토리 주소]

그러면 원격저장소에 있는 README.md 파일이 내 PC로 들어온 것을 알 수 있습니다.

 

 

 

VScode로 git clone


 

△ 1. VScode 홈화면의 Clone Git Repository를 누릅니다.

 

 

△ 2. 활성화된 상단 바에 복제할 리포지토리 URL을 복붙합니다.

 

 

△ 3. 복제를 진행할(리포지토리 대상으로 선택할) 폴더를 선택합니다.

 

 

△ 4. 요렇게 신뢰하십니까? 나오면 Yes 누르시면 됩니다.

 

 

△ 5. 그러면 내가 고른 파일에 해당 리포지토리가 복제된 것을 확인할 수 있습니다.

 

 

 

Terminal로 git pull


 git clone은 원격저장소의 리파지토리를 일방적으로 로컬저장소 폴더로 옮기는 명령입니다. git clone만을 위해서는 두 저장소를 연결(remote)하지 않아도 됩니다.

 반면, git pull을 하기 위해서는 로컬저장소를 원격저장소와 연결(remote)해줘야 합니다. (remote : 로컬저장소 <-> 원격저장소)

 

$ git remote -v
// 현재 연결된 원격저장소를 알려줌. (아무 것도 안 뜨면, 연결되지 않은 것.)

$ git remote add origin [리파지토리 URL]
// 원격저장소 리파지토리와 연결.

$ git remote rm origin
// 연결된 원격저장소 연결 해제.

 

△ 1. git pull할 폴더를 엽니다.

 

 

△ 2. git remote 후 git pull 해줍니다.

 

 맨 처음 git remote 가 안된 이유는 초기화가 안됐기 때문입니다(.git 폴더 없음) git init을 해줍시다!

그 뒤 해당 리포지토리 URL로 remote하고 다음 명령어를 쳐주면

$ git pull origin master

 해당 리포지토리의 파일이 로컬저장소로 들어옴을 확인할 수 있습니다.

 

※ git clone 또한 나중에 로컬저장소 -> 원격저장소로 파일을 이동하기 위해서는 remote가 필요합니다.

 

 

Functions

 

 

▽ 7.1 함수 스타일에 대해서는 별도의 스타일 가이드를 제공하지 않는다.

// type 1
function foo() {
  // ...
}

// type 2
const foo = function() {
  // ...
};

// type 3
const foo = function bar() {
  // ...
};

: Naver에서는 함수 스타일에 대해 차별을 두지 않지만, Airbnb의 경우 type3의 명명된 함수식을 권장합니다. 

 

 

▽ 7.2 즉시 실행함수는 함수를 괄호로 감싼다.

// bad
!function()) {
  console.log("Welcome to the Internet. Please follow me.");
}();

// bad - Airbnb권장
(function() {
  console.log("Welcome to the Internet. Please follow me.");
}());

// good - Naver권장
(function() {
  console.log("Welcome to the Internet. Please follow me.");
})();

: 즉시 실행함수(IIFE, Immediately Involked Function Expression)은 단 한번 호출되며, 재호출이 불가한 함수입니다.

IIFE를 사용하는 이유'전역변수 사용을 억제하기 위해서'입니다.

IIFE를 (괄호)로 감싸는 이유함수 객체를 생성하기 위함인데, 구체적인 이유는 다음과 같습니다.

  1. 보통 IIFE는 익명함수를 쓰는 것이 일반적인데, JavaScript엔진이 함수이름을 생략할 수 없어 에러가 발생됩니다.
  2. 함수이름을 넣더라도 JavaScript엔진이 암묵적으로 세미콜론(;)을 자동 삽입해 함수선언문이 끝나는 위치에 세미콜론이 추가돼 에러가 발생됩니다.
  3. 세미콜론이 추가되더라도 세미콜론 다음의 괄호는 함수 호출 연산자가 아닌 그룹 연산자로 해석돼 에러가 발생됩니다.

해당 내용에 대해서는 추후 즉시 실행함수에 대해 따로 정리해보겠습니다.

 

 

▽ 7.3 함수 이외의 블록(if, while 등) 안에서 함수를 선언하지 않는다.

// bad
let i;
for (i = 10; i; i--) {
    (function() { 
      return i; 
    })();
}

// bad
while(i) {
    let a = function() {
      return i;
    };
    a();
}

// good
const a = function() {};
let i;
for (i = 10; i; i--) {
    a();
}

: browser마다 함수 외의 블록 내에 있는 함수를 모두 다르게 해석하기 때문입니다.

 

 

▽ 7.4 Airbnb와 다르게 block 내의 함수선언에 대해서는 별도로 가이드 하지 않는다.

이하 Airbnb 내용

// Naver가 아닌 Airbnb 내용입니다.

// bad
if (currentUser){
	function test(){
    	console.log('Nope');
    }
}

// good
let test;
if (currentUser){
	test = () => {
    	console.log('Yup');
    }
}

 

 

▽ 7.5 절대로 파라미터에 arguments를 지정하지 않는다. 이것은 함수 스코프에 전해지는 arguments 오브젝트의 참조를 덮어버린다.

// bad
function nope(name, options, arguments) {
  // ...stuff...
}

// good
function yup(name, options, args) {
  // ...stuff...
}

: JavaScript 함수에는 '인수객체(arguments)'라는 '내장객체'가 있습니다. 인수객체에는 함수가 호출될 때 사용된 인수 배열이 포함됩니다. 즉 이미 내장객체에 arguments가 있으니 파라미터로 쓸 수 없다는 뜻입니다.

 

 

▽ 7.6 절대 arguments를 이용하지 않는다. 대신에 rest 파라미터(...)를 이용한다.

// bad
function concatenateAll() {
  const args = Array.prototype.slice.call(arguments);
  return args.join("");
}

// good
function concatenateAll(...args) {
  return args.join("");
}

: rest 파라미터는 원하는 값에 대해 명확히 표현할 수 있습니다. 하지만 인수객체(arguments)를 쓴다면 오류 유발 가능성이 커집니다.

 

 

▽ 7.7 함수의 파라미터를 재정의하지 않는다. 대신 default 파라미터를 이용한다.

// really bad
function handleThings(opts) {
  opts = opts || {};
  // ...
}

// still bad
function handleThings(opts) {
  if (opts === void 0) {
    opts = {};
  }
  // ...
}

// good
function handleThings(opts = {}) {
  // ...
}

: default parameter(기본 매개변수)는 함수에 전달된 파라미터 값이 'undefined'거나 '값이 없을 때, 초기화 설정된 값'을 의미합니다.

 'void'은 관용적으로 사용하는 JavaScript 연산자입니다.

  • 'undefined' 원시값을 얻기 위해 void 0 또는 void(0)을 사용합니다.
  • void는 오버라이드 되지 않고 void 0은 항상 undefined를 리턴합니다.
  • undefined는 예약어가 아니라서 어떤 값이든 될 수 있습니다. (ex. var undefined = 0;    // 0)

 

 

▽ 7.8 side effect를 유발하는 default 파라미터의 이용을 피한다.

var b = 1;
// bad
function count(a = b++) {
  console.log(a);
}
count();  // 1
count();  // 2
count(3); // 3
count();  // 3

 

 

▽ 7.9 항상 default 파라미터는 뒤쪽에 둔다.

// bad
function handleThings(opts = {}, name) {
  // ...
}

// good
function handleThings(name, opts = {}) {
  // ...
}

 

 

▽ 7.10 절대 새 함수를 작성하기 위해 Function constructor를 이용하지 않는다.

// bad
var add = new Function("a", "b", "return a + b");

// still bad
var subtract = Function("a", "b", "return a - b");

: 이런 방식으로 함수를 만들면 취약성을 여는 eval()과 유사한 문자열처럼 처리됩니다. eval()에 관한 글 보기

 

 

▽ 7.11 익명함수는 function과 괄호 사이에 공백이 없다. 기명 함수(named function)는 함수 이름과 괄호 사이에 공백이 없다. async arrow function인 경우 async와 arrow function 사이에 공백이 있다.

// bad
const f = function () {};
const g = function a (){};
const h = async(v,i) => {};

// good
const x = function() {};
const y = function a() {};
const z = async (v,i) => {};

: 이는 코드를 일관성 있게 보이게 하며, 이름을 추가하거나 제거할 때 공백을 추가하거나 제거할 필요가 없어 관리가 편합니다.

 Naver에서는 async와 arrow function 사이에 공백도 추가했네요.

 

 

▽ 7.12 가급적 mutate parameter는 사용하지 않는다. 하지만, 필요에 의해서는 주의하여 사용한다.

// 권장하지 않음.
function f1(obj){
	obj.key = 1;
}

: 함수의 파라미터로 전달된 개체를 변형(mutate)하면, caller의 변수에 side effects가 발생할 수 있기 때문입니다.

 

 

▽ 7.13 파라미터를 재할당하지 않는다. 단, 파라미터의 속성에 대해서는 재할당이 가능하다.

// bad
function f1(a) {
  a = 1;
  // ...
}

// bad
function f2(a) {
  if (!a) { a = 1; }
  // ...
}


// good
function f3(a) {
  const b = a || 1;
  // ...
}

// good
function f4(a) {
  if (!a) { a.b = 1; }
  // ...
}

: Airbnb에서는 f4 함수에서 보이는 파라미터 속성값의 재할당 또한 금하고 있습니다.

 

 

▽ 7.14 가변함수를 호출할 때는 spread 연산자(...)를 사용한다.

// bad
const x = [1, 2, 3, 4, 5];
console.log.apply(console, x);

// good
const x = [1, 2, 3, 4, 5];
console.log(...x);

// bad
new (Function.prototype.bind.apply(Date, [null, 2016, 8, 5]));

// good
new Date(...[2016, 8, 5]);

: spread 연산자를 사용하면, 더 깔끔하고 문맥을 제공하지 않아도 됩니다.

 

 

▽ 7.15 함수의 정의가 멀티라인인 경우, 오브젝트와 같은 스타일 가이드를 따른다.

// bad
function foo(bar,
             baz,
             quux) {
  // ...
}

// good
function foo(
  bar,
  baz,
  quux,
) {
  // ...
}

// bad
console.log(foo,
  bar,
  baz);

// good
console.log(
  foo,
  bar,
  baz,
);

 

 

 예상하다시피 JavaScript Function에 대한 컨벤션은 길고, 사전지식이 많이 필요한 것 같습니다. 위 내용에서 궁금한 점도 많이 생겼으니 추후 자세하게 다뤄볼 주제들도 많네요. 다음 주제는 Arrow Function(화살표 함수)입니다.

 

 

naver github STYLE_GUIDE.md

 

 

사전지식

  • JavaScript에서 텍스트 데이터는 문자열(String)로 저장됩니다.
  • 문자열은 작은 따옴표(' '), 큰 따옴표(" "), 백틱(` `)으로 묶을 수 있습니다. - mac 에서 백틱은 [Opt + 원화] 입니다.
  • 특수문자를 사용할 때는 escape문자( \ )를 사용합니다.

Strings


 

 ▽ 6.1 따옴표는 쌍따옴표를 사용한다. 이스케이프한 경우는 예외로 홑따옴표를 사용할 수 있다.

// bad
var key = 'naver';
var obj = {
  'key': '1'
}

// good
var key = "naver";
var obj = {
  "key": "1"
}

 

 

 ▽ 6.2 문자열은 100자를 넘지 않는다. 100자가 넘는 긴 물자열인 경우 줄바꿈시 escape 문자()를 사용하지 않는다. escape문자 대신 +연산자를 이용한다. ES6의 template strings가 사용 가능한 환경에서는 6.3룰을 적용한다.

// bad
const errorMessage = 'This is a super long error that was thrown because \
of Batman. When you stop to think about how Batman had anything to do \
with this, you would get nowhere \
fast.';

// good
const errorMessage = "This is a super long error that was thrown because " +
  "of Batman. When you stop to think about how Batman had anything to do " +
  "with this, you would get nowhere fast.";

 

 

 ▽ 6.3 프로그램에서 문자열을 생성하는 경우는 문자열 연결이 아닌 template strings를 이용한다.

// bad
function sayHi(name) {
  return "How are you, " + name + "?";
}

// bad
function sayHi(name) {
  return ["How are you, ", name, "?"].join();
}

// good
function sayHi(name) {
  return `How are you, ${name}?`;
}

: ES6에서는 템플릿 리터럴이라는 새로운 문자열 표기법을 도입했습니다.

  • 따옴표와 다르게 백틱( ` )을 이용합니다. -> 연산자 없이 간단히 문자열을 삽입할 수 있습니다.
  • escape를 사용하지 않아도 됩니다. ex. \n
  • 문자열 내부에 포함식을 사용할 수 있습니다. 위 예제와 같이.
  • 멀티라인도 가능합니다.

 

 

 ▽ 6.4 절대로 eval()을 사용하지 않는다.

: eval()이라는 JavaScript의 내장함수는 사용을 절대 금하고 있습니다. 이유가 뭘까요?

  • eval()은 JS파일로부터 인자로 받은 코드 중 문자열이 있으면 이를 수치화 합니다.(문자열->숫자)
  • 이 때, 인자로 받은 코드를 caller의 권한으로 수치화합니다. 관리자 권한으로 실행과 같은 느낌이죠.
  • 위의 이유로 바이러스에 취약하고, 제 3자가 eval()이 호출된 위치의 스코프 추적이 가능합니다.
  • JS 파싱단계에서 JS파일의 문자열을 발견하면 수행합니다.
  • 위 단계에서 인터프리터를 사용하여 다른 대안보다 느리고 비효율적으로 동작합니다.

결국 eval()이 취약하다는 점에서 사용을 금하고 있는 것 같습니다. (아마도!)

 

 

 ▽ 6.5 문자열에 불필요한 escape 문자를 사용하지 않는다.

// bad
const foo = "\'this\' \i\s \'quoted\'";

// good
const foo = "\"this\" is 'quoted'";
const foo = `my name is '${name}'`;

 

 문자열 또한 그렇게 많이 언급할 부분은 없는 것 같습니다. 그래도 eval()을 사용하지 않아야겠다! 정도 얻은 것 같습니다.

추후 escape나 백틱, string 내장함수들에 대해서도 정리하는 시간을 가져야겠습니다.

 

 

naver github STYLE_GUIDE.md

 

 

Destructuring


 

 네이버 컨벤션은 Destructuring에 대해 Airbnb와 다르게 별도의 가이드를 제공하지 않습니다. 하지만 Airbnb의 Destructuring conventions에도 좋은 점이 많이 보여 정리하였습니다.

 JavaScript의 Destructuring 개념에 대해 알고싶으시다면 이전 글을 참고해주시기 바랍니다.

 

Airbnb Conventions

 

▽ 5.1 object의 여러 프로퍼티에 접근하거나 사용하기 위해 destructuring을 사용합니다.

// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;

  return `${firstName} ${lastName}`;
}

: Destructuring을 진행하지 않고 각각의 변수를 선언합니다.

// good
function getFullName(user) {
  const { firstName, lastName } = user;
  return `${firstName} ${lastName}`;
}

// best
function getFullName({ firstName, lastName }) {
  return `${firstName} ${lastName}`;
}

: Destructuring의 다음과 같은 장점을 사용하기 위해서입니다.

  • 해당 프로퍼티에 대한 임시 참조를 생성합니다 : 해당 프로퍼티 사용 시, 블록 전체를 읽어낼 필요가 없어 속도가 향상됩니다.
  • 개체에 대한 반복적인 접근(Access)를 방지합니다 : 반복적인 엑세스는 더 많은 반복적인 코드를 생성해 실수를 유발합니다.

 

 ▽ 5.2 배열 Destructuring을 사용합니다.

const arr = [1, 2, 3, 4];

// bad
const first = arr[0];
const second = arr[1];

// good
const [first, second] = arr;

 

▽ 5.3 반환 값이 여러개라면, Array Destructuring보다 Object Destructuring이 권장됩니다.

// bad
function processInput(input) {
  // then a miracle occurs
  return [left, right, top, bottom];
}

// 이 경우 반환 데이터의 순서를 고려해야됩니다.
const [left, __, top] = processInput(input);
// good
function processInput(input) {
  // then a miracle occurs
  return { left, right, top, bottom };
}

// 원하는 데이터만 가져올 수 있습니다.
const { left, top } = processInput(input);

 

naver github STYLE_GUIDE.md

+ Recent posts