함수 포인터
함수명 앞에 *만 붙여주면 함수 포인터가 선언된다.
자료형(함수 포인터 이름)(인자 목록)
- 함수 포인터도 포인터이므로 주소값 저장
함수포인터 사용 이유
- 메모리 크기 및 위치가 결정되는 시점은 컴파일 타임 또는 런타임 시점
- 컴파일 타임 시점 결정은 정적 바인딩, 런타임 시점 결정은 동적 바인딩
- 컴파일 타임 : C언어 ➡️ int a = 10
- 런타임 시점 : 자바스크립트 ➡️ var a = 10;
동적바인딩 예
- vs code의 extension들은 플러그인 방식으로 동작한다.
- 새 기능 추가하면 매번 다시 컴파일 해야 하는 불편함이 있으나 플러그인 방식 사용 시 그럴 필요 없다.
- 함수 포인터 사용은 프로그램의 유연한 확장성 제공
- 플러그인 : 규격맞 맞춰놓고 끼웠다 넣었다 할 수 있는 기능
구조체
- 하나 이상의 서로 다른 종류의 변수들을 묶어서 새로운 데이터 타입을 정의하는 것
구조체를 사용하는 이유
- 연관된 변수를 하나로 묶어 관리함으로써 데이터 관리에 유용
- 데이터 양(변수의 개수)이 많아지면 구조체가 유리함
구조체 정의
- 구조체 기본형태(학생 정보)
struct student { char name[10]; int age; int height; } - struct 키워드는 구조체라는 데이터타입을 의미
- student는 내가 만든 구조체 이름
- name, age, height는 구조체 멤버
구조체 멤버에 접근하기
- 구조체 변수를 통해 구조체 멤버의 값을 참조해야 한다.
[구조체 변수명].[구조체 멤버]
ex) st1.name, st1.age... - 멤버 접근 시 .[점] 사용을 직접 접근이라고 한다.
#include <stdio.h>
#include <string.h>
struct student {
char name[10];
int age;
int height;
}st1;
int main() {
strcpy(st1.name, "홍길동");
st1.age = 20;
st1.height = 170;
printf("이름 : %s\n, 나이 : %d\n, 키 : %d\n", st1.name, st1.age, st1.height);
return 0;
}
공용체
- 공용체도 사용자 정의 자료형이다.
- 구조체와 차이점은 메모리 공간을 공유한다는 점이다.
- 타입스크립트에서도 사용됨
열거형
- enumeration 약자로 enum이라고 읽음
- 데이터들을 열거한 집합. 연속적 데이터를 정의할 때
- 컴파일러는 열거형 멤버들을 정수형 상수로 취급한다.
enum Week { sun = 0 mon tue wed thu } - 열거형 멤버들 각 요일 나타냄
- 첫번째 멤버 sun을 0으로 설정하면 다음 멤버 mon부터 1씩 증가
#include <stdio.h>
#include <string.h>
enum Week
{
sun = 1,
mon,
tue,
wed,
thu,
fri,
sat
};
int main() {
int day;
printf("요일을 선택하세요 : ");
scanf("%d", &day);
switch(day){
case sun:
printf("일요일엔 짜파게티\n");
break;
case mon:
printf("월요일\n");
break;
case tue:
printf("화요일엔 짜파게티\n");
break;
case wed:
printf("수요일엔 짜파게티\n");
break;
case thu:
printf("목요일엔 짜파게티\n");
break;
case fri:
printf("금요일엔 짜파게티\n");
break;
case sat:
printf("토요일엔 짜파게티\n");
break;
default:
printf("잘못입력하셨습니다.\n");
break;
}
return 0;
}
메모리구조

메모리 영역
- 스택 영역 : 우리가 지금껏 사용한 지역변수 및 매개변수 등은 모두 스택 메모리 사용
- 매개변수 및 지역변수가 스택메모리에 어떤 구조로 저장되는지 보자

- 힙영역(큐 메모리) : 힙은 컴퓨터 메모리의 일부가 할당되었다가 회수되는 일들의 반복문
- 힙은 컴파일 시가 아닌 실행 시 사용자로부터 할당 메모리를 입력 받음
➡️ 동적 메모리 할당
- 힙은 컴파일 시가 아닌 실행 시 사용자로부터 할당 메모리를 입력 받음
- 데이터영역 : 전역변수와 static 변수가 저장되는 메모리 영역, 이 메모리는 프로그램 종료시 소멸
동적 메모리 할당
동적으로 메모리 할당하는 이유
- 일반 변수 선언 : 메모리 할당은 컴파일 타임에 이루어진다. int a; ➡️ 정적 할당
- 전교생 10명인 학교의 학생수 배열로 선언한다면? int student[10]
- 학생수가 늘어나게 되면? int student[100]
➡️ 이는 미봉책에 불과. 학생수가 어떻게 변할지 모른다. - 결국 학생 수는 유동적이므로 고정하지 말고 실행 시 결정하자
scanf("%d", &num);
int student[num];
- 문제점
- scanf는 런타임에 실행
- int student[num]은 컴파일타임에 실행
- 런타임에 입력받은 변수를 컴파일 타임에 대입하는 형태는 시점 논리에 맞지 않는다.
- 해결방법
- 동적 메모리 할당 기법 필요
동적 메모리 할당 및 해제
- 동적 메모리 할당 함수의 원형
void* malloc(sizeof(int)*size);- 전달인자 size는 바이트 단위로 입력
- 메모리 할당이 되면 메모리의 주소값을 리턴
- 메모리 부족 시 NULL 포인터를 리턴
- void* 의미 : 타입이 지정되지 않는 포인터.
(메모리 크기만큼 할당해줄테니, 메모리는 원하는 형태로 정해서 사용하라)
#include <stdio.h>
int main() {
int num;
int *student;
printf("학생 수 입력 :");
scanf("%d", &num);
// 스택 = 힙 메모리
student = (int*)malloc(sizeof(int) * num);
if(student == NULL){
printf("메모리가 할당되지 않았습니다.\n");
return 0;
}
printf("메모리 크기 : %d\n", sizeof(int)*num);
free(student);
return 0;
}
- 메모리 구조
// 캡처
- 메모리 할당 후 반드시 메모리 해제해줘야 한다. (메모리누수 방지)
- 앞으로 객체 기반에서 new 연산자를 이용한 객체 생성의 메모리 구조는 모두 위 형태를 기반한다.
객체 지향 프로그래밍 방식
객체지향이란?
- 객체 : 영문으로 Object, 사물을 나타내는 추상적인 개념
- 지향 : 영문으로 Oriented, '~를 향한다'는 의미
구조적 프로그랭과 객체지향 프로그래밍
- 구조적 프로그래밍 방식 - 순차적, 하향식, 폭포수 방식
- 기능적인 기본 단위는 함수이다.
- 객체지향 프로그래밍 방식
- 기능 단위는 객체이다.
- 대표적인 예가 이벤트 기반의 모든 윈도우 프로그램이다.
ex> 메모장
추상화
- 추상 : 대상에서 특징만을 뽑아낸 것
- 우리 일상의 사물들은 관념적이고 추상적인 것들이 많다.
- 사물의 공통점을 묶는 속성이 추상화
- 객체지향의 철학 = 플라톤의 이데아?
캡슐화
- 은닉하다, 숨긴다의 의미
- 외부에서 내부를 볼 수 없게 한다는 의미
- 마냥 숨기기만 한다면 데이터는 무용지물
- 외부로부터 데이터를 조작할 인터페이스가 필요
- 하나의 캡슐단위가 클래스 = 사용자 정의 타입, 구조체와 유사
- 클래스 = 데이터 + 메소드
- 은닉된 데이터 : 프로퍼티 필드 속성 멤버변수
- 멤버함수 : 메소드, 인터페이스
클래스란
- 사용자 정의 데이터 타입
- 데이터와 메소드를 사용자인 내가 새로 정의한 데이터타입이기 때문에
클래스를 추상적인 데이터타입이라고 함. - 클래스의 본질은 데이터타입이라는 점이다.
- 구조체와 비슷하다.
- 멤버 변수(데이터)와 멤버 함수(메소드)로 구성된다.
클래스의 구성
- 사물의 특성을 정리하여 필드와 메소드로 표현하는 과정이 추상화
- 추상화된 결과를 하나의 클래스에 포함시키고 스스로 보호하는 것이 캡슐화
클래스의 선언 형식
- 클래스 선언 시 class 키워드를 쓰고, 그 뒤에 클래스 이름을 붙인다.
- 클래스 요소로는 생성자, 멤버 변수, 메소드 등으로 구성
class 클래스 이름
{
접근 지정자 클래스 이름(){...}
접근 지정자 클래스 이름(){...}
접근 지정자 데이터형 멤버 변수(필드);
접근 지정자 데이터형 메소드();
}
- 접근 지정자
- public : 누구나 접근 가능
- private : 내 클래스 내부에서만 접근 가능, 외부 접근 불가
- protected : 상속 관계에 있을 때 상속 받은 자식 클래스에서 접근 가능.
객체 선언
- 클래스의 본질은 데이터타입이다.
- 데이터타입을 통해 변수를 선언할 수 있다. 변수 선언한다.
- 클래스를 통해 선언한 변수를 객체라고 한다.
객체 생성
Dog a = new Dog();

➡️ a는 주소값 가지는 포인터
using System;
class Dog{
private int eyes, nose, mouse, ears;
public void bark(){Console.WriteLine("멍멍");}
}
class HelloWorld {
static void Main() {
Dog a = new Dog();
a.bark();
}
}
생성자의 개념
- 모든 변수는 선언이 되면 값을 초기화해야 함 ➡️ 초기화함수
- 객체도 본질적으로 변수이므로 선언되면 초기화해야 한다.
- 객체 생성 시 초기화 전용 메소드를 제공하는데 바로 생성자(constructor)이다.
- 객체 생성 시 자동으로 호출되는 메소드
// 생성자 : 초기화 전용 함수
public Dog(){
eyes = 0;
nose = 0;
mouse = 0;
ears = 0;
}
Dog a = new Dog();
using System;
class Dog{
protected int eyes, nose, mouse, ears;
public void bark(){Console.WriteLine("멍멍");}
public Dog(){
eyes = 0;
nose = 0;
mouse = 0;
ears = 0;
}
}
class Pudle : Dog{
public Pudle() {
base.eyes = 2;
Console..WriteLine("푸들 눈 : {0}", eyes);
}
}
상속성
부모 ⬅️ 자식

- 이미 완성된 클래스를 다른 클래스에 상속할 수 있다.
- 부모 클래스로부터 상속받을 때 클래스 이름 끝에 콜론(:)
자바의 경우 extends 붙인 후 부모 클래스 이름 적음 - 프로젝트 관점에서 상속 개념
- A프로젝트(종료됨)
- B프로젝트(신규과제)
- A프로젝트 기능이 B프로젝트의 기능과 유사함
- B프로젝트는 A프로젝트를 상속 받고, 추가 기능만 구현하면 됨
다형성
- 함수 이름이 같더라도 전달인자의 타입이나 개수에 따라 구분된다.
- 객체지향에서는 대표적으로 오버로딩과 오버라이딩 기법이 있다.
오버로딩
- 과적하다, 적재하다 라는 의미
- 겉모습은 똑같지만 내용이 다른 경우
- 이름이 같은 함수일지라도 전달인자 타입이나 개수가 다른 경우
- 스타크래프트 오버로드 유닛의 예
- 코드로 풀어보면 같은 이름의 함수에 같은 개수의 전달인자가 서로 다른 타입으로 존재
using System;
public class Zerg{
public void Overload(int zerggling){
Console.WriteLine("저글링 {0}마리", zerggling);
}
public void Overload(int zerggling, int hydra){
Console.WriteLine("저글링 {0}마리 + 히드라 {1}마리", zerggling, hydra);
}
public void Overload(int zerggling, int hydra, int lurker){
Console.WriteLine("저글링 {0}마리 + 히드라 {1}마리 + 럴커 {1}마리",
zerggling, hydra, lurker);
}
public void Overload(char zerggling){
Console.WriteLine("저글링 {0}등급", zerggling);
}
}
class HelloWorld {
static void Main() {
Zerg zerg = new Zerg();
zerg.Overload(10);
zerg.Overload(10, 20);
zerg.Overload(10, 20, 30);
zerg.Overload('A');
}
}
오버라이딩
- 위로 올라탄다, 엎어친다는 의미
- 기존의 것을 덮어버린다는 개념
- 상속의 개념이 기반이 되어야 한다.
using System;
class Dog{
protected int eyes, nose, mouse, ears;
virtual public void bark(){Console.WriteLine("멍멍");}
public Dog(){
eyes = 0;
nose = 0;
mouse = 0;
ears = 0;
}
}
class Pudle : Dog{
public Pudle() {
base.eyes = 2;
Console.WriteLine("푸들 눈 : {0}", eyes);
}
public override void bark(){Console.WriteLine("왈왈");}
}
class HelloWorld {
static void Main(){
Dog dog = new Dog();
dog.bark();
Pudle pd = new Pudle();
pd.bark();
dog = new Pudle();
dog.bark();
}
}
인터페이스
- 메소드의 목록만을 가지고 있는 명세(Specification), 사용자 정의 타입이다.
- 메소드의 목록만 선언하고 구현은 하지 않는다.
- 인터페이스의 선언 형태
접근지정자 interface 이름 : 기반인터페이스
{
}
- 인터페이스를 상속받는 클래스 형태
접근지정자 class 자식클래스이름 : 인터페이스
{
}
인터페이스 사용하는 이유
- 인터페이스는 본체가 정의되지 않는 추상메소드만 갖는다.
- 목적은 기존의 기능을 추가/수정하는 개념보다는 동일한 개념의 기능을 새롭게 구현하는 기능
- 공동작업 시 표준을 정하는 역할
추상클래스를 상속하는 경우
- 일반적으로 클래스를 상속하는 이유는 기능의 확장이 목적
인터페이스를 상속하는 경우
- 상속관계의 개념이 아니라 여러가지 기능의 나열
- 인터페이스에서 기능을 명세하고, 자식클래스에서 상속한다.
- 인터페이스는 상속이 아니라 구현의 의미로 implements 사용
using System;
public interface IUnit{
void Attack();
void Move();
}
public class Zergling : IUnit{
public void Attack(){
Console.WriteLine("저글링 : 공격한다.");
}
public void Move(){
Console.WriteLine("저글링 : 이동한다.");
}
}
public class Dragoon : IUnit{
public void Attack(){
Console.WriteLine("드라군 : 공격한다.");
}
public void Move(){
Console.WriteLine("드라군 : 이동한다.");
}
}
class HelloWorld {
static void Main(){
Zergling zerg = new Zergling();
zerg.Attack();
zerg.Move();
Dragoon dragoon = new Dragoon();
dragoon.Attack();
dragoon.Move();
}
}
메모리 관리
- 플랫폼 기반의 객체 지향 언어는 가비지 컬렉터가 메모리를 자동관리한다.
- 백그라운드에서 더이상 사용되지 않는 메모리를 찾아 회수한다.
람다를 통한 화살표 함수의 이해
익명 메소드
- 메소드를 미리 정의하지 않고 사용할 때 정의한다.
- 익명 메소드를 사용하면 코드가 간결해진다.
- 익명 메소드는 별도의 메소드를 만들지 않으므로 코딩 오버헤드를 줄일 수 있다.
- 내용 자체가 목잡하면 안된다.
- 익명 메소드는 람다식에서 사용됨다.
람다식이란
- 기존 익명 메소드를 더욱 간결하게 만든다.
using System;
class HelloWorld {
static int Add(int a){
return a + 1;
}
delegate int CalcDele(int x);
static void Main() {
Console.WriteLine(Add(3));
CalcDele d = delegate (int x){
return x + 1;
};
Console.WriteLine(d(3));
}
}
람다식표현
(인수)=> 표현식 또는 명령문
delegete 키워드를 사라지며 화살표로 대체한다.
CalcDele d = x => x + 1;
'데브코스 웹풀스택 과정 > TIL' 카테고리의 다른 글
| 1106 프로그래밍 언어 기초문법 - C언어 포인터 (0) | 2025.11.05 |
|---|---|
| 1105 프로그래밍의 기본 원리 및 변수와 자료형 (0) | 2025.11.05 |
| 1002 쿠키와 세션 그리고 JWT(토큰 발행 및 쿠키담기, 유효기간 설정) (0) | 2025.10.02 |
| 1001 express-validator 사용해 유효성 검사 / 검사결과 처리 미들웨어 분리 (0) | 2025.10.01 |
| 0930 타임 존(timezone) 설정, 디비 연동 및 쿼리 가져오기 (0) | 2025.09.30 |