* 프로그래머스, 타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 5기 강의 수강 내용을 정리하는 포스팅.

* 원활한 내용 이해를 위해 수업에서 제시된 자료 이외에, 개인적으로 조사한 자료 등을 덧붙이고 있음.

0. JavaScript에 앞서서 C언어부터..

  • JavaScript는 여타 프로그래밍 언어와 다르게, 스크립트 언어에서 시작해서 프로그래밍 언어로 진화한 독특한 특징을 지니고 있다.

  • 따라서 JavaScript만 배운 사람이라고 하면, 프로그래밍적 사고를 기르는 것이 어렵다.



모든 프로그래밍 언어의 동작 원리는 거의 똑같다

  • 모든 프로그래밍 언어는 입력을 처리하여 출력하는 공통적인 흐름(입력 → 처리 → 출력)을 기반으로 동작한다.

  • 기본적으로 조건문, 반복문, 함수와 같은 핵심적인 구조와 원리를 공유한다.

  • 따라서 하나의 언어를 깊이 이해하면, 다른 언어로 전환하거나 학습하는 데 필요한 노력이 줄어든다.

// javaScript의 if 조건문은 Python, C, Java 등에서도 거의 동일한 방식으로 작동한다.

// JavaScript
if (x > 0) {
    console.log("양수입니다.");
}

# Python
if x > 0:
    print("양수입니다.")



JavaScript와 같은 스크립트 언어로는 동작 원리를 이해하기 힘들다..

  • 자바스크립트는 동적 타입 언어로, 명시적 타입 선언이 없고 런타임에서 타입이 결정된다.

  • 포인터, 메모리 관리 등 저수준 프로그래밍 개념이 추상화되어 있어 개발자가 직접적으로 동작 원리를 경험하기 어렵다.

  • 예를 들어, 메모리 할당 및 해제는 자바스크립트에서 Garbage Collector가 자동으로 처리하지만, C 같은 언어에서는 개발자가 직접 관리해야 한다.

  • 변수의 타입도 마찬가지. let과 const만 존재하는 JavaScript와 달리, 다른 언어들은 숫자를 다루는 타입만 int, long, float, double 등이 존재한다.

// JavaScript:
let x = 10; // 동적 타입, x는 숫자로 할당됨

// C언어:
int x = 10; // 정적 타입, x는 정수로 선언됨

Hello, World! 출력으로 보는 두 언어의 차이점

#include <stdio.h>

int main()
{
    printf("Hello World");

    return 0;
}
console.log("Hello World");
  • C 언어는 소스 코드를 작성한 후 컴파일러(예: GCC)를 사용하여 기계어로 변환해야 실행할 수 있다.
    - #include <stdio.h>: printf 함수가 포함된 표준 입출력 라이브러리 헤더 파일을 포함.
    - main 함수: 프로그램 실행의 진입점(entry point).
    - return 0;: 프로그램이 성공적으로 종료되었음을 운영체제에 알림.
    (JavaScript는 코드를 실행하기 전에 별도의 컴파일 단계가 없고, JavaScript 엔진이 코드를 직접 실행한다.)
    (JavaScript는 C 언어의 헤더 파일이나 함수 선언이 필요 없이 바로 실행한다.)



특성C 언어JavaScript
언어 유형컴파일 언어인터프리터 언어
출력 함수printf("Hello World");console.log("Hello World");
필요한 준비 작업컴파일(예: GCC) 후 실행실행 환경(Node.js, 브라우저)만 필요
출력 대상터미널(콘솔)터미널(콘솔) 또는 브라우저 콘솔
코드 구조헤더 파일 및 진입점(main 함수) 필요단순히 console.log 호출로 가능
실행 속도컴파일된 실행 파일이 더 빠름해석 중 실행하므로 상대적으로 느림



C 언어의 변수와 데이터타입, 배열, 포인터 등의 동작 원리들은 자바스크립트 언어 동작의 근간을 이룬다.

  • 자바스크립트는 고수준 언어로, 많은 저수준 언어의 동작 원리를 추상화하여 사용자가 쉽게 프로그래밍할 수 있도록 설계되었다.

  • C 언어의 개념인 변수, 데이터타입, 배열, 포인터 등은 자바스크립트 내부적으로 동작 원리에 영향을 준다.

  • 예를 들어, 자바스크립트 객체의 참조는 C 언어의 포인터와 유사하다.



타입을 변수와 함수에 기본으로 사용해보면 타입스크립트를 더 쉽게 이해할 수 있다.

  • 타입스크립트(TypeScript)는 자바스크립트에 정적 타입(static typing)을 추가한 언어이다.

  • C, Java와 같이 변수와 함수에 타입을 명시적으로 선언하는 방식을 사용하면, 타입스크립트 학습에 더 쉽게 적응할 수 있다.

  • 타입을 명시적으로 선언하면, 코드의 안정성과 가독성이 향상되며, 에러를 사전에 방지할 수 있다.

  • TypeScript로 작성된 코드는 컴파일 과정을 거쳐 바닐라 JavaScript로 전환된다. 사실상 컴파일 개념이 있는 동적 프로그래밍 언어와 원리가 비슷하다는 뜻.



1. 프로그래밍의 기본 원리

프로그래밍 개념과 원리

개념

  • 컴퓨터가 작업을 수행하도록 명령어를 작성하는 과정. 목표는 문제를 해결하기 위한 효율적이고 논리적인 코드 작성이다.

원리:

  • 입력 → 처리 → 출력의 흐름을 통해 데이터를 조작하며, 재사용 가능성과 유지 보수성을 고려하여 코드를 작성한다.



프로그램 개발 과정

  • 요구사항 분석: 해결하려는 문제를 이해하고 요구사항을 정의한다.

  • 설계: 프로그램의 구조와 로직을 설계(플로우차트, 의사코드 작성 등).

  • 코딩: 설계에 따라 소스 코드를 작성.

  • 테스트 및 디버깅: 코드의 정확성을 검증하고 오류를 수정.

  • 배포 및 유지보수: 프로그램을 사용자에게 제공하고 업데이트 및 오류 수정.

  • 자세한 내용은 이전 포스팅 - 폭포수 모델과 애자일 방법론 참조.



변수와 자료형, 연산자

변수

  • 데이터를 저장하는 메모리 공간의 이름.

  • 어떤 값을 기억할 때, 메모리 주소를 기억하는 것보다는 명확한 의미를 가지는 '문자열'로 기억하는게 더 좋다. 변수라는 형태를 사용하는 이유.

  • 선언 시 데이터 타입을 지정하며, 메모리 크기와 표현 가능한 값의 범위를 결정.

int a = 10; // 정수형 변수
float b = 3.14; // 실수형 변수
char c = 'A'; // 문자형 변수

자료형

기본 자료형:

  • int: 정수형 (4바이트)
  • float: 실수형 (4바이트)
  • double: 배정밀도 실수형 (8바이트)
  • char: 문자형 (1바이트)

파생 자료형:

  • 배열(Array), 구조체(Struct), 공용체(Union), 열거형(Enum), 포인터(Pointer).

연산자

  • 산술 연산자: +, -, *, /, %
  • 관계 연산자: ==, !=, <, >, <=, >=
  • 논리 연산자: &&, ||, !
  • 비트 연산자: &, |, ^, ~, <<, >>
  • 대입 연산자: =, +=, -=, *=, /=, %=
int a = 10, b = 20;

int sum = a + b; // 산술 연산

if (a < b) { // 관계 연산
    printf("a는 b보다 작다.\n");
}



메모리의 4가지 주요 영역

  • 컴퓨터 프로그램이 실행될 때, 메모리는 코드 영역, 스택 영역, 힙 영역, 데이터 영역으로 나뉜다.

  • 각 영역은 메모리에서 서로 다른 역할을 하며, 변수와 실행 명령어 등을 저장하는 데 사용된다.

1. 코드 영역 (Code Segment)

  • 실행할 명령어(코드)를 저장하는 영역이다.

  • 컴파일된 프로그램의 바이너리 코드가 이 영역에 로드된다.

  • 보통 읽기 전용으로 설정되어 있어 실행 중에 수정할 수 없다.

  • 함수의 코드, 제어문 등이 저장된다.

  • 수정이 불가능하므로 프로그램의 안정성을 높인다.

int main() { ... }과 같은 함수의 기계어 코드.

2. 스택 영역 (Stack Segment)

  • 함수 호출과 관련된 지역 변수와 매개변수를 저장한다.

  • 함수가 호출되면 새로운 스택 프레임이 생성되고, 함수 실행이 종료되면 스택 프레임이 제거된다.

  • 메모리가 자동으로 관리된다.

  • LIFO(Last In First Out) 구조로 동작.

  • 스택 오버플로우(Stack Overflow)가 발생할 수 있음 (예: 재귀 호출 무한 루프).

void func() {
    int localVar = 10; // 스택에 저장
}

3. 힙 영역 (Heap Segment)

  • 동적 메모리 할당을 위해 사용되는 영역이다.

  • 프로그래머가 필요에 따라 메모리를 할당하고, 해제해야 한다.

  • 메모리 크기가 프로그램 실행 중 동적으로 결정된다.

  • 명시적으로 할당(malloc, new)과 해제(free, delete)를 수행해야 한다.

  • 해제를 잊으면 메모리 누수(memory leak)가 발생할 수 있음.

int* ptr = (int*)malloc(sizeof(int)); // 힙에 메모리 할당
*ptr = 10; // 값 저장
free(ptr); // 메모리 해제

4. 데이터 영역 (Data Segment)

  • 프로그램 실행 동안 유지되는 전역 변수와 정적 변수(static 변수)가 저장된다.

  • 초기화된 데이터와 초기화되지 않은 데이터로 나뉜다.

  • 전역 변수와 정적 변수는 프로그램이 실행되는 동안 메모리에 계속 존재.

  • 프로그램이 시작될 때 초기화되며, 종료 시까지 유지된다.

  • BSS(Block Started by Symbol): 초기화되지 않은 전역 변수, 정적 변수.

  • Data Segment: 초기화된 전역 변수, 정적 변수.

코드 복사
int globalVar = 10; // 데이터 영역에 저장
static int staticVar = 20; // 데이터 영역에 저장



변수와 상수

1. 변수 (Variable)

  • 변하는 값을 저장하는 메모리 공간.
  • 데이터를 저장할 메모리 공간을 선언하고, 해당 메모리에 접근할 이름(변수명)을 부여.

데이터 타입 지정:

  • 변수가 저장할 데이터의 유형(정수, 실수, 문자 등)을 지정해야 함.

초기화 가능:

  • 변수를 선언하면서 값을 할당하거나, 선언 후 값을 할당할 수 있음.

값 변경 가능:

  • 변수에 저장된 값은 프로그램 실행 중 언제든지 변경 가능.

예시

데이터타입 변수명 = 초기값;
#include <stdio.h>

int main() {
    int age = 25;          // 정수형 변수 선언 및 초기화
    float pi = 3.14;       // 실수형 변수 선언 및 초기화
    char grade = 'A';      // 문자형 변수 선언 및 초기화

    printf("Age: %d\n", age);  // Age: 25
    printf("Pi: %.2f\n", pi);  // Pi: 3.14
    printf("Grade: %c\n", grade); // Grade: A

    age = 30;              // 변수 값 변경
    printf("Updated Age: %d\n", age); // Updated Age: 30

    return 0;
}

2. 상수 (Constant)

  • 변하지 않는 값을 저장하는 메모리 공간.

  • 프로그램 실행 중 값이 고정되어 변경되지 않음.

값 변경 불가능:

상수로 선언된 값은 초기화 이후 변경할 수 없음.

읽기 전용 데이터:

코드의 안정성을 높이며, 값의 무결성을 유지.

const 키워드 사용:

const 데이터타입 상수명 =;

#define 전처리기 사용:

#define 상수명 값

예시

  • const 키워드
#include <stdio.h>

int main() {
    const float PI = 3.14;  // 실수형 상수 선언

    printf("Pi: %.2f\n", PI); // Pi: 3.14

    // PI = 3.14159;  // 오류: 상수 값 변경 불가

    return 0;
}
  • #define 전처리기
#include <stdio.h>
#define MAX 100  // 상수 정의

int main() {
    printf("Max value: %d\n", MAX); // Max value: 100

    // MAX = 200;  // 오류: #define으로 정의된 상수는 변경 불가

    return 0;
}

3. 변수와 상수의 차이점

특성변수상수
값의 변경변경 가능변경 불가능
메모리읽기 및 쓰기 가능읽기 전용
선언 방식데이터타입 변수명const 또는 #define 사용
사용 목적가변적인 데이터 저장고정된 값(예: 수학적 상수, 설정 값) 저장
예시int x = 10;const int y = 100; 또는 #define Z 200

4. 변수와 상수의 활용

변수의 활용

  • 데이터를 저장하고 동적으로 변경해야 하는 경우.
  • 예: 사용자 입력, 계산 결과 저장.
#include <stdio.h>

int main() {
    int a, b;
    printf("Enter two numbers: ");
    scanf("%d %d", &a, &b);  // 사용자로부터 입력 받기

    int sum = a + b;  // 변수 사용
    printf("Sum: %d\n", sum);

    return 0;
}

상수의 활용

  • 변하지 않는 값(예: 수학적 상수, 프로그램 설정 값)을 저장.

  • 코드의 안정성을 높이고 가독성을 향상.

#include <stdio.h>
#define TAX_RATE 0.1  // 세율 정의

int main() {
    const float PI = 3.14;

    float radius = 5.0;
    float area = PI * radius * radius;  // 원의 넓이 계산
    printf("Area of circle: %.2f\n", area);

    float income = 1000.0;
    float tax = income * TAX_RATE;  // 세금 계산
    printf("Tax: %.2f\n", tax);

    return 0;
}

5. 요약

  • 변수는 프로그램 실행 중 값이 변경될 수 있는 데이터 저장소.

  • 상수는 프로그램 실행 중 값이 변경되지 않는 데이터 저장소.

  • const와 #define을 통해 상수를 선언하며, 코드의 안정성을 높이는 데 사용.

  • 변수와 상수를 적절히 활용하면 프로그램의 가독성, 안정성, 유지보수성이 향상된다.

profile
프론트엔드 개발자를 준비하고 있습니다.

0개의 댓글