자바스크립트 완벽가이드 5장 (문장)

문장(statement), 즉 ‘문’은 자바스크립트 문장, 다시 말해 명령이다. 자바스크립트 문장은 세미콜론(;)으로 끝난다. 표현식은 어떤 값을 생성하기 위해 평가되지만, 구문은 어떤 일을 하기위해 실행되는 것이다.

5.2 복합문과 빈 문장

문장 블록은 여러 문장을 하나의 복합문으로 묶는다. 자바스크립트에는 블록 단위의 유효범위(scope)가 존재하지 않기 때문에, 구문 블록 안에 선언된 변수는 블록뿐 아니라 블록 밖에서도 접근할 수 있다.

자바스크립트 문법은 대체로 하나의 하위문을 허용한다. 예를 들어, while 루프 문법은 루프 몸체로 하나의 문장을 허용한다. 문장 블록을 사용하면 문법이 허용하는 하나의 하위문 자리에 얼마든지 많은 문장을 넣을 수 있다.

결과적으로 복합문은 자바스크립트 문법에서 하나의 문장이 있어야 할 곳에 여러 문장을 사용할 수 있게 한다. 빈문장은 정 반대다. 하나의 문장이 있어야 할 곳에 아무런 문장도 두지 않을 수 있도록 한다. 빈 문장은 ;을 사용하여 표현한다. 임의로 빈 문장을 사용할 경우에는, 코드에 고의로 사용했다는 설명을 주석으로 표시하는 것이 좋다.

5.3 선언문

5.3.1 var

var문은 하나 또는 그 이상의 변수를 선언한다. var문에서 변수에 초기 값을 지정하지 않으면 변수의 초기 값은 undefined가 된다. 스크립트나 함수 안에서 선언된 변수는 해당 스크립트나 함수 전체에 걸쳐 유효하다. 하지만 초기화된 var문이 선언된 시점에서 발생하고, 그 전까지는 변수 값은 undefined가 된다.

5.3.2 function

함수 선언문은 자바스크립트 최상위 단계 코드에서 나타날 수도 있고, 다른 함수 내에 중첩될 수도 있다. 하지만 함수가 다른 함수 속에 중첩될 때는, 중첩된 함수 내에서 최상위 단계에 위치해야 한다. 즉, 함수 선언은 if문이나 while문 등의 다른 문장 안에 있을 수 없다.

**함수 선언문**은 함수 이름을 포함한다는 점에서 **함수 정의표현식**과는 차이가 있다. 둘 다 새 함수 객체를 만들지만, 함수 선언문은 함수 이름을 변수로 선언한 후 이 변수에 함수 객체를 할당한다는 차이가 있다. var로 선언한 변수와 같이, 함수 선언문으로 정의된 함수는 스크립트나 함수 유효범위 최상단에 위치하게 되어(hoisted) 해당 유효범위 내에서 사용할 수 있다. var 문을 이용하면 변수 선언만 유효범위 최상단으로 끌어올려지지만(변수 초기화 코드는 원래 위치에 그대로 유지), 함수 선언문을 이용하면 함수의 이름과 본문 모두 유효범위 최상단으로 끌어올려진다. 이때 스크립트 내의 모든 함수 또는 함수의 중첩 함수는 다른 코드가 실행되기 전에 선언된다. 이는 자바스크립트 함수를 호출하는 코드가 선언문이 나오기 전에도 올 수 있다는 뜻이다.

5.4 조건문

5.4.1 if

대다수의 프로그래밍 언어와 마찬가지로 자바스크립트 규칙에 의하면 else 절은 기본적으로 가장 가까운 if문에 속한다. 모하함을 없애고 읽기 쉽고 이해하기 쉬운 동시에 유지보수와 디버깅을 쉽게 하려면 반드시 중괄호를 사용해야 한다.

5.4.3 switch

switch문은 if문에서처럼 동일한 표현식이 여러 번 반복되는 문제점을 확실히 해결한다. 다음은 실용적인 switch 문의 예제이다. 이 예제에서는 어떤 값을 문자열로 바꾸는데, 그 값의 타입에 따라 각기 다른 방법을 적용해 문자열로 변환한다.

1
2
3
4
5
6
7
8
9
10
function convert(x) {
switch(typeof x) {
case 'number': // 주어진 숫자를 16진수 정수로 변경한다.
return x.toString(16);
case 'string': // 문자열을 큰따옴표로 묶어서 반환한다.
return '"' + x + '"';
default: // 이 외의 타입은 문자열로 변환한다.
return String(x);
}
}

switch문이 실행될 때마다 모든 case 표현식이 매번 평가되지는 않기 때문에, case 표현식에 함수 호출이나 값 할당과 같이 부수 효과를 일으킬 수 있는 표현식을 사용해서는 안된다. 가장 안전한 방법은 case 표현식을 상수 표현식만으로 제한하는 것이다. case를 판별할 때는 동치 연산자 ==가 아닌 **일치 연산자 ===**가 사용된다.

5.5 루프

자바스크립트에는 네 개의 루프문이 있다.

  1. while
  2. do/while
  3. for
  4. for/in

5.5.4 for/in

for/in문은 for 키워드를 사용하지만, 일반적인 for 루프와는 전혀 다른 종류다.

1
2
for (변수 in 객체)
문장

‘변수’는 보통 변수 이름이지만 좌변 값으로 평가되는 표현식이거나, 단일 변수를 선언하는 var문일 수도 있다. ‘객체’는 객체로 평가되는 표현식이어야 한다. ‘문장’은 루프 몸체를 구성하는 문장 또는 문장 블록이다.
일반적인 for 루프를 사용하면 다음과 같이 배열의 원소를 쉽게 순회할 수 있다.

1
2
for(var i = 0; i < a.length; i++)
console.log(a[i]);

이와 비슷하게 for/in 루프를 사용하면 객체가 가진 프로퍼티들을 쉽게 순회할 수 있다.

1
2
3
for(var p in o) {       // 변수 p에 객체 o가 가진 프로퍼티 이름을 할당한다.
console.log(o[p]);
}

for/in문을 실행하기 위해서 자바스크립트 인터프리터는 먼저 객체 표현식을 평가한다. 이때 표현식이 null이나 undefined로 평가되면 인터프리터는 해당 루프를 중단하고 다음 문장을 실행한다. 만약 표현식이 원시 값으로 평가되면 해당 값은, 값과 상응하는 Wrapper 객체로 바뀐다. 이 외에 표현식은 객체로 평가된다.

for/in 루프에서 사용하는 ‘변수’로는 할당 표현식의 좌변에 적합한 무언가로 평가되는 임의의 표현식을 사용할 수 있다. 이 표현식은 루프가 돌 때마다 평가되는데, 이때 매번 다르게 평가될 수 있다. 다음과 같은 코드를 사용하면 주어진 객체의 모든 프로퍼티 이름을 배열에 복사할 수 있다.

1
2
3
var o = {x:1, y:2, z:3};
var a = [?], i = 0;
for(a[i++] in o) /* 비어 있음 */;

자바스크립트 배열은 단순히 특별한 종류의 객체에 지나지 않는다. 따라서 for/in 루프는 객체의 프로퍼티와 마찬가지로 배열 인덱스 또한 하나씩 열거할 수 있다.

for/in 루프는 실제로 객체가 가진 모든 프로퍼티를 열거하지 않고 오직 ‘열거 할 수 있는 프로퍼티’만 열거한다. 자바스크립트 코어에 정의된 다양한 내장 메서드들은 일반적으로 열거할 수 없다. (예를 들면 toString() 메서드)

5.6 점프문

5.6.4 return

함수를 호출하는 것 역시 표현식이고, 모든 표현식에는 값이 있다. return문은 함수 호출 표현식의 값, 즉 함수에서 반환하는 값을 지정하는 데 쓰인다. return문은 오직 함수 몸체 내부에서만 나타날 수 있다. 다른 곳에서 사용하면 문법 에러가 발생한다. return문이 실행되면 ‘표현식’이 평가되어 그 결과가 함수의 값으로 반환된다. 함수 내에 return문이 없다면 함수 호출은 단지 함수 몸체의 끝에 도달할 때까지 모든 구문을 차례로 실행하고, 호출한 지점으로 돌아간다. 이 경우에 해당 함수 호출 표현식의 값은 undefined가 된다. return문은 주로 함수의 마지막에 위치하지만 반드시 마지막에 있어야 하는것은 아니며, 함수 몸체 내에서 return문이 실행되면 아직 남은 문장들이 있어도 함수를 호출한 지점으로 돌아간다.

5.6.5 throw

자바스크립트에서는 런타임 에러가 일어날 때마다 예외를 발생시킨다. Error 객체는 에러의 종류를 담고 있는 name 프로퍼티와 Error 클래스 생성자 함수에 넘기는 문자열 값을 담고 있는 message 프로퍼티를 갖고 있다.

예외가 발생하면 자바스크립트 인터프리터는 정상적인 프로그램 실행을 즉시 중단하고 가장 가까운 예외 처리기로 넘어간다. 예외를 발생시킨 코드 블록이 catch절과 연결되어 있지 않으면, 인터프리터는 바로 상위 단계를 감싸고 있는 코드 블록에 연결된 예외 처리기가 있는지 확인한다. 이 과정은 처리기를 찾을 때까지 계속된다. 이같은 방법으로 자바스크립트의 언어적인 구조를 따라서, 즉 호출 스택을 따라서 예외가 전파되어 올라간다. 예외 처리기를 찾을 수 없는 경우 해당 예외는 에러로 취급되고 사용자에게 보고된다.

5.6.5 try/catch/finally

  • try : 단순히 예외가 발생할지도 모르는 코드 블록을 정의하는 역할
  • catch : try 블록 내부에서 예외가 발생할 경우 호출되는 문장 블록
  • finally : try 블록에서 일어난 일에 관계없이 항상 실행이 보장되어야 할 뒷정리용 코드가 포함

정상적인 경우에, 자바스크립트 인터프리터는 try 블록의 끝까지 도달하고 난 후, finally 블록으로 이동해 무언가 필요한 뒷정리를 수행한다. 만일 인터프리터가 return, continue, break 문 등을 만나 try 블록의 제어를 벗어날 경우, 새 지점으로 이동하기 전에 finally 블록이 실행된다.

만일 예외를 처리할 catch 블록이 없다면 인터프리터는 일단 finally 블록을 실행한 후 상위 블록으로 예외를 전파하여, 해당 예외를 처리할 수 있는 가장 가까운 catch 절로 이동한다.

5.7 기타

5.7.1 with

with문은 유효범위 체인의 첫 번째에 ‘객체’를 추가한다. 그 후에 ‘문장’을 실행한 다음, 유효범위 체인을 ‘객체’를 추가하기 전 상태로 되돌려 놓는다. with문을 사용하는 자바스크립트 코드는 최적화하기 힘들고 with문을 사용하지 않는 코드에 비해 느리기 때문에 사용하지 않는것이 좋다.

5.7.2 debugger

debugger문은 평소에는 아무것도 하지 않지만 디버거 프로그램을 사용할 수 있고 디버거가 실행 중일 때, 자바스크립트 구현체는 해당 위치에서 정의된 코드 디버깅을 수행한다. debugger문은 코드의 중단점(breakpoint)와 같이 동작한다. 자바스크립트 코드의 실행을 잠시 멈추고 디버거 프로그램을 사용해 변수의 값을 출력할 수 있고, 호출 스택등을 살펴볼 수 있다.

5.7.3 “use strict”

use strict'는 ECMAScript 5에서 처음 소개된 지시어다. ‘use strict’ 지시어를 사용하는 목적은 지시어 다음에 오는 (스크립트나 함수의) 코드들이 엄격 모드를 따르게 하기 위해서다. 스크립트의 최상단에 ‘use strict’ 지시어가 있으면 최상단(함수가 아닌) 코드는 엄격한 코드(엄격 모드를 따르는 코드)다.

엄격한 코드는 엄격 모드에서 실행된다. ECMAScript 5의 엄격 모드는 언어의 일부 기능이 제한된 부분 집합으로, 몇 가지 주용한 언어적 문제점을 수정하고 강력한 에러 검사와 향상된 보안 기능을 제공한다. 다음과 같은 부분이 일반 모드와 다르다.

  • with문은 엄격 모드에서 사용 불가능 하다.
  • 엄격 모드에서 모든 변수는 반드시 선언되어야 한다. 선언되지 않은 변수나 함수, 함수 인자, catch 절 인자, 전역 객체 프로퍼티에 값을 할당하는 경우 ReferenceError 예외가 발생한다.
  • 엄격 모드에서 함수는 메서드로 호출된 것이 아닌, 함수로 호출된 함수의 this 값은 undefined다. (표준 모드에서는 함수가 함수로 호출될 때 항상 전역 객체를 this의 값으로 넘겨주게 된다.) 또한 엄격 모드에서는 함수를 **call()**이나 **apply()**로 호출하면, this의 값은 정확히 call()이나 apply() 함수의 첫 번째 인자 값으로 설정된다. (표준 모드에서는 null과 undefined 값은 전역 객체로 대체되고, 객체가 아닌 값들은 객체로 바뀌게 된다.)
  • 엄격 모드에서 함수의 arguments 객체는 함수에 전달된 값의 정적 사본을 갖고 있지만 표준 모드에서 arguments 배열의 원소와 함수의 전달인자는 동일한 값을 참조한다.

출처 : “JavaScript: The Definitive Guide, by David Flanagan (O’Reilly). Copyright 2011 David Flanagan, 978-0-596-80552-4”

자바스크립트 완벽가이드 3장 (타입, 값, 변수)

자바스크립트의 타입은 크게 원시 타입(promitive type)객체 타입(object type)으로 나뉜다. 원시타입에는 숫자, 텍스트의 나열, 불리언 진리 값이 있다.
자바스크립트에서 null과 undefined는 원시값이긴 하지만, 숫자도 아니고, 문자열이나 불리언도 아니다. null과 undefined는 자기 자신만을 값으로 갖는 독립적인 타입이다. 숫자와 문자열, 불리언, null, undefined 외의 값은 객체다. 객체는 이름과 값을 갖는 프로퍼티의 집합이다.

자바스크립트에서는 함수도 특별한 객체이다. 함수는 값이고, 자바스크립트 프로그램은 함수를 보통 객체처럼 다룰 수 있다.

클래스는 객체 타입의 하위 타입으로 생각할 수 있다. 코어 자바스크립트에서는 Array와 Function 클래스 뿐만 아니라 세 개의 다른 유용한 클래스들을 정의하고 있다.

  • Date : 날짜를 표현하는 객체를 정의
  • RegExp : 정규 표현식을 표현하는 객체를 정의
  • Error : 자바스크립트 프로그램에서 발생할 수 있는 문법과 런타임 에러를 표현하는 객체를 정의

자바스크립트 인터프리터는 메모리 관리를 위해 자동으로 **가비지 컬렉션**을 수행한다. 프로그램이 필요할 때 객체를 생성할 수 있고, 프로그래머는 이 객체를 어떻게 해제할지 걱정할 필요가 없다. 객체에 더 이상 접근할 수 없을 때(프로그램이 더 이상 객체를 참조하지 않을 때) 인터프리터는 그 객체를 자동으로 메모리에서 해제한다.

자바스크립트는 객체 지향 언어다. 다양한 타입의 값을 다루는 전역 함수를 정의해두기보다, 어떠한 값과 작동하는 메서드를 그 값의 타입에 정의해둔다는 말이다. 예를 들면, 배열의 원소들을 정렬할 때는 배열 a를 sort() 함수에 인자로 전달하는 것이 아니라 a의 sort() 메서드를 호출하여 정렬하는 것이다. null과 undefined를 제외하고는 모두 메서드를 가질 수 있다.

3.1 숫자

다른 프로그래밍 언어들과는 다르게 자바스크립트는 정수 값과 실수 값을 구분하지 않는다. 자바스크립트에서는 모든 숫자를 실수로 표현한다.

3.1.3 산술 연산

자바스크립트의 산술 연산은 오버플로와 언더플로, 0으로 나누는 에러를 발생시키지 않는다. 산술 연산의 결과가 표현할 수 있는 가장 큰 수보다 더 크다면(오버플로) Infinity라고 표현하는 무한대의 값을 출력한다. 음의 무한대가 되면 이 값을 -Infinity로 출력한다. 언더플로는 산술 연산의 결과가 표현할 수 있는 가장 작은 값보다 더 0에 가까울 때 발생한다. 이런 경우 자바스크립트는 0을 돌려준다.

자바스크립트에서 0으로 나누는 연산은 에러가 아니다. 이런 경우 무한대 또는 음의 무한대가 반환된다. 그러나 0을 0으로 나누는 것은 정의되지 않은 값을 갖고, 그 결과로 숫자가 아닌 특수한 값을 가진다. 자바스크립트에서는 이러한 값을 NaN으로 출력한다. (ECMAScript 5에서는 Infinity와 NaN을 읽기 전용 값으로 정의한다.) Number객체에는 Inifiny와 NaN이 따로 상수로 정의되어 있다.

자바스크립트에서 NaN은 그 자신뿐만 아니라 다른 값과 같은지 비교 할 수 없다. 변수 x가 NaN인지 판단하기 위해 x === NaN 문을 작성할 수 없고, 대신 x != x 라고 작성해야 한다. isNaN() 함수가 이러한 경우에 유용하게 사용할 수 있다. 이 함수는 인자가 NaN이거나, 문자열이나 객체처럼 숫자가 아니라면 참을 반환한다.

3.1.4 이진 부동소수점과 반올림 오류

무한히 많은 실수가 있지만 자바스크립트에서는 한정된 숫자만 부동소수점 형태로 표현할 수 있다. 자바스크립트에서 사용하는 IEEE-754 부동소수점 표현 방식은 1/2, 1/8, 1/1024 같은 분수를 정확하게 표현 할 수 있는 이진 표현법이다. 하지만 가장 많이 사용하는 분수는 10진수 분수인데, 이진 표현법으로는 0.1과 같은 간단한 값도 정확하게 표현 할 수 없다.
따라서 다음과 같은 상황이 발생한다.

1
2
3
4
5
var x = .3 - .2;        // 0.3 - 0.2
var y = .2 - .1; // 0.2 - 0.1
x == y // => false: 두 값은 같지 않다.
x == .1 // => false: 0.3 - 0.2는 0.1이 아니다.
y == .1 // => true: 0.2 - 0.1은 0.1과 같다.

이진 부동소수점 숫자를 사용하기 때문에 발생하는 현상이다. 계산된 값은 대부분 적절하지만, 값들을 동등 비교할 경우에 문제가 발생한다.

3.1.5 날짜와 시간

날짜와 시간을 표현하는 Date 객체를 사용한다. Date 객체는 숫자 같은 원시 타입이 아니다.

3.2 텍스트

문자열(string)은 16비트 값들이 연속적으로 나열된 변경이 불가능한 값으로, 각 문자는 유니코드 문자로 표현된다. 문자열의 길이 값은 문자열에 들어 있는 16비트 값의 개수다.

자바스크립트는 유니코드 문자열 집합으로 UTF-16을 사용한다. 유니코드 문자는 16비트에 적합한 코드 포인트를 갖고 있고, 문자열의 한 문자로 표현할 수 있다. 16비트로 표현할 수 없는 유니코드는 UTF-16 규칙에 따라 두 개의 16비트 값으로 인코딩한다. 따라서, 자바스크립트에서는 길이가 2인 문자열이 하나의 유니코드 문자를 표현하는 경우도 있다.
문자열을 다루는 다양한 메서드는 문자를 다루는게 아니라 문자의 16비트 값을 다룬다.

3.2.3 문자열 다루기

자바스크립트에서 문자열은 변경되지 않는다. replace()와 toUpperCase() 같은 메서드는 기존 문자열을 변경하지 않고 새문자열을 반환한다. 즉, 문자열 관련 메서드는 호출 시에 기존 문자열을 수정하지 않는다. ECMAScript5에서 문자열은 읽기 전용 배열처럼 취급될 수 있고, 대괄호 대신 charAt() 메서드를 사용해도 문자열의 개별 문자(16비트 값)에 접근할 수 있다.

3.2.4 패턴 매칭

자바스크립트는 문자 패턴을 나타내는 객체를 생성하기 위해 RegExp() 생성자를 정의한다. 이 패턴은 정규 표현식이라 부르며, 자바스크립트는 정규 표현식을 위해 펄(Perl)의 구문을 따른다. 문자열과 RegExp 객체는 모두 패턴 매칭과 ‘검색 후 바꾸기’기능을 수행하는 메서드를 갖고 있다. RegExp는 자바스크립트의 원시 타입이 아니다. Date 객체처럼 RegExp는 유용한 API를 갖고 있는 특별한 종류의 객체다.
한 쌍의 슬래시 사이에 있는 문자열은 정규 표현식 리터럴을 구성하고, 한 쌍의 슬래시 중 두 번째 슬래시 뒤에는 하나 혹은 그 이상의 문자가 뒤따라 올 수 있는데, 이것은 패턴의 의미를 수정할 수 있다.

RegExp 객체에는 유용한 메서드들이 정의되어 있다. 또한 문자열은 RegExp 객체를 인자로 갖는 메서드들을 갖고 있다.

1
2
3
4
5
6
7
var text = "testing: 1, 2, 3";      // 간단한 문자열
var pattern = /\b+/g // 하나 이상의 모든 숫자와 일치
pattern.test(text); // => true: 일치하는 문자열이 존재
text.search(pattern); // => 9: 첫 번째로 매치하는 문자열의 위치
text.match(pattern); // => ["1", "2", "3"]: 일치된 항목의 배열
text.replace(pattern, "#"); // => "testing: #, #, #"
text.split(/\D+/); // => ["", "1", "2", "3"]: 숫자가 아닌 문자(열)를 기준으로 분할

3.3 불리언 값

자바스크립트의 어떤 값이든 불리언 값으로 변환될 수 있다. 다음은 모두 불리언 false 값으로 변한다.

  • undefined
  • null
  • 0
  • -0
  • NAN
  • “” // 빈 문자열

불리언 값은 문자열 “true” 혹은 “false”로 변환할 수 있는 toString() 메서드를 갖고 있지만 그 밖의 메서드는 갖고있지 않다.

3.4 null과 undefined

null은 보통 아무 값도 갖지 않음을 가리킬 때 사용한다. typeof 연산자를 null에 사용하면 문자열 “object”를 반환한다. 그 결과로 볼 때, null은 ‘객체가 없음’을 뜻하는 특수한 객체 값으로 생각할 수 있다. 하지만 실무에서 null은 값이 null 하나뿐인 어떤 고유한 자료형에 속한 것으로 간주하여, 객체뿐 아니라 수나 문자열 “값이 없음”을 나타내는 데도 쓰인다.

자바스크립트에는 값이 없음을 나타내는 또 다른 값, undefined가 있다. undefined는 null보다 심한 부재 상태를 나타낸다. undefined는 초기화되어 있지 않는 변수나, 존재하지 않는 객체 프로퍼티나 배열의 원소 값에 접근하려고 할 때 얻는 값이다. 또한 undefined는 반환값이 없는 함수의 반환값이고, 실 인자가 전달되지 않은 형식인자의 값이다. ECMAScript 5에서 undefined는 읽기 전용이며, typeof 연산자의 결과로 “undefined”가 반환된다. 이는 undefined가 특별한 고유의 값임을 말한다.

이러한 차이에도 불구하고 nullundefined는 둘다 값이 없음을 가리키고, 사용할 때 서로 바꿔 사용할 수도 있다. 동치 연산자 ==를 null과 undefined에 사용하면 두 값이 같다고 간주하며 엄격한 동치 연산자 ===는 다르다고 판단한다.

시스템 수준에서 예기치 않은 상황에 발생한, 오류성 값 부재를 표현할 때는 주로 undefined를 사용하고, 일반적인 프로그램 수준에서 일반적으로, 또는 예상 가능한 값 부재 상황을 표현하고 싶을 때는 null을 사용한다. 만약 이들 값 중 하나를 변수나 프로퍼티에 할당할 필요가 있거나 함수에 인자로 전달할 필요가 있다면, undefined보다는 null을 사용하는게 적절하다.

3.6 래퍼(wrapper) 객체

자바스크립트 객체는 복합적인 값이다. 객체는 프로퍼티 또는 이름 있는 값들의 집합이다. 프로퍼티의 값이 함수일 때, 그 함수를 메서드라 부른다.

문자열의 프로퍼티를 참조하려 할 때, 자바스크립트는 new String()를 호출한 것처럼 문자열 값을 객체로 변환한다. 이 객체는 문자열 메서드를 상속하며, 프로퍼티 참조를 살펴보는 데 사용한다. 일단 프로퍼티 참조가 해제되면 새로 생성된 임시 객체는 메모리에서 회수된다.

숫자와 불리언은 문자열과 같은 이유로 메서드를 갖고 있다. 임시 객체는 Number() 혹은 Boolean() 생성자를 통해 만들어지고, 메서드는 임시 객체를 통해 호출된다.

1
2
3
var s = "test";
s.len = 4;
var t = s.len;

위의 코드를 실행시 t의 값은 undefined이다. 2행은 생성된 임시 String 객체의 len 프로퍼티에 4를 할당한다. 그리고 임시 객체는 바로 삭제된다. 3행은 기존 문자열 값과 같은 값을 가진 새로운 String 객체를 생성하고 len 프로퍼티를 읽으려고 하지만 존재하지 않아 undefined를 출력한다. 값을 할당하는 것은 임시 객체에서 수행되며, 지속되지 않는다.

문자열, 숫자, 불리언의 프로퍼티에 접근하려고 할 때 생성되는 임시 객체래퍼(wrapper) 객체로 알려져 있다. 문자열과 숫자, 불리언 값의 프로퍼티는 읽기 전용이고, 이 값들에 새로운 프로퍼티를 정의할 수 없다는 점에서 이 값들이 객체와 다르다는 사실을 알아야 한다.

String()과 Number(), Boolean() 생성자를 사용해 명시적으로 래퍼 객체를 생성할 수도 있다. 자바스크립트는 래퍼 객체를 필요에 따라 기본 타입으로 변환한다. == 동치 연산자는 값과 그 값의 래퍼 객체를 동등하게 다루지만 === 엄격한 동치 연산자로 이를 구별할 수 있다. (typeof 연산자는 기본 타입과 래퍼 객체의 차이점을 보여줄 수 있다.)

#3.7 변경 불가능한 원시 타입 값과 변경 가능 객체 참조
자바스크립트에서 원시 타입(undefined, null, 불리언, 숫자, 문자열) 값객체(배열과 함수를 포함한) 사이에는 근본적인 차이점이 있다. 원시 타입의 값은 수정할 수 없다는것이다. 문자열 같은 경우 문자열을 수정하는 모든 문자열 메서드는 새로운 문자열을 반환한다. 원시 타입은 값으로 비교된다. 두 값은 같은 값이어야만 같다. 문자열 같은 경우 서로 다른 문자열 값을 비교할 때, 자바스크립트는 두 문자열의 길이가 같고 각 인덱스에 있는 문자들이 같다면 두 문자열을 같다고 판단한다.

객체는 원시 타입과는 다르다. 객체는 자신의 값을 변경할 수 있다. 객체는 값으로 비교되지 않는다. 두 객체가 같은 프로퍼티와 값을 가지고 있어도 두 객체는 같지 않다. 그리고 두 배열은 같은 순서로 같은 원소를 갖고 있어도 같지 않다.

객체는 참조 타입(reference type)으로 불리는데, 이는 자바스크립트의 원시 타입과 구별하기 위해서다. 객체의 값은 참조다. 객체는 참조로 비교될 수 있다. 두 객체 값은 그들이 같은 객체를 참조하면 같다. 객체는 새로운 복사본을 생성하지 않기 때문에 객체 혹은 배열의 새로운 복사본을 만들고 싶다면 명시적으로 객체의 프로퍼티 또는 배열의 원소를 복사해야 한다.

1
2
3
4
5
var a = ['a', 'b', 'c'];                  // 복사하고자 하는 배열
var b = []; // 복사하고자 하는 배열
for(var i = 0; i < a.length; i++) { // 배열 a의 각 인덱스
b[i] = a[i]; // a의 원소를 b로 복사한다.
}

두 다른 객체 또는 배열을 서로 비교하고 싶다면 그들의 프로퍼티 또는 원소를 비교해야 한다.

3.8 타입 변환

자바스크립트는 타입에 매우 유연하다. 자바스크립트가 문자열을 원한다면, 문자열이 올 자리에 어떤 값을 전달하더라도 문자열로 변환될 것이고, 숫자를 원한다면 숫자가 올 자리에 다른 어떤 값이 오더라도 숫자로 변환될 것이다.(또는 의미 있는 변환을 할 수 없다면 NaN으로 변환된다.)

3.8.1 변환과 동치

자바스크립트는 값의 타입을 유연하게 변환시킬 수 있다. 따라서, 동치 연산자 ==도 유연하게 동작한다. 다음은 모두 true를 반환한다.

1
2
3
4
null == undefined     // 이 두 값은 같다고 판단된다.
"0" == 0 // 비교하기 전에 숫자로 변환된다.
0 == false // 불리언은 비교하기 전에 숫자로 변환한다.
"0" == false // 두 피연선자는 비교하기 전에 숫자로 변환된다.

서로 변환 가능한 값이라고 해서 동치는 아니다. undefined가 불리언 값이 올 자리에 사용되면 false로 변환된다. 하지만 이것이 undefined == false 임을 의미하지는 않는다. if문은 undefined를 false로 변환하지만, == 연산자는 undefined를 불리언으로 변환하지 않는다.

3.8.2 명시적 변환

자바스크립트는 많은 형 변환을 자동으로 수행하지만, 명시적 변환이 필요할 때가 있다. 명시적으로 타입변환을 수행하는 가장 간단한 방법은 Boolean(), Number(), String(), Object() 함수를 사용하는 것이다. new 연산자 없이 호출되면, 이 함수들은 변환 함수로 작동한다.

3.8.3 객체에서 원시 타입으로 변환

모든 객체는 두 개의 타입 변환 메서드를 상속한다.

  • toString() : 객체를 문자열로 표현하여 반환한다.
  • valueOf() : 기본적으로 원시 타입을 반환하지 않고 단순히 객체 그 자신을 반환한다.

자바스크립트는 toString(), valueOf() 순으로 메서드를 호출하여 문자열로 변환하여 반환한다. 만약 toString() 또는 valueOf() 로부터 원시타입 값을 얻을 수 없다면 TypeError를 발생시킨다. 객체를 숫자로 전환할 때는 문자열과 같은 방식으로 전환하지만, valueOf() 메서드를 먼저 호출한다.

3.9 변수 선언

자바스크립트에서는 변수를 사용하기 전에 변수 선언을 해야 한다. var 문을 통해서 변수를 선언하는데, var 문에서 변수에 초기 값을 지정하지 않는다면, 변수는 값이 설정될 때까지 undefined 값을 갖게 된다. 자바스크립트 변수 선언에는 타입을 명시하지 않는다.

3.10 변수의 유효범위

변수의 유효범위란 프로그램에서 어떤 변수가 정의되어 있는 영역을 말한다.

3.10.1 함수 유효범위와 끌어올림(hoisting)

C 같은 프로그래밍 언어에서 블록 안에 있는 코드는 자신만의 유효범위를 가지며, 변수는 해당 변수가 선언되지 않은 블록 밖에서는 보이지 않는다. 이를 블록 유효범위라고 부른다. 자바스크립트에서는 블록 유효범위의 개념이 없고 함수 유효범위를 사용한다. 변수는 해당 변수가 정의된 함수 안에서 보일 뿐 아니라, 그 함수 안에 중첩된 함수 안에서도 보인다. 이런 자바스크립트의 특징을 비공식적으로 **끌어올림(hoisting)**이라고 한다. 자바스크립트의 코드는 함수 안에 있는 모든 변수를 함수 맨 위로 ‘끌어올린’ 것처럼 동작한다.

1
2
3
4
5
6
var scope = "global";
function f() {
console.log(scope); // "global"이 아니라 "undefined"를 출력한다.
var scope = "local"; // 여기서 초기호하지만, 정의는 다른 곳에서 이루어진다.
console.log(scope); // "local"을 출력한다.
}

위의 함수는 실제로 다음 코드와 같다.

1
2
3
4
5
6
function f() {
var scope; // 지역 변수는 함수 맨 꼭대기에서 선언한다.
console.log(scope); // scope 변수는 존재하지만 아직 "undefined" 값이다.
scope = "local"; // 이제 scope 변수가 초기화되고 제대로 된 값이 있다.
console.log(scope); // 여기서는 기대한 값이 들어있다.
}

함수의 유효범위 규칙 때문에 지역 변수는 함수 전체에 걸쳐 정의된다. 지역 변수가 함수 전체에 걸쳐 정의되었더라도 var 문이 실행되고 나서야 실제로 초기화 된다. 따라서 변수 선언은 함수 맨 위로 **’끌어올려(hoisting)’**지고 초기화는 나중에 이루어지게 된다.

블록 유효범위를 가진 프로그래밍 언어에서 일반적으로 변수를 선언하는 좋은 프로그래밍 방법은, 가능한 한 그 변수가 사용되는 가장 가까운 곳에서 선언하는 것이다. 하지만 자바스크립트는 블록 유효범위를 가지고 있지 않기 때문에 함수의 맨 위에 선언해야할지도 모른다.

3.10.3 유효범위 체인

자바스크립트는 언어적으로 유효범위를 갖고 있는 언어다. 변수의 유효범위란 정의된 변수를 사용 가능한 소스코드의 집합으로 생각할 수 있다.

지역 변수를 객체의 프로퍼티로 생각한다면, 변수 유효범위를 다른 관점으로 볼 수도 있다. 자바스크립트의 모든 코드 무더기는 그것과 연관된 유효범위 체인을 갖고 있다. 이 유효범위 체인은 해당 코드 무더기의 ‘범위 안’에 있는 변수를 정의하는 객체의 체인, 리스트다.

최상위 자바스크립트 코드의 경우, 유효범위 체인은 단 하나의 ‘전역 객체’만으로 이루어진다. 중첩되지 않은 함수의 유효 범위 체인은 두 개의 객체로 이루어진다. 하나는 함수 매개변수와 지역 변수를 정의하는 객체고, 다른 하나는 전역 객체다. 중첩된 함수에서 유효범위 체인은 세 개 이상의 객체를 갖는다. 함수가 호출될 때, 해당 함수의 지역변수를 저장하기 위해서 새로운 객체를 하나 생성하고, 해당 객체를 기존에 저장된 유효범위 체인에 추가한다. 중첩 함수의 경우에는 외부에서 함수를 호출할 때마다 중첩된 함수가 매번 선언된다.

출처 : “JavaScript: The Definitive Guide, by David Flanagan (O’Reilly). Copyright 2011 David Flanagan, 978-0-596-80552-4”

자바스크립트 완벽가이드 2장 (어휘 구조)

프로그래밍 언어의 어휘 구조는 프로그램을 어떻게 작성해야 하는지를 알려주는 기본 규칙이다. 어휘 구조는 가장 저수준 문법이다.

2.1 문자 집합

자바스크립트 프로그램은 Unicode 문자 집합을 사용해 작성된다.

2.1.1 대소문자 구분

자바스크립트는 대소문자를 구분하는 언어이다. 그러나 HTML은 대소문자를 구별하지 않는다.

2.1.2 공백, 줄바꿈 제어 문자

자바스크립트는 프로그램 코드 내의 토큰들 사이에 있는 공백들을 무시한다. 대부분의 경우, 줄바꿈 문자도 무시한다.

2.1.3 유니코드 이스케이프 시퀀스

일부 컴퓨터 하드웨어와 소프트웨어에서는 특정 유니코드 글자들을 입력받고서 화면에 출력할 수 없는데 이와 같은 경우 프로그래머가 유니코드를 사용할 수 있도록 일련의 6자리 ASCII 문자열 시퀀스를 정의하고 있다. 유니코드 이스케이프 시퀀스는 \u로 시작하고, 그 뒤에 16진수 숫자 4개가 온다. (유니코드 이스케이프는 자바스크립트 문자열 리터럴이나 정규 표현식 리터럴에서 사용가능)

1
"café" === "caf\u00e9" // true

2.3 리터럴

리터럴(literal)은 프로그램에 직접 나타나는 데이터 값이다. 숫자, 문자열, 불리언, null 모두 리터럴이다.

2.5 선택적인 세미콜론 사용

자바스크립트가 항상 모든 줄바꿈을 세미콜론으로 해석하는 것은 아니다. 일반적으로 세미콜론 없이 코드를 해석할 수 없는 경우에만 줄바꿈을 세미콜론으로 해석한다. 일반적으로, 문장이 (, [, /, +, - 로 시작하면 자바스크립트 인터프리터는 해당 문장을 이전 문장에 이어서 해석한다.
다음 줄을 첫 줄의 문장과 이어서 하나로 처리할 수 없는 경우에만 줄바꿈을 세미콜론으로 해석한다는 일반 규칙에는 두 가지 예외가 있다.

  • return, break, continue 문 바로 다음에 사용했을 경우다. 따라서 return, break, continue와 다음에 오는 키워드 사이에 줄바꿈을 하지 말아야 한다.
  • ++나 – 연산자가 포함된 경우다.
    1
    2
    3
    4
    x
    ++
    y
    // 위코드는 x++; y가 아니라 x; ++y로 해석된다.

출처 : “JavaScript: The Definitive Guide, by David Flanagan (O’Reilly). Copyright 2011 David Flanagan, 978-0-596-80552-4”

자바스크립트 완벽가이드 1장 (자바스크립트 소개)

자바스크립트는 고수준이고 동적이며 타입을 명시할 필요가 없는 인터프리터 언어로, 객체지향 프로그래밍 스타일과 함수형 프로그래밍 스타일을 모두 잘 표현하는 언어이다.

인터프리터는 프로그래밍 언어의 소스 코드를 바로 실행하는 컴퓨터 프로그램 또는 환경을 말한다. 원시 코드를 기계어로 번역하는 컴파일러와 대비된다. 인터프리터는 다음의 과정 가운데 적어도 한 가지 기능을 가진 프로그램이다. 구글의 V8엔진 이라는것은 결국 인터프리터인것이다.
출처 : 위키백과 - 인터프리터

자바스크립트는 웹 초창기에 현재 오라클이라고 불리는 썬마이크로시스템즈에서 상표권 라이센스를 갖고 있고, 언어 자체 구현은 현재 모질라라고 불리는 넷스케이프에서 담당했다. 넷스케이프는 이 언어를 표준화 하기 위해서 **ECMA(European Computer Manufacturer’s Association)**에 제출했는데, 상표권 문제로 언어의 이름을 ECMAScript라고 정했다. 깉은 이유로, 마이크로소프트가 제작한 언어의 이름은 JScript가 되었지만 사람들은 이들 모두를 자바스크립트라고 부른다.
지난 십 년 동안 모든 웹브라우저에 탑재된 자바스크립트는 ECMAScript 3 구현체였다. 최근에는 ECMAScript 5 그리고 ECMAScript 6까지 정의되었다.
자바스크립트 언어 자체만 볼 때, 실질적인 버전은 ECMAScript 3과 5, 6뿐이다. (ECMAScript 4는 기존의 자바스크립트와 다른점이 많아 세상에 나오지 못했다.)

모든 언어는 기초적인 입출력을 처리하는 데 필요한 함수 API나 기반이 되는 플랫폼 또는 표준 라이브러리를 포함하고 있지만 자바스크립트 언어의 코어는 최소한의 API만 정의하고 입출력과 관련된 기능은 포함하고 있지 않다. 입출력을 비롯해 통신과 파일 저장, 그래픽 처리와 같은 복잡한 기능들은 자바스크립트를 내장하고 있는 **’호스트 환경’**에서 담당한다. 브라우저가 자바스크립트 엔진을 내장하고 있기 때문에 클라이언트 측 자바스크립트의 호스트 환경은 웹브라우저다.

1.1 자바스크립트 코어

표현식 (expression) : 값으로 평가될 수 있는 구절, 프로그램의 상태를 바꾸지는 않는다.

1
2
3
4
5
var book = {
topic: "Javascript",
fat: true
};
book.topic // => "Javascript"

설명문 (statement) : 프로그램의 상태를 변경할 수 있다.

1
2
3
var count = 0;
count++;
count--;

출처 : “JavaScript: The Definitive Guide, by David Flanagan (O’Reilly). Copyright 2011 David Flanagan, 978-0-596-80552-4”

정적 이미지 사용하기

React Native는 웹뷰를 통해 인터페이스를 구축하는 하이브리드 방식(예를 들면 Ionic)과는 달리 자바스크립트로 작성한 코드가 Native UI 컴포넌트로 만들어집니다. React Native에서 이미지를 사용하는 코드는 iOS와 Android 모두 통합되어 있지만, 정적인 이미지 파일을 추가하는 부분은 Naming에 있어 차이가 있습니다. 이번에는 React Native에서 정적 이미지를 사용하는 방법과, 정적 이미지 추가 시 반복되는 작업을 좀 더 효율적으로 할 수 있도록 Node를 사용하여 스크립트를 작성하는 부분을 다뤄보도록 하겠습니다. 글 작성 기준 React Native의 최신버전은 0.4입니다.

React Native 정적 이미지 사용하기

React Native에서 정적 이미지를 추가하는 방법은 공식홈페이지에서도 잘 설명되어 있지만 한번 더 살펴보겠습니다.

다음과 같이 react-native 의 기본적인 Image 컴포넌트를 통해 정적인 이미지 파일을 사용할 수 있습니다. 아래의 코드는 작성된 컴포넌트의 파일과 같은 경로에 있는 gold.png라는 파일을 사용합니다.

1
<Image source={require('./gold.png')} />

하나의 파일을 두개의 플랫폼(iOS와 Android)에서 같이 사용할 수 있지만 만약 플랫폼에 따라 다른 이미지를 사용하고 싶다면 gold.png라는 파일을 gold.android.pnggold.ios.png로 각각 저장하여 사용할 수 있습니다. 이와 같은 경우는 주로 Android와 iOS에서 같은 목적으로 사용되는 이미지가 다를 경우 유용합니다. (React Native에서 iOS와 Android의 Entry file이 index.ios.js와 index.android.js 인것과 같은 개념입니다.)

또한 React Native의 packager플랫폼 뿐만 아니라 디바이스 스크린의 해상도에 따라서도 다른 이미지를 제공할 수 있습니다. 따라서 다음과 같이 이미지 파일의 이름을 해상도에 따라 달리하여 사용할 수 있습니다.

1
2
3
4
├─ Test.js
└── img/
├── gold@2x.png
└── gold@3x.png
1
2
{/* Test.js 코드의 render 부분 */}
<Image source={require('./img/gold.png')} />

파일 구조와 Test.js의 코드가 위와 같을 때 iPhone 6와 iPhone 6 Plus는 각각 gold@2x.pnggold@3x.png 파일을 사용합니다. 만약 디바이스 스크린의 해상도에 해당하는 파일이 없다면 가장 밀접한 해상도를 가진 파일을 사용합니다.

정리하면 디바이스의 플랫폼과 해상도에 따라 파일을 사용하고 싶을 경우 다음과 같이 사용할 수 있습니다.

1
2
3
4
5
6
├─ Test.js
└── img/
├── gold@2x.android.png
├── gold@2x.ios.png
├── gold@3x.android.png
└── gold@3x.ios.png

React Native에서 정적인 이미지를 사용할 경우 주의해야할 점은 공식홈페이지를 참고하시면 좋을것 같습니다.

Native 측면에서 바라보기

React Native는 기존 Android와 iOS에서 이미지를 추가하여 사용하는 방법을 그대로 사용할 수도 있습니다. 이미 위의 방법으로 해결이 가능하며 이 방법이 좀 더 복잡하기에 사용을 권장드리지 않지만 이런방법으로도 가능하다는걸 알고계시면 좋을것 같습니다. Native에서 Android와 iOS의 이미지 파일은 다음과 같은 경로에 저장하여 사용합니다.

  • Android Test-app/android/app/src/main/res/
  • iOS Test-app/ios/Test-app/images.xcassets/
### Android Android에서 해상도별로 이미지를 추가하는 방법을 알아보겠습니다.

1.처음 프로젝트 생성시에는 drawable관련 폴더가 없으므로 android/app/src/main/res/ 에 해당 폴더들을 생성합니다.

  • drawable-mdpi
  • drawable-hdpi
  • drawable-xhdpi
  • drawable-xxhdpi
  • drawable-xxxhdpi

2.해상도 별로 각 drawable 폴더에 파일을 저장합니다. (각 폴더별 저장되는 이미지는 파일명이 모두 같아야합니다.) 파일명이 gold.png 라면 각 폴더에는 다음과 같이 존재하게 됩니다.

  • drawable-mdpi/gold.png
  • drawable-hdpi/gold.png
  • drawable-xhdpi/gold.png
  • drawable-xxhdpi/gold.png
  • drawable-xxxhdpi/gold.png

iOS

iOS에서 이미지를 추가하는 방법은 Android에 비해 좀 더 번거롭습니다. 글로 설명하는것보다 사진을 참고하는 것이 이해하기 쉽기 때문에 사진을 첨부합니다.

1.먼저 xcode에서 프로젝트의 root폴더에서 ios폴더를 로드한 후 images.xcassets 폴더를 클릭 후 AppIcon 아래의 빈공간을 우클릭하면 New Image set라는 메뉴가 있습니다. 클릭 후 1x, 2x, 3x에 이미지를 넣으신 후 이미지의 이름을 설정합니다.
xcode에서 이미지 추가1

2.위와 같이 이미지를 넣고나면 해당 경로에 다음과 같은 형식으로 파일이 생성됩니다. Contents.json은 이미지 파일에 대한 정보를 갖고 있습니다.
xcode에서 이미지 추가2

이미지 사용하기

Android와 iOS에 이미지 추가가 모두 끝났습니다. 추가한 이미지를 React Native 에서 사용해보겠습니다.

1
2
{/* Test.js 코드의 render 부분 */}
<Image source={require('image!gold')} />

위의 코드에 **image!**라는 부분의 추가와 이미지 파일의 확장자가 사라졌다는게 전과 다릅니다. 이미지의 위치를 알리는 경로 또한 명시할 필요가 사라졌습니다.

코드로 한번 더 복습하기

이제 React Native에서 정적인 이미지를 추가하는 방법을 모두 알아보았습니다. 마지막으로 코드상에서 정적인 이미지를 사용하는 방법을 정리해보겠습니다.

– Native 에서 이미지를 추가하는 방법을 사용하였을 경우

1
2
{/* Test.js 코드의 render 부분 */}
<Image source={require('image!gold')} />

– 프로젝트 폴더내에 추가 후 상대경로를 사용하는 경우

1
2
{/* Test.js 코드의 render 부분 */}
<Image source={require('./image/gold.png')} />

– 첫번째와 두번째 방법을 모두 사용하는 경우 (Native에서 사용되는 폴더에서 이미지를 찾은 후 존재하지 않을 경우 상대경로를 사용하여 이미지를 사용)

1
2
{/* Test.js 코드의 render 부분 */}
<Image source={ {uri: 'gold', isStatic: true} } />

눈으로 확인하는 결과

iPhone6와 iPhone6 Plus 에서 Gold 이미지가 기기의 해상도에 맞게 다른 파일로 사용된것을 확인할 수 있습니다.

![iPhone6 에서의 Gold 이미지](/images/post/2017-01-22/iPhone6.png)
![iPhone6Plus 에서의 Gold 이미지](/images/post/2017-01-22/iPhone6Plus.png)

다음 포스팅에서는 정적인 이미지 파일을 쉽게 추가하여 사용할 수 있도록 자동화하는 스크립트 작성에 대해서 작성하겠습니다.

.bashrc 와 .bash_profile 의 차이

bash 쉘(Shell) 이란?

쉘(Shell)은 운영체제에서 **사용자가 입력하는 명령을 읽고 해석하여 대신 실행해주는 프로그램**입니다. 운영체제 상에서 다양한 운영체제 기능과 서비스를 구현하는 인터페이스를 제공하며, 사용자와 운영체제의 내부(커널)` 사이의 인터페이스를 감싸는 층이기 때문에 셸이라는 이름이 붙었습니다. 쉘은 운영체제에서 필수적으로 존재합니다.

운영체제는 로그인한 사용자가 없다면 하나의 쉘도 실행되지 않은 상태이며, 사용자가 로그인을 시도하면 운영체제는 ID와 패스워드를 받아들이는 로기은 프로그램을 실행하고, 사용자가 입력한 ID와 패스워드를 검증한 후 인증된 사용자라면 쉘을 실행하여 사용자 세션을 쉘에게 전달합니다.

쉘의 역할은 사용자가 입력한 명령을 해석하여 대신 실행해주는 것입니다. 쉘의 내부 명령어라면 스스로 실행한 뒤 화면에 표시해주고 내부 명령어가 아니라면 PATH 환경변수에 지정된 경로에서 입력받은 명령과 같은 파일을 찾아 exec() 시스템콜을 호출하여 실행한 뒤 키보드와 마우스 등의 입력장치와 모니터에 해당하는 표준 출력장치의 제어권을 해당 프로그램에 넘겨준 뒤 프로그램이 끝날 때 까지 대기하는 역할을 합니다.

bash 쉘은 유닉스에서 사용하는 커맨드 쉘의 일종으로 GNU 프로젝트를 위해 만들어졌습니다. 초기의 유닉스 쉘인 본 쉘(Bourne Shell)과 새로 태어났다는 뜻의 영어 ‘born again’을 합쳐 **본 어게인 쉘(Bourne-again Shell)**이라고 불렸으나, 일반적으로 bash로 줄여 부릅니다.

Login Shell 과 Non-Login Shell

Login Shell

Login은 ID와 패스워드를 입력해서 Shell을 실행하는 것을 말합니다. 따라서 ssh로 접속하거나 로컬에서 GUI를 통해 Shell을 실행하는 것은 Login Shell 입니다.
.profile, .bash_profile 이 두 파일은 Login할 때 로드되는 파일입니다. .profile은 꼭 bash가 아니더라도 로그인하면 로드되며, .bash_profile은 꼭 bash로 로그인 할 때만 실행됩니다.

Non-Login Shell

Non-Login Shell은 로그인 없이 실행하는 Shell을 말합니다. ssh로 접속하고 나서 다시 bash를 실행하는 경우나, GUI 세션에서 터미널을 띄우는 것도 여기 해당합니다. ‘sudo bash’나 ‘su’같은 것도 해당합니다.

.bashrc 와 .bash_profile 의 차이

.bashrc

이미 로그인 한 상태에서 새 터미널 창을 열 때마다 로드됩니다. (Non-Login Shell에서 실행됩니다.)

.bash_profile

시스템에 로그인할 때마다 로드됩니다. (Login Shell에서 실행됩니다.) 대부분 개별 사용자에 대한 설정에 대한 코드들이 들어갑니다. 예를 들면 nvm(Node Version Manager)은 기본적으로 nvm을 사용하지 않고 Node를 설치할 때와는 다르게 각 사용자의 경로에 설치되게 되는데, 이럴때 nvm의 PATH를 .bash_profile 파일에 기재합니다.

.profile

로그인할 때 로드됩니다. 개별 사용자에 대한 설정 코드들 중 bash와는 관계없는 부분을 기재합니다.

  • 만약 Mac에서 새 터미널 창을 열 때마다 .bashrc를 로드하고 싶다면 .bash_profile에서 .bashrc를 로드하면 됩니다.
    1
    2
    3
    4
    # Source bashrc
    if [ -f ~/.bashrc ]; then
    . ~/.bashrc
    fi