Skip to content

MATLAB 치트시트

공학 및 과학을 위한 수치 컴퓨팅 환경.

01

행렬과 기본 연산

행렬과 벡터 생성

MATLAB(MATrix LABoratory)은 모든 변수를 행렬로 취급합니다. 벡터는 1xN 또는 Nx1 행렬입니다. 행의 요소를 구분할 때는 공백이나 콤마를 사용하고, 새 행은 세미콜론으로 시작합니다. zeros, ones, eye, rand, magic이 일반적인 테스트 행렬을 생성합니다. 콜론 연산자 start:step:stop는 범위를 생성합니다(기본 step는 1). linspace(a, b, n)는 n개의 균일 간격 점을 생성하며 플롯 축에 이상적입니다.

matlab
% row vector
v = [1 2 3 4 5];

% column vector (semicolon = new row)
c = [1; 2; 3];

% 3x3 matrix
A = [1 2 3; 4 5 6; 7 8 9];

% special matrices
Z = zeros(3);          % 3x3 zeros
O = ones(2, 4);        % 2x4 ones
I = eye(3);            % 3x3 identity
R = rand(2, 3);        % 2x3 uniform random
N = randn(4);          % 4x4 normal random
M = magic(4);          % 4x4 magic square
D = diag([1 2 3]);     % diagonal matrix

% linear spacing
l = linspace(0, 1, 5); % [0 0.25 0.5 0.75 1]
r = 0:0.5:2;           % [0 0.5 1 1.5 2]

행렬 인덱싱과 슬라이싱

MATLAB은 1-기반 인덱스입니다(0-기반이 아님). 콜론 :은 '전체'를 의미합니다 — A(:,2)는 두 번째 열 전체입니다. A(1:3, :)는 1-3행을 선택합니다. 'end'는 해당 차원의 마지막 인덱스를 가리킵니다. 논리 인덱싱(A(A > 5))은 매우 강력합니다 — 조건에 맞는 요소를 추출하거나 수정합니다. find는 0이 아닌/참인 요소의 인덱스를 반환하며, 두 개의 출력을 사용하면 행과 열을 따로 반환합니다.

matlab
A = magic(4);          % 4x4 magic square

% single element (1-indexed!)
A(2, 3)                % row 2, col 3

% entire row or column
A(1, :)                % first row (all columns)
A(:, 2)                % second column (all rows)

% submatrix
A(1:2, 2:4)            % rows 1-2, cols 2-4

% linear indexing (column-major)
A(5)                   % 5th element counting down columns

% end keyword
A(end, :)              % last row
A(:, end-1)            % second-to-last column

% logical indexing
A(A > 10)              % all elements > 10 (as vector)
A(A > 10) = 0;         % set large elements to 0

% find indices
[r, c] = find(A == 16) % row and col of value 16

행렬 연산

연산자 앞의 점(.*)은 행렬 연산 대신 요소별 연산을 수행합니다 — 이것은 초보자 버그의 1번 원인입니다. A*B는 행렬 곱셈이고; A.*B는 대응 요소를 곱합니다. 백슬래시 연산자(\)는 선형 시스템을 빠르고 정확하게 풉니다(LU 분해) — x = A\b를 inv(A)*b보다 항상 선호하세요. 어포스트로피(')는 전치합니다; 복소수 행렬에서는 비켤레 전치를 위해 .'를 사용하세요.

matlab
A = [1 2; 3 4];
B = [5 6; 7 8];

% matrix operations
C = A + B;             % addition
D = A - B;             % subtraction
E = A * B;             % matrix multiplication
F = A';                % transpose
G = A^2;               % matrix power (A * A)

% element-wise operations (use the dot!)
H = A .* B;            % element-wise multiply
I = A ./ B;            % element-wise divide
J = A .^ 2;            % element-wise power
K = 2 * A;             % scalar multiply

% matrix functions
det(A)                 % determinant
inv(A)                 % inverse
pinv(A)                % pseudo-inverse
rank(A)                % rank
trace(A)               % trace (sum of diagonal)

% solving linear systems Ax = b
b = [5; 11];
x = A \ b;              % left division: solves A*x = b
x = inv(A) * b;        % equivalent but slower

행렬 조작

[A B](공백)는 수평으로 결합하고; [A; B](세미콜론)는 수직으로 결합합니다 — 행 생성 구문과 동일합니다. reshape는 열 우선(아래로 내린 후 옆으로)으로 채웁니다. flipud/fliplr/rot90는 행렬을 재배열합니다. repmat은 격자 패턴으로 행렬을 반복 배치합니다. 행이나 열을 []로 설정하면 삭제됩니다. size는 차원을, length는 가장 큰 차원을, numel은 총 요소 수를 반환합니다.

matlab
A = [1 2; 3 4];
B = [5 6; 7 8];

% concatenation
C = [A B];             % horizontal: [1 2 5 6; 3 4 7 8]
D = [A; B];            % vertical: 4x4

% reshape
E = reshape(1:12, 3, 4);  % 3x4 matrix from 1..12

% flip and rotate
F = flipud(A);         % flip up-down
G = fliplr(A);         % flip left-right
H = rot90(A);          % rotate 90 degrees

% repmat (tile)
I = repmat([1 2], 2, 3);  % repeat [1 2] in a 2x3 grid

% size and length
[m, n] = size(A);      % m=2, n=2
len = length(A);       % max dimension = 2
num = numel(A);        % total elements = 4

% remove rows/cols
A(2, :) = [];          % delete row 2
A(:, 1) = [];          % delete column 1

요소별 함수와 벡터화

MATLAB의 강점은 벡터화입니다 — 전체 배열에 한 번에 연산을 적용하며, 내부적으로 최적화된 C/Fortran으로 실행됩니다. sin, exp, sqrt 등은 자동으로 요소별로 동작합니다. sum/prod/max/min은 기본적으로 열 단위(차원 1)로 동작합니다; 행 단위를 원하면 차원 2를 전달하세요. A(:)는 행렬을 벡터로 평탄화합니다. 성능을 위해 for 루프보다 벡터화 연산을 항상 선호하세요 — 10-100배 더 빠를 수 있습니다.

matlab
% math functions operate element-wise
x = 0:0.1:2*pi;
y = sin(x);            % sine of each element
z = exp(x);            % exponential
w = sqrt(x);           % square root

% rounding
round(3.7)             % 4
floor(3.7)             % 3
ceil(3.2)              % 4
fix(-3.7)              % -3 (toward zero)

% sums and products along dimensions
A = magic(3);
sum(A)                 % sum of each column (row vector)
sum(A, 2)              % sum of each row (column vector)
sum(A(:))              % sum of ALL elements
prod(A)                % product of each column
cumsum(A)              % cumulative sum

% min, max, sort
[v, i] = max(A(:))     % max value and its index
sort(A, 'descend')     % sort each column descending

% AVOID loops — vectorize!
% BAD: for i=1:1000, y(i)=sin(i); end
% GOOD:
i = 1:1000;
y = sin(i);            % fast, vectorized
02

제어 흐름과 논리

If / Elseif / Else

MATLAB은 if/elseif/else/end를 사용합니다(주의: elseif는 한 단어). 논리 연산자: &&(스칼라 AND), ||(스칼라 OR), &(요소별 AND), |(요소별 OR), ~(NOT, !가 아님). 문자열 비교에는 strcmp/strcmpi(대소문자 무시)를 사용하세요 — == 연산자는 같은 길이의 문자 배열에서만 작동합니다. 블록은 항상 'end'로 끝내야 합니다.

matlab
score = 85;

if score >= 90
    grade = 'A';
elseif score >= 80
    grade = 'B';
elseif score >= 70
    grade = 'C';
else
    grade = 'F';
end

disp(grade);  % B

% logical operators: && (and), || (or), ~ (not)
if x > 0 && x < 10
    disp('in range');
end

% compare strings with strcmp
if strcmp(name, 'Alice')
    disp('hi Alice');
end

For와 While 루프

for는 주어진 표현식의 각 열을 순회합니다(벡터의 경우 각 요소). while은 조건이 참인 동안 실행됩니다. 루프 전에 항상 배열을 미리 할당하세요(result = zeros(1,N)) — 루프 안에서 배열을 키우면 매 반복마다 재할당이 발생해 매우 느립니다. 콜론 연산자 1:5는 [1 2 3 4 5]를 생성합니다. fprintf는 포맷된 출력을 인쇄합니다(C의 printf처럼).

matlab
% for loop over a range
for i = 1:5
    fprintf('i = %d\n', i);
end

% iterate over a vector
v = [10 20 30];
for val = v
    disp(val);
end

% nested loop over a matrix
A = zeros(3, 3);
for r = 1:3
    for c = 1:3
        A(r, c) = r * c;
    end
end

% while loop
n = 10;
while n > 1
    n = n / 2;
    fprintf('%.2f\n', n);
end

% preallocate for speed (IMPORTANT!)
result = zeros(1, 1000);
for i = 1:1000
    result(i) = i^2;
end

Switch와 Break/Continue

switch는 값을 case 레이블과 비교합니다 — break가 필요 없습니다(C/Java와 다름). case는 여러 값을 위해 셀 배열을 받을 수 있습니다. otherwise가 기본값입니다. break는 가장 안쪽 루프를 빠져나가고; continue는 다음 반복으로 건너뜁니다. try/catch는 오류를 우아하게 처리합니다; ME는 .message와 .identifier를 가진 MException 객체입니다. MATLAB에는 삼항 연산자가 없습니다 — if/else나 인라인 함수를 사용하세요.

matlab
% switch statement
method = 'linear';
switch method
    case 'linear'
        disp('using linear');
    case 'cubic'
        disp('using cubic');
    case {'nearest', 'spline'}
        disp('using nearest or spline');
    otherwise
        disp('unknown method');
end

% break and continue
for i = 1:10
    if i == 5
        break        % exit the loop entirely
    end
    if mod(i, 2) == 0
        continue     % skip to next iteration
    end
    disp(i);         % prints 1 3
end

% try-catch for error handling
try
    x = 1 / 0;       % may error
catch ME
    fprintf('Error: %s\n', ME.message);
end

논리 연산과 인덱싱

논리 인덱싱은 MATLAB의 핵심 기능입니다 — A(condition)은 논리 배열이 참인 요소를 선택합니다. ~=는 '같지 않음'입니다(!=가 아님). &와 |는 요소별이고; &&와 ||는 단락 평가입니다(스칼라만 가능, if 조건에서 선호됨). find는 참 값의 선형 인덱스를 반환합니다. any/all은 차원을 따라 임의의/모든 요소가 참인지 검사합니다. is* 계열 함수는 타입과 특수 값(NaN, Inf)을 검사합니다.

matlab
A = [1 2 3 4 5 6 7 8 9 10];

% comparison operators
A > 5                  % logical array
A == 5
A ~= 5                 % not equal (NOT !=)
A >= 3 & A <= 7        % element-wise AND
A < 3 | A > 7          % element-wise OR

% logical indexing (powerful!)
A(A > 5)               % [6 7 8 9 10]
A(A > 5) = 0;          % set elements > 5 to 0
A(mod(A, 2) == 0)      % even numbers

% find indices
idx = find(A > 5);     % indices of elements > 5
[r, c] = find(A > 5);  % row and col (for matrices)

% any and all
any(A > 5)             % true if ANY element > 5
all(A > 0)             % true if ALL elements > 0
any(A > 5, 2)          % per row

% is functions
isnan(x); isinf(x); isfinite(x);
isnumeric(x); ischar(x); iscell(x);

문자열과 포매팅

MATLAB에는 두 가지 문자열 타입이 있습니다: 문자 배열('text', 레거시)과 문자열 스칼라("text", R2017+). 문자열 스칼라는 조작에 더 유연합니다. sprintf는 포맷된 문자열을 반환하고; fprintf는 콘솔이나 파일에 인쇄합니다. 일반 포맷 지정자: %s(문자열), %d(정수), %f(실수), %.2f(소수점 2자리), %e(과학 표기법). strsplit/strjoin은 구분자 목록을 처리합니다. num2str/mat2str는 숫자를 문자열로 변환합니다.

matlab
% string creation
s1 = 'Hello';          % char array
s2 = "World";          % string scalar (R2017+)

% concatenation
greeting = [s1 ', ' s2 '!'];  % char array concat
full = s1 + " " + s2;          % string concat

% formatting
name = 'Alice';
age = 30;
fprintf('Name: %s, Age: %d\n', name, age);
str = sprintf('Pi is %.2f', pi);  % returns string

% common string functions
upper('hello')         % HELLO
lower('WORLD')         % world
strlength("hello")     % 5 (string)
length('hello')        % 5 (char array)
strcmp('a', 'a')       % true
strfind('hello', 'll') % 3 (index)
strrep('cat', 'c', 'b') % bat
strsplit('a,b,c', ',') % {'a','b','c'}
strjoin({'a','b'}, '-') % a-b
num2str(42)             % '42'
03

함수와 스크립트

함수 정의

함수는 같은 이름의 파일에 있어야 합니다(add 함수는 add.m). 함수 선언은 첫 번째 줄입니다. 함수는 자체 작업 공간을 가집니다(기본 작업 공간과 분리). nargin/nargout로 선택적 인수를 처리합니다 — nargin은 실제 입력 수를 셉니다. 다중 출력은 [a, b] = func()로 캡처합니다. 더 적은 출력으로 호출하면 추가 출력은 버려집니다.

matlab
% function in a file named 'add.m'
function result = add(a, b)
    % ADD returns the sum of a and b
    result = a + b;
end

% with multiple inputs and outputs
function [mn, mx, avg] = stats(v)
    mn = min(v);
    mx = max(v);
    avg = mean(v);
end

% calling functions
s = add(3, 4);              % 7
[lo, hi, mu] = stats([1 2 3 4 5]);

% capture only first output
minimum = stats([1 2 3]);   % gets mn only

% nargin and nargout (number of args)
function y = power(x, n)
    if nargin < 2
        n = 2;              % default value
    end
    y = x .^ n;
end

익명 함수와 인라인 함수

익명 함수(@(args) expr)는 인라인으로 정의된 빠른 한 줄 함수입니다 — 파일 생성 없이 솔버(fzero, integral, ode45)에 전달하기에 완벽합니다. 생성 시점의 작업 공간 변수를 캡처합니다. 함수 핸들(@sin)은 내장 또는 사용자 함수를 인수로 전달하게 합니다. 이것은 수치 계산에 필수적입니다: integral(@(x) f(x), a, b)는 정의한 어떤 함수든 적분합니다.

matlab
% anonymous function (one-liner, no file needed)
square = @(x) x .^ 2;
square(5)              % 25
square([1 2 3])        % [1 4 9]

% with multiple inputs
add = @(a, b) a + b;
add(3, 4)              % 7

% capture variables from workspace
c = 10;
addc = @(x) x + c;
addc(5)                % 15

% function handle to built-in
f = @sin;
f(pi/2)                % 1

% pass functions as arguments
result = integral(@(x) x.^2, 0, 1);  % integrate x^2 from 0 to 1
result = fzero(@(x) x^2 - 2, 1);     % find root near 1

% array of function handles
funs = {@sin, @cos, @tan};
funs{1}(0)             % 0

스크립트와 라이브 스크립트

스크립트는 기본 작업 공간에서 실행되는 명령 시퀀스입니다(분리된 작업 공간을 가진 함수와 다름). %% 마커는 Ctrl+Enter로 독립적으로 실행할 수 있는 '셀'(섹션)을 생성합니다 — 점진적 개발에 좋습니다. 라이브 스크립트(.mlx)는 Jupyter 노트북과 같습니다: 코드, 포맷된 텍스트, 수식, 인라인 플롯을 하나의 대화형 문서로 결합합니다. 재사용 가능한 코드에는 스크립트보다 함수를 선호하세요.

matlab
% A script is just a sequence of commands in a .m file
% It shares the base workspace

% script: analyze_data.m
data = load('data.mat');
cleaned = data.values(data.values > 0);
mean_val = mean(cleaned);
fprintf('Mean: %.2f\n', mean_val);
plot(cleaned);
title('Cleaned Data');

% sections (cells) with %%
%% Initialize
x = linspace(0, 2*pi, 100);

%% Plot
plot(x, sin(x));

%% Analyze
disp(mean(sin(x)));

% Run a section: Ctrl+Enter (in editor)
% Live Scripts (.mlx): rich text, inline plots, equations

중첩 함수와 로컬 함수

스크립트는 파일 끝에 로컬 함수를 포함할 수 있습니다(R2016b부터) — 해당 파일 내에서만 보입니다. 중첩 함수(다른 함수 내부에 정의)는 부모의 작업 공간을 공유하므로 변수를 읽고 수정할 수 있습니다 — 콜백과 누적기에 유용하지만 코드 이해를 어렵게 할 수 있습니다. 함수 파일의 로컬 함수는 해당 파일 내에서만 보이는 헬퍼입니다. 로컬 함수를 사용하여 많은 파일을 만들지 않고 스크립트를 정리하세요.

matlab
% local functions in a script (must be at the end)
% main_script.m
x = 1:10;
y = process(x);
disp(y);

function r = process(v)
    r = normalize(scale(v));  % calls another local function
end

function s = scale(v)
    s = v * 10;
end

function n = normalize(v)
    n = v / max(v);
end

% nested function (inside another function)
function outer(x)
    y = 0;
    function inner()
        y = y + x;    % can access outer's variables
    end
    inner();
    disp(y);
end

변수 스코프와 Global

MATLAB은 값으로 인수를 전달합니다(수정 시 복사), 따라서 함수가 호출자 변수를 실수로 변경할 수 없습니다 — C/Python과 다릅니다. 진정으로 공유되는 상태에는 global을 사용하지만(사용하는 모든 함수에서 선언), 인수 전달을 선호하세요. persistent 변수는 함수 호출 간에 값을 유지합니다(C의 static처럼) — 카운터, 캐시, 메모이제이션에 유용합니다. 첫 호출 시 isempty 검사로 persistent 변수를 초기화하세요. 함수 반환값이나 중첩 함수를 대신해 글로벌 사용을 피하세요.

matlab
% base workspace variables
x = 10;

% functions have their OWN workspace
function y = myfunc()
    % x is NOT accessible here
    y = 5;
end

% pass by value (modifications don't affect caller)
function y = modify(v)
    v = v * 2;        % local copy
    y = v;
end
a = 5;
b = modify(a);        % b=10, a still 5

% global variables (use sparingly!)
global COUNTER
COUNTER = 0;
function increment()
    global COUNTER
    COUNTER = COUNTER + 1;
end

% persistent variables (like static in C)
function counter()
    persistent count
    if isempty(count)
        count = 0;
    end
    count = count + 1;
    disp(count);
end
04

데이터 구조

셀 배열

셀 배열은 MATLAB의 혼합 타입 데이터 컨테이너입니다(Python 리스트처럼). 셀의 내용에 접근하려면 중괄호 {}를, 셀을 가져오려면 괄호()를 사용하세요(슬라이싱에 유용). 이 구분이 중요합니다: c{1}은 문자열을, c(1)은 문자열을 담은 셀을 줍니다. 셀은 다른 길이의 문자열, 가변 크기 행렬, 들쭉날쭉한 데이터를 처리하는 데 필수적입니다. num2cell/mat2cell은 숫자 배열과 셀 간 변환합니다.

matlab
% cell arrays hold mixed data types
c = {'Alice', 30, [1 2 3], magic(2)};

% access with {} (content) vs () (cell)
c{1}                  % 'Alice' (the string itself)
c(1)                  % {'Alice'} (a 1x1 cell)
c{3}(2)               % 2 (second element of third cell)

% modify and append
c{2} = 31;
c{end+1} = 'new';     % append
c{5} = 'skip';        % auto-fills gaps with []

% multi-dimensional cell array
c2 = {'a', 'b'; 'c', 'd'};  % 2x2 cell

% iterate over cells
for i = 1:numel(c)
    disp(c{i});
end

% convert: cell2mat, mat2cell, num2cell
nums = num2cell(1:5);  % {1, 2, 3, 4, 5}

구조체와 테이블

구조체는 이름이 있는 필드로 관련 데이터를 그룹화합니다 — 메서드 없는 객체 같습니다. 테이블(R2013+)은 MATLAB의 데이터프레임입니다: 열 지향, 이름이 있는 변수와 행 이름. 테이블은 CSV/Excel 데이터에 이상적입니다. 이름(T.ages)이나 인덱스로 열에 접근합니다. 논리 인덱싱은 행에 작동합니다: T(T.age > 25, :)는 행을 필터링합니다. summary()는 각 열의 통계를 제공합니다. 테이블은 데이터 입출력을 위해 readtable/writetable과 통합됩니다.

matlab
% struct: named fields with any data
user.name = 'Alice';
user.age = 30;
user.scores = [90 85 88];
disp(user.name);      % Alice

% struct constructor
s = struct('name', 'Bob', 'age', 25, 'active', true);

% array of structs
users(1) = struct('name', 'Alice', 'age', 30);
users(2) = struct('name', 'Bob', 'age', 25);
disp(users(2).name);  % Bob

% table (like a dataframe) — great for tabular data
names = {'Alice'; 'Bob'; 'Carol'};
ages = [30; 25; 28];
scores = [90; 85; 88];
T = table(names, ages, scores);

% access table columns
T.ages               % column as array
T(:, 2)              % column as table
T(1:2, :)            % first 2 rows
T.age > 26           % logical indexing
T(T.age > 26, :)     % rows where age > 26

% summary statistics
summary(T)

문자열 배열과 문자 처리

현대 MATLAB(R2017+)은 문자 배열('text')보다 문자열 배열("text")을 선호합니다. 문자열 배열은 벡터화 연산을 지원합니다: strlength, +, split, join, contains, matches, replace가 모두 요소별로 작동합니다. 문자 배열은 이전 코드에서 여전히 흔하고 일부 함수에 필요합니다. 텍스트 모음에는 문자열 배열을 사용하세요; 패딩이나 셀이 필요한 문자 배열과 달리 다른 길이를 자연스럽게 처리합니다.

matlab
% string array (R2017+) — recommended for text
names = ["Alice", "Bob", "Carol"];
names(1)              % "Alice"
names'                % column string array
strlength(names)      % [5 3 5]

% char array (legacy)
c = 'Hello World';
c(1:5)                % 'Hello'
size(c)               % [1 11]

% cell array of char vectors (legacy mixed-length)
old = {'Alice', 'Bob', 'Carol'};

% convert between types
s = string('hello');          % char -> string
c = char("hello");            % string -> char
cellarr = cellstr(names);     % string array -> cell of char

% combine and split
full = "Alice" + " " + "Smith";  % "Alice Smith"
parts = split("a,b,c", ",");     % ["a", "b", "c"]
joined = join(["a" "b" "c"], "-"); % "a-b-c"

% pattern matching
matches(names, 'A*')  % logical: [true false false]
contains(names, 'li') % [true false false]
replace("hello", 'l', 'L')  % "heLLo"

Containers.Map과 집합

containers.Map은 MATLAB의 키-값 사전(해시 맵)입니다 — 조회 테이블과 설정에 유용합니다. 키는 문자열이나 숫자일 수 있습니다. isKey는 존재를 확인하고; keys/values는 전체를 검색합니다. 집합 연산(union, intersect, setdiff, setxor, ismember)은 숫자 배열과 문자열 셀 배열에 작동합니다. ismember는 멤버십을 검사하고 논리 배열을 반환합니다 — 필터링에 좋습니다. 이들은 데이터 조작을 위한 논리 인덱싱을 보완합니다.

matlab
% map (dictionary / hash table)
m = containers.Map;
m('name') = 'Alice';
m('age') = 30;
m('scores') = [90 85];

% access
m('name')             % 'Alice'
isKey(m, 'name')      % true
keys(m)               % {'age', 'name', 'scores'}
values(m)             % {30, 'Alice', [90 85]}
remove(m, 'age');

% create with initial values
m2 = containers.Map({'a','b','c'}, {1, 2, 3});

% set operations
A = [1 2 3 4 5];
B = [4 5 6 7 8];
union(A, B)           % [1 2 3 4 5 6 7 8]
intersect(A, B)       % [4 5]
setdiff(A, B)         % [1 2 3]
setxor(A, B)          % [1 2 3 6 7 8]
ismember(3, A)        % true
ismember([1 6], A)    % [true false]

범주형과 날짜/시간

categorical 배열은 텍스트 데이터를 효율적으로 저장하고(레이블 맵이 있는 정수로) 순서를 지원합니다 — 설문 응답, 평점, 고정된 범주 집합에 이상적입니다. datetime/duration(R2014+)은 타임존을 인식하는 현대적 날짜 시스템으로 레거시 datenum/datestr 함수를 대체합니다. 날짜 연산이 직관적입니다: days(), hours(), minutes()를 더하세요. 이 타입들은 시계열 분석을 위해 테이블과 플로팅에 통합됩니다.

matlab
% categorical data (efficient for repeated strings)
colors = categorical({'red', 'blue', 'red', 'green', 'blue'});
categories(colors)    % list of categories
summary(colors)       % count per category
ord = categorical({'low','med','high'}, ...
     {'low','med','high'}, 'Ordinal', true);
ord(1) < ord(2)       % true (ordered)

% datetime
t = datetime('now')   % current date and time
t = datetime(2024, 1, 15)
t.Format = 'yyyy-MM-dd HH:mm:ss';

% duration
d = duration(2, 30, 0);  % 2 hours 30 min
d = hours(2) + minutes(30);

% date arithmetic
t2 = t + days(7);     % add a week
t2 - t                % duration of 7 days

% date strings and numbers
s = datestr(t, 'yyyy-mm-dd');  % to string (legacy)
n = datenum(t);                 % to serial number
t = datetime(n, 'ConvertFrom', 'datenum');

% generate date range
dates = datetime(2024,1,1) + days(0:6);  % one week
05

플로팅과 시각화

기본 2D 플롯

plot()은 핵심 2D 플로팅 함수입니다. 세 번째 인수는 색과 스타일을 지정합니다('b-' = 파란 실선). hold on은 여러 플롯을 겹치게 하고; hold off는 해제합니다. 항상 축에 레이블을 지정하고 범례를 추가하세요. axis([xmin xmax ymin ymax])는 한계를 설정합니다. saveas/print는 그림을 내보냅니다 — print에 -r300을 주면 300 DPI입니다. gcf는 현재 그림 핸들을 가져옵니다. 'Location','best' 옵션은 범례를 자동 배치합니다.

matlab
x = linspace(0, 2*pi, 100);

% line plot
plot(x, sin(x), 'b-', 'LineWidth', 2);
hold on;
plot(x, cos(x), 'r--', 'LineWidth', 2);
hold off;

% labels and legend
xlabel('x (radians)');
ylabel('amplitude');
title('Sine and Cosine');
legend('sin(x)', 'cos(x)', 'Location', 'best');
grid on;

% line styles: b- blue solid, r-- red dashed
% g: green dotted, m-. magenta dash-dot
% markers: o circle, * star, s square, + plus

% axis control
axis([0 2*pi -1.5 1.5]);  % [xmin xmax ymin ymax]
xlim([0 2*pi]);
ylim([-1.5 1.5]);

% save figure
saveas(gcf, 'plot.png');
print('-dpng', '-r300', 'plot.png');

다중 플롯과 서브플롯

subplot(r, c, n)은 그림을 r-by-c 격자로 나누고 n번째 셀을 플로팅에 선택합니다. tiledlayout(R2019+)은 현대적 대체품입니다 — 더 깔끔한 간격과 공유 제목. nexttile은 다음 서브플롯으로 이동합니다. yyaxis는 다른 스케일의 데이터에 대해 두 개의 y축(좌우) 플롯을 생성합니다. 항상 figure를 먼저 호출하여 새 창을 열거나, 현재 플롯을 덮어쓰게 됩니다.

matlab
% subplot(rows, cols, index)
figure;
subplot(2, 2, 1);
plot(x, sin(x));
title('Sine');

subplot(2, 2, 2);
plot(x, cos(x));
title('Cosine');

subplot(2, 2, 3);
plot(x, tan(x));
title('Tangent');
ylim([-5 5]);

subplot(2, 2, 4);
plot(x, exp(-x));
title('Decay');

% tiledlayout (newer, cleaner)
figure;
t = tiledlayout(2, 2);
nexttile; plot(x, sin(x)); title('Sine');
nexttile; plot(x, cos(x)); title('Cosine');
nexttile; plot(x, tan(x)); title('Tangent');
nexttile; plot(x, exp(-x)); title('Decay');
title(t, 'Trig Functions');  % overall title

% multiple y-axes
yyaxis left;  plot(x, sin(x));
yyaxis right; plot(x, 100*cos(x));

특수 플롯

MATLAB에는 수십 가지 특수 플롯이 있습니다: bar/barh(막대 차트), histogram(hist 대체), scatter(선택적 색/크기 매핑), pie, area, stem, stairs, compass, feather. scatter(x, y, size, color, 'filled')는 특히 강력합니다 — 4번째 인수가 점을 값으로 색칠해 세 번째 차원을 드러냅니다. histogram에 'Normalization','pdf'를 주면 연속 분포와 비교하기 위해 확률 밀도로 정규화합니다.

matlab
% bar chart
bar([1 2 3], [10 15 7]);
bar([1 2 3; 4 5 6], 'grouped');  % grouped bars
bar([1 2 3; 4 5 6], 'stacked');  % stacked bars

% histogram
data = randn(1000, 1);
histogram(data, 30);    % 30 bins
histogram(data, 'Normalization', 'pdf');

% scatter plot
x = rand(100, 1);
y = 2*x + randn(100, 1)*0.1;
scatter(x, y, 50, 'filled');
% colored scatter
scatter(x, y, 50, y, 'filled');  % color by y value
colorbar;

% pie chart
pie([30 20 50], {'A', 'B', 'C'});

% area plot
area(1:5, [1 3 2 4 5]);

% stem (discrete)
stem(0:5, [1 4 9 16 25 36]);

% boxplot (requires Statistics toolbox)
boxplot(randn(100, 3));

3D 플롯과 서피스

plot3은 3D 파라메트릭 선을 그립니다. 서피스의 경우 먼저 meshgrid로 격자를 만들고, Z = f(X, Y)를 계산합니다. surf는 채워진 서피스를, mesh는 와이어프레임을, contour는 2D 등고선을 그립니다. colormap(jet, parula, hot, cool)이 색 매핑을 제어하고; colorbar가 범례를 추가합니다. shading interp는 부드러운 그라데이션을 위해 격자선을 제거합니다. view(az, el)는 카메라 각도를 설정합니다. 'EdgeColor','none'은 깔끔한 모양을 위해 메시선을 숨깁니다.

matlab
% 3D line plot
t = 0:0.1:10*pi;
plot3(sin(t), cos(t), t);
xlabel('x'); ylabel('y'); zlabel('z');

% meshgrid for surface plots
[X, Y] = meshgrid(-2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);

% surface plots
figure;
subplot(1, 3, 1);
surf(X, Y, Z);     % surface
title('surf');

subplot(1, 3, 2);
mesh(X, Y, Z);     % wireframe
title('mesh');

subplot(1, 3, 3);
contour(X, Y, Z, 20);  % contour lines
title('contour');

% colored surface with colorbar
figure;
surf(X, Y, Z, 'EdgeColor', 'none');
colorbar;
colormap jet;
shading interp;     % smooth colors

% view angle
view(45, 30);       % azimuth, elevation
axis equal;

플롯 사용자 정의와 내보내기

거의 모든 시각적 측면이 이름-값 쌍이나 set()으로 사용자 정의 가능합니다. 색은 0-1 범위의 RGB 트리플 [r g b]입니다. set(gca, ...)는 현재 축을 수정합니다(폰트, 스케일, 한계). MATLAB은 'Interpreter','latex'으로 제목/레이블에서 LaTeX를 지원합니다. exportgraphics(R2020+)는 벡터와 고해상도 DPI 옵션이 있는 현대적 내보내기 함수입니다. 여러 창을 관리하려면 그림 핸들(f1, f2)을 사용하세요. annotation()은 화살표, 텍스트 상자, 도형을 추가합니다.

matlab
% customize line appearance
plot(x, y, ...
    'Color', [0.2 0.6 0.8], ...     % RGB 0-1
    'LineWidth', 2, ...
    'Marker', 'o', ...
    'MarkerSize', 8, ...
    'MarkerFaceColor', 'r');

% annotations
text(1, 0.5, 'important point');
annotation('arrow', [0.3 0.5], [0.3 0.5]);

% figure and axes properties
set(gcf, 'Position', [100 100 800 600]);
set(gca, 'FontSize', 14, 'FontName', 'Arial');
set(gca, 'XScale', 'log');  % log scale

% latex in labels
title('Function: \\alpha + \\beta^2', 'Interpreter', 'latex');

% export high quality
exportgraphics(gcf, 'plot.pdf', 'ContentType', 'vector');
exportgraphics(gcf, 'plot.png', 'Resolution', 300);

% legend customization
legend('show', 'Location', 'northwest', ...
       'FontSize', 12, 'Box', 'off');

% multiple figures
f1 = figure; plot(x, sin(x));
f2 = figure; plot(x, cos(x));
figure(f1);  % switch back to f1
06

데이터 분석과 통계

기술 통계

MATLAB은 포괄적인 통계 함수를 제공합니다. 중심 경향에는 mean/median/mode; 퍼짐에는 std/var/range/iqr. 기본적으로 이들은 첫 번째 차원(열)을 따라 동작합니다. NaN 값을 건너뛰려면 'omitnan'을 사용하세요(실제 데이터에 중요). quantile/prctile은 백분위수를 제공합니다. Statistics and Machine Learning Toolbox가 geomean, harmmean, zscore, 분포 함수를 추가합니다. 분석 전에 항상 NaN을 확인하세요 — 대부분의 연산에서 전파됩니다.

matlab
data = [1 2 3 4 5 6 7 8 9 10];

% central tendency
mean(data)            % 5.5
median(data)          % 5.5
mode(data)            % 1 (first mode)
geomean(data)         % geometric mean (Stats toolbox)
harmmean(data)        % harmonic mean

% dispersion
std(data)             % standard deviation
var(data)             % variance
range(data)           % max - min
iqr(data)             % interquartile range
mad(data)             % mean absolute deviation

% extremes and quantiles
min(data); max(data);
quantile(data, 0.25)  % 25th percentile
prctile(data, 95)     % 95th percentile

% along dimensions
A = randn(100, 3);
mean(A)               % mean of each column
mean(A, 2)            % mean of each row
mean(A, 'all')        % overall mean

% ignoring NaNs
data(5) = NaN;
mean(data, 'omitnan') % skip NaN values
nanmean(data)         % legacy equivalent

곡선 피팅과 회귀

polyfit은 주어진 차수의 다항식을 피팅하고; polyval로 평가합니다. 선형 회귀의 경우 regress()가 계수와 통계량(R², F-통계량, p-값)을 제공합니다. corrcoef는 전체 상관 행렬을 반환합니다. Curve Fitting Toolbox는 사용자 정의 모델로 fit()을 제공합니다. lsqcurvefit(Optimization Toolbox)은 임의의 비선형 모델을 피팅합니다. 항상 데이터와 피팅을 플롯하여 품질을 확인하세요 — 고차 다항식은 과적합될 수 있습니다.

matlab
% polynomial fit
x = 0:0.5:10;
y = 2*x + 1 + randn(size(x))*2;  % noisy linear data

% linear least squares (degree 1)
p = polyfit(x, y, 1);   % [slope, intercept]
yfit = polyval(p, x);
plot(x, y, 'o', x, yfit, '-');

% higher-order polynomial
p3 = polyfit(x, y, 3);
yfit3 = polyval(p3, x);

% fit with fittype (Curve Fitting Toolbox)
f = fit(x', y', 'poly2');  % quadratic
plot(f, x, y);

% custom model fit
% fit y = a*exp(b*x) using lsqcurvefit
model = @(p, x) p(1)*exp(p(2)*x);
params = lsqcurvefit(model, [1 0.1], x, y);

% correlation
r = corrcoef(x, y);     % correlation matrix
r = corr(x, y);         % correlation coefficient

% linear regression with stats
X = [ones(size(x)) x'];  % design matrix
[b, bint, r, rint, stats] = regress(y', X);
% stats = [R^2, F, p, error_var]

보간과 리샘플링

interp1은 1D 데이터를 보간합니다 — 'linear'는 빠르고, 'spline'은 부드럽지만(오버슈트 가능), 'pchip'은 형태를 보존합니다(오버슈트 없음). interp2는 2D 격자에 같은 작업을 합니다. 반복 쿼리의 경우 griddedInterpolant가 더 효율적입니다(한 번 구축, 여러 번 쿼리). resample은 신호의 샘플링 속도를 변경합니다(Signal Processing Toolbox 필요). 데이터에 따라 방법을 선택하세요: 부드러운 함수에는 spline, 단조 데이터에는 pchip, 범주형에는 nearest.

matlab
% 1D interpolation
x = 0:5;
y = [0 1 4 9 16 25];
xi = 0:0.5:5;

yi = interp1(x, y, xi, 'linear');   % linear (default)
yi = interp1(x, y, xi, 'spline');   % cubic spline
yi = interp1(x, y, xi, 'pchip');    % shape-preserving
yi = interp1(x, y, xi, 'nearest');  % nearest neighbor

% extrapolation
yi = interp1(x, y, xi, 'linear', 'extrap');

% 2D interpolation
[X, Y] = meshgrid(0:2:10);
Z = X.^2 + Y.^2;
[Xi, Yi] = meshgrid(0:0.5:10);
Zi = interp2(X, Y, Z, Xi, Yi, 'spline');

% resample signal to new rate
y_resampled = resample(y, 3, 2);  % 3/2 times the rate

% griddedInterpolant (efficient for repeated queries)
F = griddedInterpolant(x, y, 'spline');
y1 = F(2.5);
y2 = F([1.5 3.5 4.5]);

FFT와 신호 처리

fft는 고속 푸리에 변환을 계산합니다 — 주파수 분석의 기초. 출력은 복소수이고; 크기는 abs()로 구합니다. 전반부를 취해 두 배로(DC와 나이퀴스트 제외) 만들어 단면 스펙트럼으로 변환합니다. 주파수는 0에서 fs/2(나이퀴스트)까지입니다. ifft는 시간 영역으로 역변환합니다. 주파수 영역에서 필터링(원치 않는 주파수를 0으로)은 간단하지만 링잉을 유발할 수 있습니다; 적절한 필터에는 designfilt를 사용하세요. spectrogram은 시간에 따른 주파수 내용을 보여줍니다.

matlab
% generate a signal with two frequencies
fs = 1000;                    % sampling rate (Hz)
t = 0:1/fs:1-1/fs;            % 1 second of time
x = 2*sin(2*pi*50*t) + 1*sin(2*pi*120*t);

% compute FFT
N = length(x);
Y = fft(x);
P2 = abs(Y/N);                % two-sided spectrum
P1 = P2(1:N/2+1);             % one-sided spectrum
P1(2:end-1) = 2*P1(2:end-1);
f = fs*(0:(N/2))/N;

% plot
plot(f, P1);
xlabel('Frequency (Hz)');
ylabel('Amplitude');
title('Single-Sided Spectrum');

% filtering (simple low-pass)
cutoff = 100;  % Hz
Y_filt = Y;
Y_filt(f > cutoff) = 0;       % zero out high freqs (simplified)
x_filtered = real(ifft(Y_filt));

% spectrogram
spectrogram(x, 128, 120, 128, fs, 'yaxis');

최적화와 근 찾기

fzero는 1D 함수의 근을 찾습니다(구간이나 추측값 필요). fminbnd는 구간에서 1D 함수를 최소화하고; fminsearch는 비제약 다변수 최적화에 Nelder-Mead를 사용합니다. fmincon(Optimization Toolbox)은 제약을 처리합니다. linprog는 선형 계획을 풉니다. 반복 솔버에는 항상 좋은 초기 추측(x0)을 제공하세요. 수렴을 확인하려면 exitflag 출력을 확인하세요. 전역 최적화에는 GlobalSearch나 MultiStart를 사용하세요.

matlab
% find root of f(x) = 0
f = @(x) x^2 - 2;
x_root = fzero(f, 1);         % ~1.4142 (sqrt(2))
x_root = fsolve(f, 1);        % alternative

% minimize a function
fun = @(x) (x-3)^2 + 1;
[x_min, f_min] = fminbnd(fun, 0, 5);  % bounded 1D
% x_min = 3, f_min = 1

% multivariate minimization
fun2 = @(x) x(1)^2 + x(2)^2;  % sphere function
x0 = [1, 1];
[x_opt, f_opt] = fminsearch(fun2, x0);
% x_opt ≈ [0, 0]

% constrained optimization (Optimization Toolbox)
% minimize fun subject to A*x <= b
A = []; b = []; Aeq = []; beq = [];
lb = [0 0]; ub = [];
[x, fval] = fmincon(fun2, x0, A, b, Aeq, beq, lb, ub);

% linear programming
% minimize f'*x subject to A*x <= b
f = [-1; -1];                 % maximize x+y
A = [1 1; -1 0; 0 -1];
b = [2; 0; 0];
[x, fval] = linprog(f, A, b);
07

파일 입출력과 데이터 가져오기

MAT 파일과 저장/불러오기

.mat은 MATLAB의 네이티브 바이너리 형식입니다 — 빠르고, 작고, 모든 변수 타입을 보존합니다. save/load가 기본 명령입니다. 2GB 이상 파일에는 -v7.3을 사용하세요(HDF5 기반). -ascii는 사람이 읽을 수 있는 텍스트로 내보냅니다(타입 정보 손실). 구조체로 불러오면(s = load(...)) 작업 공간 오염을 피합니다. clear는 변수를 제거하고; clearvars -except는 지정한 것을 유지합니다. 긴 계산에서 재개를 가능하게 하려면 항상 중간 결과를 저장하세요.

matlab
% save variables to a .mat file
x = 1:10;
y = sin(x);
save('data.mat');             % save ALL variables
save('data.mat', 'x', 'y');   % save specific variables
save('data.mat', '-append');  % add more variables

% load variables
load('data.mat');             % load all into workspace
loaded = load('data.mat');    % load into a struct
loaded.x                      % access via struct

% save with compression
save('data.mat', 'x', 'y', '-v7.3');  % large files (>2GB)
save('data.mat', '-v7');              % compressed (default)

% save specific format
save('data.txt', 'x', '-ascii');      % plain text
save('data.csv', 'x', '-ascii', '-double');

% clear variables
clear x y;                    % remove specific
clear all;                    % remove everything
clearvars -except x;          % keep only x

텍스트와 CSV 파일 읽기

readtable은 CSV/Excel을 읽는 현대적 방법입니다 — 이름이 있는 열의 테이블을 반환하고 헤더를 자동 처리합니다. readmatrix는 숫자 데이터를 행렬로 읽습니다. 완전한 제어를 원하면 fopen/fgetl/fprintf/fclose를 사용하세요(항상 파일 닫기!). fscanf는 C처럼 포맷된 데이터를 읽습니다. 항상 fid 오류를 확인하세요: fid == -1이면 파일을 열 수 없습니다. readcell은 행렬이나 테이블에 맞지 않는 혼합 타입 데이터를 처리합니다.

matlab
% readtable (recommended for tabular data)
T = readtable('data.csv');
T = readtable('data.xlsx', 'Sheet', 'Sheet1');
T = readtable('data.csv', 'Delimiter', ',');

% access columns by name
T.Var1; T.age;

% readmatrix (numeric data)
M = readmatrix('numbers.csv');
M = readmatrix('data.txt', 'Delimiter', '\t');

% readcell (mixed data)
C = readcell('mixed.csv');

% low-level file I/O
fid = fopen('data.txt', 'r');
while ~feof(fid)
    line = fgetl(fid);
    disp(line);
end
fclose(fid);

% read formatted data
fid = fopen('data.txt', 'r');
data = fscanf(fid, '%f %f', [2, inf]);
fclose(fid);

% write text
fid = fopen('output.txt', 'w');
fprintf(fid, 'Result: %.2f\n', 3.14159);
fclose(fid);

Excel과 스프레드시트 입출력

readtable/writetable이 Excel 입출력에 권장되는 함수입니다. 헤더, 타입, 시트를 자동으로 처리합니다. detectImportOptions로 열 파싱 방식을 사용자 정의할 수 있습니다(예: 열을 int32나 문자열로 강제). 'Range'로 특정 셀을 읽거나 씁니다. 'WriteMode','append'는 기존 시트에 행을 추가합니다. 큰 Excel 파일에는 CSV(빠름)나 .mat(네이티브)을 고려하세요. Spreadsheet Link 툴박스는 MATLAB을 Excel에 직접 연결합니다.

matlab
% read Excel files
T = readtable('data.xlsx');
T = readtable('data.xlsx', 'Sheet', 'Sales', 'Range', 'A1:D100');

% numeric data only
M = readmatrix('data.xlsx', 'Sheet', 1);

% write to Excel
writetable(T, 'output.xlsx');
writetable(T, 'output.xlsx', 'Sheet', 'Results');

% write matrix
writematrix(M, 'output.xlsx', 'Sheet', 1);

% cell array (mixed types)
C = {'Name','Age'; 'Alice',30; 'Bob',25};
writecell(C, 'people.xlsx');

% append to existing sheet
writetable(T, 'data.xlsx', 'Sheet', 1, 'WriteMode', 'append');

% read specific range
T = readtable('data.xlsx', 'Range', 'B2:D10');

% detect import options (customize parsing)
opts = detectImportOptions('data.csv');
opts = setvartype(opts, 'age', 'int32');
T = readtable('data.csv', opts);

경로와 디렉터리 작업

dir()은 각 파일에 대해 .name, .date, .bytes, .isdir, .datenum을 가진 구조체 배열을 반환합니다. fullfile은 이식 가능하게 경로를 결합합니다(각 OS에서 올바른 구분자 사용). fileparts는 경로를 디렉터리, 이름, 확장자로 분할합니다. exist('name', 'file')은 파일 존재를 확인합니다. addpath는 디렉터리를 MATLAB 검색 경로에 추가해 함수에 접근 가능하게 하고; savepath로 영속화합니다. 폴더의 파일을 일괄 처리하는 데 필수적입니다.

matlab
% current directory
pwd
cd('C:\\Users\\data')

% list files
files = dir();              % struct array of files
files = dir('*.mat');       % filter by pattern
files = dir('subdir/');     % list a subdirectory

% access file info
for i = 1:length(files)
    if ~files(i).isdir
        fprintf('%s - %d bytes\n', files(i).name, files(i).bytes);
    end
end

% path operations
fullfile('data', '2024', 'file.csv')  % data/2024/file.csv
[filepath, name, ext] = fileparts('C:\\data\\test.csv')
% filepath = 'C:\data', name = 'test', ext = '.csv'

% create and remove directories
mkdir('output');
rmdir('output', 's');      % remove recursively

% file existence
if exist('data.mat', 'file')
    load('data.mat');
end

% add folder to path
addpath('C:\\myfunctions');
savepath();                 % save for future sessions

이미지와 오디오

imread/imshow/imwrite는 이미지를 처리합니다(JPEG, PNG, TIFF, BMP). 이미지는 uint8 행렬(0-255)이나 double(0-1)로 저장됩니다. rgb2gray는 컬러를 회색조로 변환합니다. Image Processing Toolbox는 imresize, imrotate, imfilter, 에지 검출, 형태학적 연산을 추가합니다. audioread/audiowrite/sound는 오디오 파일을 처리합니다. 이미지와 오디오는 단순히 행렬이므로 모든 MATLAB 수학과 플로팅 도구가 직접 적용됩니다.

matlab
% read and display an image
img = imread('photo.jpg');
imshow(img);
[m, n, c] = size(img);     % dimensions, c=3 for RGB

% write image
imwrite(img, 'output.png');
imwrite(img, 'output.jpg', 'Quality', 90);

% convert to grayscale
if size(img, 3) == 3
    gray = rgb2gray(img);
    imshow(gray);
end

% image processing
img2 = imresize(img, 0.5);          % scale 50%
img3 = imrotate(img, 45);           % rotate 45 degrees
img4 = imadjust(img, [0.2 0.8], []); % contrast adjust

% audio
[y, fs] = audioread('song.wav');    % y = samples, fs = sample rate
sound(y, fs);                        % play audio
audiowrite('output.wav', y, fs);

% record audio
recObj = audiorecorder(44100, 16, 1);
recordblocking(recObj, 3);           % record 3 seconds
y = getaudiodata(recObj);
08

심볼릭 수학과 고급

심볼릭 변수와 단순화

Symbolic Math Toolbox는 (수치가 아닌) 정확한 계산을 가능하게 합니다. syms로 심볼릭 변수를 선언합니다. simplify, expand, factor, collect가 대수 표현을 조작합니다. subs는 값이나 변수를 치환합니다. vpa(가변 정밀도 산술)는 임의 정밀도로 계산합니다 — 부동소수점 반올림이 중요할 때 유용합니다. 심볼릭 결과는 정확합니다(예: sqrt(2)가 1.4142...가 아닌 sqrt(2)로 유지). 필요할 때 double()로 수치로 변환하세요.

matlab
% create symbolic variables (Symbolic Math Toolbox)
syms x y z

% symbolic expressions
f = x^2 + 2*x + 1;
g = sin(x)^2 + cos(x)^2;

% simplify
simplify(f)             % (x + 1)^2
simplify(g)             % 1
expand((x+1)^3)         % x^3 + 3*x^2 + 3*x + 1
factor(x^2 - 1)         % (x - 1)*(x + 1)
collect(x^2 + 2*x + x^2)% 2*x^2 + 2*x

% substitute values
subs(f, x, 3)           % 16 (f at x=3)
subs(f, x, y)           % y^2 + 2*y + 1

% pretty print
pretty(f)
disp(f)

% convert between numeric and symbolic
double(sym('1/3'))      % 0.3333
sym(0.5)                % 1/2
vpa(pi, 50)             % 50-digit pi: 3.1415926535897...

미적분: 미분과 적분

diff는 미분합니다(고차 도함수를 위해 두 번째 인수 전달). int는 적분합니다 — 한계 없이는 부정적분을 반환하고; 한계 있이는 정적분을 계산합니다. limit는 극한을 계산합니다('left'/'right'로 한쪽 극한 포함). taylor는 함수를 점 주변의 테일러 급수로 전개합니다. 이들은 심볼릭 표현을 반환합니다; 수치 결과에는 double()이나 vpa()를 사용하세요. 심볼릭 미적분은 정확하고 수치적 반올림을 피합니다.

matlab
syms x

% differentiation
f = x^3 + 2*x^2 + x;
df = diff(f)            % 3*x^2 + 4*x + 1
d2f = diff(f, 2)        % second derivative: 6*x + 4
diff(f, x, 3)           % third derivative: 6

% partial derivatives
syms x y
g = x^2 * y + sin(x*y);
diff(g, x)              % 2*x*y + y*cos(x*y)
diff(g, y)              % x^2 + x*cos(x*y)

% integration
int(x^2)                % x^3/3 (indefinite)
int(x^2, x, 0, 1)       % 1/3 (definite, 0 to 1)
int(sin(x), x, 0, pi)   % 2

% limits
limit(sin(x)/x, x, 0)   % 1
limit(1/x, x, inf)      % 0
limit(1/x, x, 0, 'left')  % -inf

% Taylor series
taylor(exp(x), x, 0, 'Order', 6)
% 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120

방정식 풀기

solve는 대수 방정식과 시스템의 정확한(심볼릭) 해를 찾습니다. 닫힌 형식 해가 없는 방정식에는 vpasolve(수치)를 사용하세요. dsolve는 상미분 방정식을 심볼릭으로 풉니다 — 특정 해를 위해 초기/경계 조건을 제공하세요. 결과는 심볼릭입니다; 플로팅을 위해 double/vpa로 변환하세요. 심볼릭으로 풀 수 없는 복잡한 ODE에는 ode45(수치 솔버)를 대신 사용하세요. solve가 빈 것을 반환했는지(해 없음) 항상 확인하세요.

matlab
syms x y

% solve algebraic equations
solve(x^2 - 4 == 0, x)        % [2; -2]
solve(x^2 + 1 == 0, x)        % [i; -i] (complex roots)

% solve a system
sol = solve([x + y == 5, x - y == 1], [x, y]);
sol.x                        % 3
sol.y                        % 2

% solve with parameters
syms a b c
r = solve(a*x^2 + b*x + c == 0, x);
% r = -(b + (b^2 - 4*a*c)^(1/2))/(2*a), ...

% numerical solve (no closed form)
vpasolve(x^5 - 3*x + 1 == 0, x)

% differential equations
syms y(t) t
ode = diff(y, t) == -k*y;     % dy/dt = -k*y
cond = y(0) == y0;
ySol(t) = dsolve(ode, cond);  % y0*exp(-k*t)

% system of ODEs
syms x(t) y(t)
eq1 = diff(x,t) == y;
eq2 = diff(y,t) == -x;
sol = dsolve([eq1, eq2]);

라플라스와 푸리에 변환

laplace/ilaplace는 라플라스 변환 쌍을 계산합니다 — 선형 ODE 풀기와 제어 시스템 분석에 필수적입니다. fourier/ifourier는 푸리에 변환(연속 주파수)에 같은 작업을 합니다. ztrans/iztrans는 이산 신호(디지털 필터)를 처리합니다. 라플라스로 ODE 푸는 작업 흐름: ODE를 대수로 변환, Y(s)에 대해 풀기, 역변환. 이들은 정확한 심볼릭 연산입니다; 수치 변환에는 fft를 사용하세요.

matlab
syms t s w

% Laplace transform
f = exp(-a*t);
F = laplace(f)          % 1/(a + s)
% default: f(t) -> F(s)

% inverse Laplace
f2 = ilaplace(1/(s+1))  % exp(-t)

% Fourier transform
g = exp(-t^2);
G = fourier(g)          % pi^(1/2)*exp(-w^2/4)

% inverse Fourier
g2 = ifourier(G)

% Z-transform (for discrete signals)
syms n z
h = a^n;
H = ztrans(h)           % -z/(a - z) (for |z| > |a|)
h2 = iztrans(z/(z-a))   % a^n

% apply transform to solve ODE
% y'' + y = 0, y(0)=0, y'(0)=1
syms y(t) Y(s)
ode = diff(y, t, 2) + y == 0;
% take Laplace of both sides, solve for Y(s), then invert

수치 ODE 솔버

ode45는 기본 ODE 솔버입니다 — 정확하고 적응적인 Runge-Kutta(4,5) 방법. 시스템의 경우 상태는 벡터 v이고 함수는 도함수의 열 벡터를 반환합니다. ode15s는 stiff 문제(역학이 매우 다른 시간 스케일에서 동작)에 사용합니다. odeset이 허용 오차와 이벤트를 구성합니다. 파라미터를 전달하려면 캡처하는 익명 함수를 사용하세요. 해가 합리적으로 보이는지 확인하려면 항상 플롯하세요. 경계값 문제에는 bvp4c를 사용하세요.

matlab
% solve dy/dt = f(t, y) numerically with ode45

% define the ODE as a function
f = @(t, y) -2*y;       % dy/dt = -2y (exponential decay)

% solve on [0, 5] with y(0) = 1
[t, y] = ode45(f, [0 5], 1);
plot(t, y);
xlabel('t'); ylabel('y');

% system of ODEs (Lotka-Volterra predator-prey)
% dx/dt = 1.5x - xy,  dy/dt = -0.7y + 0.1xy
ode_sys = @(t, v) [1.5*v(1) - v(1)*v(2);
                   -0.7*v(2) + 0.1*v(1)*v(2)];
[t, V] = ode45(ode_sys, [0 20], [10; 5]);
plot(t, V(:,1), 'b', t, V(:,2), 'r');
legend('Prey', 'Predator');

% stiff ODE solver (for fast dynamics)
[t, y] = ode15s(f, [0 5], 1);

% set options
opts = odeset('RelTol', 1e-6, 'AbsTol', 1e-9);
[t, y] = ode45(f, [0 5], 1, opts);

% pass parameters via anonymous function
a = 0.5;
f = @(t, y, a) -a*y;
[t, y] = ode45(@(t,y) f(t,y,a), [0 10], 1);
09

행렬 연산 심층

선형 방정식과 분해

백슬래시 연산자(\)는 MATLAB이 선호하는 선형 솔버입니다 — 행렬에 따라 LU, QR, Cholesky를 자동 선택합니다. 역행렬이 실제로 필요하지 않은 한 inv(A)*b를 사용하지 마세요; 더 느리고 수치적으로 덜 안정적입니다. lu, qr, chol이 표준 행렬 분해를 반환합니다. eig는 고윳값/고유벡터를 계산하고, svd는 특이값 분해를 제공합니다 — PCA, 의사 역행렬, 저랭크 근사의 기초.

matlab
% solve Ax = b
A = [3 2 -1; 2 -2 4; -1 0.5 -1];
b = [1; -2; 0];
x = A \ b;             % backslash: preferred solver
x = inv(A) * b;         % explicit inverse (slower, less stable)
x = linsolve(A, b);     % optimized linear solver

% LU, QR, Cholesky decompositions
[L, U, P] = lu(A);      % PA = LU
[Q, R] = qr(A);         % QR factorization
R = chol(A'*A);         % Cholesky (needs SPD matrix)

% eigenvalues and eigenvectors
[V, D] = eig(A);        % A*V = V*D
eigenvalues = diag(D);

% singular value decomposition
[U, S, V] = svd(A);     % A = U*S*V'

희소 행렬

희소 행렬은 0이 아닌 항목만 저장합니다 — 주로 0인 100k+ 차원 행렬(유한 요소법, 그래프 알고리즘, PDE에서 흔함)을 다룰 때 필수적입니다. sparse(i,j,v)로 삼중항 형식에서 구축하고; full로 되돌립니다. 희소 행렬 간의 연산은 희소성을 유지합니다. nnz는 0이 아닌 것을 세고 spy는 희소 패턴을 플롯합니다. 희소 선형 해(S\b)는 UMFPACK 같은 특수 솔버를 자동으로 사용합니다.

matlab
% create sparse matrix (memory efficient for large, mostly-zero)
S = sparse(10000, 10000);
S(1, 1) = 5;
S(2, 3) = 10;

% from triplets (row, col, value)
i = [1 2 2 3];
j = [1 1 3 3];
v = [4 5 7 9];
S = sparse(i, j, v, 3, 3);

% convert sparse <-> full
F = full(S);
S2 = sparse(F);

% sparse identity and diagonal
I = speye(1000);
D = spdiags(ones(1000,1), 0, 1000, 1000);

% operations preserve sparsity
nnz(S)                  % number of nonzeros
spy(S)                  % visualize sparsity pattern

행렬 함수와 재구성

reshape는 요소를 열 우선(열을 먼저 아래로)으로 재배열합니다 — 행 우선 언어에서 포팅할 때 흔한 버그 원인입니다. flipud/fliplr/rot90는 비표준 방식으로 뒤집거나 전치하는 데 편리합니다. repmat은 행렬을 반복 배치하고; repelem은 개별 요소를 복제합니다. 결합은 [A; B](수직)와 [A B](수평)를 사용하거나, 프로그래밍 방식으로는 horzcat/vertcat을 사용합니다. arrayfun은 벡터화가 불가능할 때 요소별로 함수를 적용합니다.

matlab
A = [1 2 3; 4 5 6];

% reshape (column-major order!)
B = reshape(A, 3, 2);   % [1 5; 4 3; 2 6]
C = reshape(A, 6, 1);   % column vector

% flip and rotate
flipud(A)               % flip up-down
fliplr(A)               % flip left-right
rot90(A)                % rotate 90 degrees
rot90(A, 2)             % rotate 180 degrees

% repmat and repelem
repmat([1 2], 2, 3)     % tile 2x3
repelem([1 2 3], 2)     % [1 1 2 2 3 3]

% concatenation
[A; A]                  % vertical (must have same # cols)
[A A]                   % horizontal (must have same # rows)
horzcat(A, A); vertcat(A, A);

% matrix functions (apply element-wise via fun)
arrayfun(@(x) x^2, A)

브로드캐스팅과 벡터화

R2016b부터 MATLAB은 자동으로 크기 1인 차원을 브로드캐스트(확장)하여 다른 피연산자와 일치시킵니다 — bsxfun이나 repmat이 필요 없습니다. 벡터화(요소별 루프 대신 전체 배열에 연산)는 MATLAB에서 가장 큰 성능 향상입니다. 왜냐하면 기본 BLAS/LAPACK 루틴이 고도로 최적화되어 있기 때문입니다. 루프에서 채우기 전에 항상 배열을 미리 할당하세요; 동적으로 배열을 키우면 매 반복마다 재할당이 발생하고 O(n^2)입니다.

matlab
% MATLAB implicitly expands (broadcasts) since R2016b
A = [1 2 3; 4 5 6];     % 2x3
b = [10 20 30];         % 1x3
C = A + b;              % 2x3: b added to each row

c = [1; 2];             % 2x1
D = A + c;              % 2x3: c added to each column

% vectorized operations (much faster than loops)
x = linspace(0, 2*pi, 1e6);
y = sin(x) .* cos(x);   % element-wise, no loop needed

% avoid growing arrays in loops
% BAD: for k=1:1e6, s(k) = k; end
% GOOD: preallocate
s = zeros(1, 1e6);
for k = 1:1e6
    s(k) = k;
end

% even better: vectorize
s = 1:1e6;

% bsxfun (legacy, before auto-broadcasting)
E = bsxfun(@plus, A, b);

수치 선형 대수 응용

백슬래시 연산자는 A가 직사각(열보다 행이 많은)일 때 최소제곱 문제를 자동으로 풉니다. polyfit/polyval이 다항식을 피팅하고 평가합니다. PCA는 중심화된 데이터 행렬의 SVD로 가장 안정적으로 계산됩니다 — V의 열이 주성분 방향이고 diag(S)가 표준편차를 줍니다. cond(A)는 수치적 민감도를 측정합니다; 1e12 이상의 값은 배정밀도 산술에서 행렬이 본질적으로 특이함을 의미합니다.

matlab
% least-squares fit (overdetermined system)
A = [1 1; 1 2; 1 3; 1 4];
b = [6; 5; 7; 10];
x = A \ b;             % least-squares solution

% polynomial curve fitting
t = 0:0.1:5;
y = 2*t.^2 + 1 + 0.5*randn(size(t));
p = polyfit(t, y, 2);   % degree-2 fit
yfit = polyval(p, t);

% PCA via SVD
X = randn(100, 5);
Xc = X - mean(X);       % center
[U, S, V] = svd(Xc, 0);
scores = Xc * V;        % principal components
variances = diag(S).^2 / (size(X,1)-1);

% condition number (numerical stability)
cond(A)                 % large = ill-conditioned
10

2D와 3D 플로팅 심층

선 플롯과 사용자 정의

plot은 핵심 2D 플로팅 함수입니다. 'r--'(빨간 점선) 같은 선 사양 문자열은 색, 마커, 스타일을 결합합니다. hold on으로 여러 플롯을 겹칠 수 있습니다. subplot(m,n,k)는 m-by-n 격자를 만들고 k번째 셀(행 우선)을 선택합니다. set(gca, ...)가 현재 축을 수정하고; gcf는 현재 그림입니다. print에 -dpng와 -r300을 주면 300 DPI PNG를 내보냅니다 — saveas보다 훨씬 높은 품질입니다.

matlab
x = linspace(0, 2*pi, 200);
y1 = sin(x); y2 = cos(x);

figure;
plot(x, y1, 'b-', 'LineWidth', 2); hold on;
plot(x, y2, 'r--', 'LineWidth', 1.5);
hold off;

% annotations
xlabel('Angle (rad)');
ylabel('Amplitude');
title('Sine and Cosine');
legend('sin(x)', 'cos(x)', 'Location', 'best');
grid on;

% axis control
axis([0 2*pi -1.2 1.2]);
set(gca, 'FontSize', 12, 'FontName', 'Arial');

% multiple subplots
subplot(2, 1, 1); plot(x, y1);
subplot(2, 1, 2); plot(x, y2);

% save figure
saveas(gcf, 'plot.png');
print('-dpng', '-r300', 'plot_hi.png');

3D 서피스, 메시, 등고선 플롯

meshgrid는 서피스 플롯에 필요한 X, Y 좌표 격자를 생성합니다. surf는 채워진 서피스를, mesh는 와이어프레임을, contour는 2D 등고선으로 투영합니다. colormap이 색 매핑을 변경하고(jet, parula, hot, cool, gray); parula가 현대적 기본값입니다. shading interp는 색 전환을 부드럽게 합니다. plot3는 3D 파라메트릭 곡선을 그립니다. view(az, el)는 카메라 각도를 설정하고; axis equal은 왜곡을 방지합니다.

matlab
[X, Y] = meshgrid(-2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);

figure;
subplot(2,2,1); surf(X, Y, Z);    title('surf');
subplot(2,2,2); mesh(X, Y, Z);    title('mesh');
subplot(2,2,3); contour(X, Y, Z, 20); title('contour');
subplot(2,2,4); surfc(X, Y, Z);   title('surfc');

% color mapping
colormap(jet(256)); colorbar;
shading interp;        % smooth colors

% 3D line plot (parametric)
t = 0:0.01:10;
plot3(sin(t), cos(t), t, 'LineWidth', 2);
xlabel('x'); ylabel('y'); zlabel('z');

% view angle
view(45, 30);          % azimuth, elevation
axis equal;

통계와 특수 플롯

histogram(R2014b+)은 hist를 대체하며 PDF를 위한 'Normalization' 같은 기능이 더 있습니다. boxplot은 그룹 간 분포를 비교합니다. scatterhist는 산점도에 한계 히스토그램을 보여줍니다 — 상관관계 시각화에 좋습니다. bar는 그룹화 및 누적 레이아웃을 지원합니다. errorbar는 불확실성 시각화를 추가합니다. 이 특수 플롯은 과학적 데이터 표현과 탐색적 분석에 필수적입니다.

matlab
data = randn(1000, 1);

% histogram (modern)
histogram(data, 30, 'Normalization', 'pdf');
hold on; x = -4:0.1:4; plot(x, normpdf(x), 'r-', 'LineWidth', 2);

% box plot by group
g = randi([1 3], 100, 1);
boxplot(data, g);

% scatter with marginal histograms
x = randn(200,1); y = x + 0.5*randn(200,1);
scatterhist(x, y);

% bar chart
sales = [10 25 30; 20 15 40];
bar(sales); legend('Q1','Q2','Q3');

% pie chart
pie([30 20 50], {'A','B','C'});

% error bars
y = [1 2 3 4]; e = [0.1 0.2 0.15 0.3];
errorbar(y, e, 'o-');

애니메이션과 대화형 그래픽

애니메이션은 루프 내에서 플롯 데이터를 업데이트하고 drawnow를 호출해 새로고침합니다. 부드러운 성능을 위해 플롯을 한 번 만들고 다시 플로팅하는 대신 XData/YData를 업데이트하세요. getframe은 현재 그림을 캡처하고; movie는 시퀀스를 재생합니다. VideoWriter는 MP4나 AVI로 내보냅니다 — 결과 공유에 유용합니다. 자동 재스케일링 지터를 방지하려면 루프 외부에서 항상 축 한계를 설정하세요.

matlab
% animated line plot
figure;
h = plot(NaN, NaN);
axis([0 10 -1 1]); xlabel('t'); ylabel('y');
for t = 0:0.1:10
    set(h, 'XData', [get(h,'XData') t], ...
           'YData', [get(h,'YData') sin(t)]);
    drawnow;
end

% getframe to capture animation
frames = [];
for k = 1:50
    plot(sin(linspace(0, k*pi/10, 200)));
    axis([0 200 -1 1]);
    frames = [frames, getframe];
end
movie(frames, 1, 30);   % play once at 30 fps

% write to video file
v = VideoWriter('anim.mp4', 'MPEG-4');
v.FrameRate = 30; open(v);
for k = 1:50
    plot(sin(linspace(0, k*pi/10, 200)));
    writeVideo(v, getframe);
end
close(v);

그래픽 객체와 핸들 사용자 정의

MATLAB 그래픽은 핸들 객체의 트리(figure → axes → lines, text, patches)로 구축됩니다. set/get이 속성을 수정하고; findobj가 속성으로 객체를 찾습니다. 'Interpreter' 옵션은 수학 표기법을 위해 TeX나 전체 LaTeX 렌더링을 가능하게 합니다. exportgraphics(R2020a+)는 타이트한 경계 상자가 있는 출판 품질의 벡터 PDF를 생성합니다 — 논문에 삽입하는 데 예전 print보다 훨씬 낫습니다.

matlab
% everything in MATLAB graphics is a handle object
h = plot(1:10, 'r-');
set(h, 'LineWidth', 3, 'Marker', 'o', 'MarkerSize', 8);
get(h, 'Color')         % returns [1 0 0]

% find objects
ax = gca;               % current axes
fig = gcf;              % current figure
lines = findobj(ax, 'Type', 'line');

% property exploration
get(ax)                 % list all axes properties
set(ax)                 % list possible values

% text annotations with LaTeX
text(2, 0.5, '\alpha^2 + \beta^2', 'Interpreter', 'tex');
title('$\int_0^1 x^2 dx$', 'Interpreter', 'latex');

% legend with custom location and orientation
legend({'data1','data2'}, 'Location','northwest','Orientation','horizontal');

% export with tight bounding box
exportgraphics(gcf, 'fig.pdf', 'ContentType','vector');
12

GUI와 App Designer

App Designer 기초

App Designer(appdesigner로 실행)는 MATLAB GUI를 구축하는 현대적 시각 도구이며, 레이아웃과 코드를 묶은 .mlapp 파일을 저장합니다. 프로그래밍 방식 UI의 경우 uifigure(R2014b+)가 uibutton, uilabel, uieditfield, uislider, uidropdown, uiaxes 같은 현대적 컴포넌트로 그림 창을 생성합니다. 콜백은 ButtonPushedFcn 같은 속성에 할당된 함수 핸들입니다. 오래된 GUIDE는 더 이상 사용되지 않으며; 새 코드는 uifigure 기반 컴포넌트나 App Designer를 사용해야 합니다.

matlab
% App Designer (appdesigner command) creates .mlapp files
% Modern replacement for GUIDE (deprecated in R2020a)

% programmatic UI (alternative to App Designer)
f = uifigure('Name', 'My App', 'Position', [100 100 600 400]);

% add components
btn = uibutton(f, 'Text', 'Click Me', ...
    'Position', [50 300 100 30]);
lbl = uilabel(f, 'Text', 'Hello', ...
    'Position', [50 250 200 30]);
fld = uieditfield(f, 'text', 'Position', [50 200 200 30]);

% slider and drop-down
sld = uislider(f, 'Position', [50 150 200 3]);
dd = uidropdown(f, 'Items', {'A','B','C'}, ...
    'Position', [50 100 100 30]);

% axes for plotting
ax = uiaxes(f, 'Position', [300 100 250 250]);
plot(ax, 1:10, rand(1,10));

% callback
btn.ButtonPushedFcn = @(src,event) clickHandler(lbl);

function clickHandler(lbl)
    lbl.Text = ['Clicked at ' datestr(now)];
end

레이아웃 관리자와 컨테이너

uigridlayout(R2018b+)은 현대적 반응형 레이아웃 관리자입니다 — 행과 열은 고정, 비례('1x'), 콘텐츠 맞춤일 수 있습니다. uitabgroup/uitab이 탭 인터페이스를 생성합니다. uipanel은 관련 컴포넌트를 시각적으로 그룹화합니다. uiscrollbox는 창을 넘는 콘텐츠에 스크롤을 추가합니다. 대화상자 함수(uigetfile, inputdlg, msgbox, questdlg)가 표준 파일 선택, 입력, 알림을 처리합니다. 이 레이아웃 도구는 전문적이고 크기 조절 가능한 MATLAB 응용 프로그램을 구축하는 데 필수적입니다.

matlab
f = uifigure;

% grid layout (responsive)
g = uigridlayout(f, [3 2]);
g.RowHeight = {'1x', '2x', '1x'};
g.ColumnWidth = {'1x', '2x'};

btn1 = uibutton(g); btn1.Layout.Row = 1; btn1.Layout.Column = 1;
btn2 = uibutton(g); btn2.Layout.Row = 1; btn2.Layout.Column = 2;

% tab group
tg = uitabgroup(f);
t1 = uitab(tg, 'Title', 'Plot');
t2 = uitab(tg, 'Title', 'Data');
ax = uiaxes(t1); plot(ax, rand(5));

% panel for grouping
p = uipanel(f, 'Title', 'Settings', 'Position', [20 20 200 150]);

% scrollable container for long content
sf = uiscrollbox(f);
% add many components inside sf

% dialog windows
uigetfile('*.mat', 'Select MAT file');
inputdlg({'Name','Age'}, 'Enter data');
msgbox('Operation complete');

콜백과 이벤트 처리

현대 MATLAB은 event.Value나 event.Key 같은 구조화된 데이터를 전달하는 두 인수(src, event)의 함수 핸들 콜백을 사용합니다. ValueChangingFcn은 상호작용 중 지속적으로 발생하고; ValueChangedFcn은 끝에 한 번 발생합니다. addlistener는 모든 속성에 영구 리스너를 생성합니다. timer 객체는 스케줄에 따라 콜백을 실행합니다 — 라이브 데이터 수집 UI에 유용합니다. 메모리 누수를 방지하려면 항상 리스너와 타이머를 정리(delete)하세요.

matlab
% value-changing callback (slider)
sld = uislider(f);
sld.ValueChangingFcn = @(src,event) onSlider(src, event);

function onSlider(src, event)
    disp(['Dragging: ' num2str(event.Value)]);
end

% value-changed callback (final value)
sld.ValueChangedFcn = @(src,event) disp(['Final: ' num2str(event.Value)]);

% button callback with event data
btn.ButtonPushedFcn = @onButton;
function onButton(src, event)
    fprintf('Button %s pushed
', src.Text);
end

% keyboard callback on figure
f.WindowKeyPressFcn = @(src,event) onKey(event);
function onKey(event)
    fprintf('Key: %s
', event.Key);
end

% listener pattern (any property change)
lh = addlistener(btn, 'Text', 'PostSet', @(src,event) disp('Text changed'));
delete(lh);  % remove listener

% timer for periodic updates
t = timer('ExecutionMode','fixedRate','Period',1, ...
    'TimerFcn',@(~,~) disp('tick'));
start(t);

배포를 위한 앱 패키징

matlab.apputil.package는 App Designer 앱을 사용자가 Apps 탭에서 설치하는 .mlappinstall 파일로 묶습니다. Application Compiler(deploytool)는 무료 MATLAB Runtime으로 실행되는 독립 실행형(.exe)을 생성합니다 — 타겟에 MATLAB 라이선스가 필요 없습니다. Web Apps(R2020a+)는 MATLAB Web App Server에 배포되어 어떤 브라우저에서도 실행됩니다. 이 배포 파이프라인으로 비 MATLAB 사용자와 MATLAB 응용 프로그램을 공유할 수 있습니다.

matlab
% package an App Designer app as a .mlappinstall file
% using the Application Compiler (deploytool app)

% programmatically create a packaged app
appFile = matlab.apputil.package(...
    'Name', 'MyPlotTool', ...
    'Summary', 'A simple plotting utility', ...
    'Description', 'Plots user-supplied data.', ...
    'MainFile', 'MyPlotTool.mlapp', ...
    'FolderPath', 'my_app_package');

% install the app
matlab.apputil.install('MyPlotTool.mlappinstall');

% list installed apps
apps = matlab.apputil.getInstalledApps;

% uninstall
matlab.apputil.uninstall('MyPlotTool');

% standalone desktop app (MATLAB Runtime required)
% deploytool -> Application Compiler -> produce .exe

% web app (runs in browser, MATLAB Web App Server)
% deploytool -> Web App

일반 UI 패턴

drawnow limitrate는 차단 없이 그래픽을 업데이트합니다 — 라이브 데이터 표시에 중요합니다. uitable은 정렬 가능한 열로 표 형식 데이터를 표시합니다. uiprogressdlg는 긴 작업을 위한 모달 진행 바를 보여줍니다. uicontextmenu는 모든 컴포넌트에 우클릭 메뉴를 추가합니다. 이 패턴은 가장 일반적인 UI 요구를 다룹니다: 라이브 업데이트, 데이터 테이블, 진행 피드백, 컨텍스트 민감 액션. 높은 처리량의 라이브 플롯에는 스트리밍 데이터에 최적화된 animatedline을 고려하세요.

matlab
% live plot update from worker
f = uifigure; ax = uiaxes(f); h = plot(ax, NaN, NaN);
for k = 1:100
    set(h, 'XData', 1:k, 'YData', rand(1,k));
    drawnow limitrate;  % throttle for performance
end

% table display
tdata = table({'A';'B';'C'}, [1;2;3], 'VariableNames', {'Name','Val'});
uit = uitable(f, 'Data', tdata.Variables, ...
    'ColumnName', tdata.Properties.VariableNames, ...
    'Position', [20 20 200 150]);

% progress dialog
d = uiprogressdlg(f, 'Title', 'Working', 'Message', 'Processing...');
for k = 1:100
    pause(0.01);
    d.Value = k;
    d.Message = sprintf('%d%% complete', k);
end
close(d);

% context menu
cm = uicontextmenu(f);
m1 = uimenu(cm, 'Text', 'Reset', 'MenuSelectedFcn', @reset);
ax.UIContextMenu = cm;
13

Image Processing Toolbox

이미지 읽기, 쓰기, 표시

imread는 PNG, JPEG, TIFF, BMP와 많은 과학 형식을 지원합니다. 이미지 데이터 타입이 중요합니다: uint8(0-255)은 파일에 흔하고, double(0-1)은 처리용입니다. double()/uint8()(자름) 대신 항상 im2double/im2uint8(재스케일)을 사용하세요. im2gray(R2020b+)가 rgb2gray를 대체합니다. imwrite는 JPEG 품질 같은 형식별 옵션을 지원합니다. imfinfo는 픽셀 데이터를 로드하지 않고 메타데이터를 읽습니다.

matlab
% read and display an image
img = imread('peppers.png');
imshow(img);
title('RGB image');

% image types
% uint8 (0-255), uint16, double (0-1), logical (binary)
whos img
class(img)              % uint8
size(img)               % rows x cols x channels

% convert between types
d = im2double(img);     % scale to [0,1]
u = im2uint8(d);        % scale to [0,255]
g = im2gray(img);       % RGB to grayscale (R2020b+, replaces rgb2gray)

% write to file
imwrite(g, 'gray.png');
imwrite(g, 'gray.jpg', 'Quality', 90);

% info without loading
info = imfinfo('peppers.png');
disp(info.Width);

% montage of multiple images
fileList = dir('*.png');
montage({fileList.name});

필터링과 향상

imgaussfilt는 현대적 가우시안 블러입니다(fspecial('gaussian') + imfilter 대체). medfilt2는 가장자리를 흐리지 않고 소금-후추 잡음을 제거합니다. fspecial이 미리 정의된 커널(sobel, prewitt, laplacian, gaussian)을 생성합니다. imsharpen은 언샤프 마스킹으로 가장자리를 향상합니다. histeq는 전역 히스토그램 평활화를 수행하고; adapthisteq(CLAHE)는 비균일 이미지에서 더 나은 대비를 위해 국소적으로 수행합니다. imadjust는 밝기/대비 보정을 위해 강도 범위를 매핑합니다.

matlab
img = im2double(imread('cameraman.tif'));

% Gaussian blur
h = imgaussfilt(img, 2);   % sigma = 2
h2 = imgaussfilt(img, [3 3], 1.5);

% median filter (salt-and-pepper noise)
noisy = imnoise(img, 'salt & pepper', 0.05);
m = medfilt2(noisy, [3 3]);

% custom 2D filter
kernel = fspecial('sobel');
edge_img = imfilter(img, kernel);

% unsharp masking (sharpen)
sharp = imsharpen(img, 'Amount', 0.8, 'Radius', 1.5);

% histogram equalization
eq = histeq(img);          % global
eq2 = adapthisteq(img);    % CLAHE (local)

% image arithmetic
bright = imadd(img, 0.1);
contrast = imadjust(img, [0.3 0.7], []);

형태학적 연산과 분할

형태학적 연산(erode, dilate, open, close)은 구조 요소(strel)를 사용해 이진 이미지를 처리합니다. 열기는 작은 객체를 제거하고; 닫기는 작은 구멍을 채웁니다. bwconncomp는 연결된 영역을 찾고; regionprops는 각각에 대한 측정(면적, 무게 중심, 경계 상자)을 추출합니다. watershed는 닿아 있는 객체를 분할합니다. edge는 경계를 검출합니다(Canny가 가장 강건). graythresh는 Otsu의 전역 임계값을 계산하고; multithresh는 다단계로 합니다. 이 도구들은 컴퓨터 비전 전처리의 핵심입니다.

matlab
bw = imread('text.png');
bw = imbinarize(bw);

% morphological operations
se = strel('disk', 3);
er = imerode(bw, se);       % shrink objects
di = imdilate(bw, se);      % grow objects
op = imopen(bw, se);        % erode then dilate (removes small noise)
cl = imclose(bw, se);       % dilate then erode (fills small holes)

% connected components
cc = bwconncomp(bw);
stats = regionprops(cc, 'Area', 'Centroid', 'BoundingBox');
[areas, idx] = sort([stats.Area], 'descend');

% watershed segmentation
grad = imgradient(bw);
D = -bwdist(~bw);
L = watershed(D);

% edge detection
edges = edge(bw, 'canny');
edges2 = edge(bw, 'sobel');

% thresholding
T = graythresh(img);        % Otsu's method
bw2 = imbinarize(img, T);

특징 검출과 변환

특징 검출은 매칭과 추적을 위해 구별되는 점을 찾습니다. Harris 코너는 빠르지만 스케일 불변이 아니고; SURF와 ORB는 여러 뷰에서 강건한 매칭을 위해 스케일/회전 불변입니다. extractFeatures는 검출된 점에서 기술자를 계산합니다. 허프 변환은 파라미터 공간에서 투표로 선(과 원)을 검출합니다 — 문서 기울기 보정과 차선 검출에 유용합니다. imregtform은 강도 기반 이미지 등록을 수행해 두 이미지를 정렬하는 기하학적 변환을 계산합니다.

matlab
img = imread('cameraman.tif');

% corner detection (Harris)
corners = detectHarrisFeatures(img);
[~, strength] = corners;
imshow(img); hold on; plot(corners);

% SURF features (scale-invariant)
points = detectSURFFeatures(img);
[f1, vpts1] = extractFeatures(img, points);

% ORB features (faster, binary)
points = detectORBFeatures(img);

% Hough transform for line detection
bw = edge(img, 'canny');
[H, T, R] = hough(bw);
P = houghpeaks(H, 5);
lines = houghlines(bw, T, R, P);

% image registration
% (find transform between two images)
moving = imread('rotated.png');
fixed = img;
[optimizer, metric] = imregconfig('monomodal');
tform = imregtform(moving, fixed, 'affine', optimizer, metric);
registered = imwarp(moving, tform);

일괄 처리와 큰 이미지

일괄 처리의 경우 parfor가 이미지 간에 병렬화합니다. blockproc는 큰 이미지를 타일로 처리합니다 — 전체 이미지가 메모리에 맞지 않을 때 필수적입니다; 'Destination' 옵션은 출력을 디스크로 스트리밍합니다. imageDatastore는 수동으로 나열하기엔 너무 큰 컬렉션을 관리하며 tall 배열과 MapReduce 프레임워크와 통합되어 아웃오브코어 계산을 합니다. bigTIFF 지원은 기가픽셀 현미경과 원격 감지 이미지를 처리합니다.

matlab
% process many images in a folder
fileList = dir('*.tif');
parfor k = 1:numel(fileList)
    img = imread(fileList(k).name);
    result = processImage(img);
    imwrite(result, ['out_' fileList(k).name]);
end

% block processing for large images
fun = @(block) std2(block);
B = blockproc('large.tif', [256 256], fun);
B = blockproc('large.tif', [256 256], fun, 'Destination', 'out.tif');

% work with very tall/wide images without loading all
% (bigTIFF, multiresolution)
t = Tiff('big.tif', 'r');
imgInfo = t.getImageInfo;

% image datastore for huge collections
imds = imageDatastore('images/', 'IncludeSubfolders', true);
imds.ReadSize = 10;  % read 10 at a time
while hasdata(imds)
    [imgs, info] = read(imds);
    % process batch
end

% tall arrays (out-of-core) for pixel statistics
t = tall(imds);
14

Optimization Toolbox

비제약과 제약 최적화

fminunc는 부드러운 비제약 문제를 풀고; fmincon은 범위, 선형, 비선형 제약을 처리합니다. linprog와 quadprog는 선형 제약이 있는 선형 및 이차 목적에 특화되어 — 일반 솔버보다 훨씬 빠릅니다. optimoptions가 솔버 동작(알고리즘, 허용 오차, 표시)을 구성합니다. 'interior-point' 알고리즘은 큰 문제에 강건하고; 'sqp'는 비선형 제약에 좋습니다. 가용할 때 항상 해석적 기울기를 제공하세요.

matlab
% unconstrained minimization
f = @(x) (x(1)-2)^2 + (x(2)-3)^2;
x0 = [0 0];
[x, fval] = fminunc(f, x0);

% constrained (with fmincon)
A = []; b = []; Aeq = []; beq = [];
lb = [0 0]; ub = [];
nonlcon = @(x) deal([], x(1) + x(2) - 4);  % x1+x2 <= 4
[x, fval] = fmincon(f, x0, A, b, Aeq, beq, lb, ub, nonlcon);

% linear programming
f_lp = [-1 -1];            % minimize -x1 - x2
A_lp = [1 1; -1 1]; b_lp = [4; 2];
[x, fval] = linprog(f_lp, A_lp, b_lp, [], [], [0;0]);

% quadratic programming
H = [1 -1; -1 2]; c = [-2; -6];
[x, fval] = quadprog(H, c, [], [], [], [], [0;0]);

% set optimization options
opts = optimoptions('fmincon', 'Algorithm','interior-point', ...
    'Display','iter', 'MaxIterations', 200);
[x, fval] = fmincon(f, x0, A, b, Aeq, beq, lb, ub, nonlcon, opts);

전역과 다목적 최적화

국소 솔버(fminunc, fmincon)는 국소 최소에 갇힐 수 있습니다. GlobalSearch와 MultiStart는 많은 시작점에서 국소 솔버를 실행합니다. ga(유전 알고리즘), particleswarm, simulannealbnd는 도함수가 없는 전역 방법입니다 — 느리지만 불연속이나 잡음이 있는 목적에 작동합니다. gamultiobj는 다목적 문제의 파레토 전선을 찾아 비지배 해 집합을 반환합니다. 문제의 매끄러움, 차원성, 전역 최적성 보장 필요 여부에 따라 선택하세요.

matlab
% GlobalSearch / MultiStart for non-convex problems
f = @(x) x(1)^2 + x(2)^2 + 10*sin(x(1)) + 10*sin(x(2));
opts = optimoptions('fmincon', 'Algorithm','sqp');
problem = createOptimProblem('fmincon','objective',f, ...
    'x0',[0 0],'lb',[-5 -5],'ub',[5 5],'options',opts);
gs = GlobalSearch;
[x, fval] = run(gs, problem);

% genetic algorithm
[x, fval] = ga(f, 2, [], [], [], [], [-5 -5], [5 5]);

% particle swarm
[x, fval] = particleswarm(f, 2, [-5 -5], [5 5]);

% simulated annealing
[x, fval] = simulannealbnd(f, [0 0], [-5 -5], [5 5]);

% multiobjective (Pareto front)
f_multi = @(x) [x(1)^2 + x(2)^2, (x(1)-1)^2 + (x(2)-1)^2];
[x, fval] = gamultiobj(f_multi, 2, [], [], [], [], [-2 -2], [2 2]);
plot(fval(:,1), fval(:,2), 'o');

곡선 피팅과 파라미터 추정

fittype은 사용자 정의 파라메트릭 모델을 정의하고; fit은 자동 시작점 휴리스틱으로 회귀를 수행합니다. lsqcurvefit은 더 낮은 수준의 비선형 최소제곱 솔버입니다 — 미세 제어나 사용자 정의 야코비안이 필요할 때 유용합니다. confint와 predint는 불확실성 정량화를 위한 신뢰와 예측 구간을 반환합니다. Curve Fitter 앱(cftool)은 피팅을 탐색하는 대화형 인터페이스를 제공합니다. 모형 오지정을 시사하는 체계적 구조에 대해 항상 잔차를 확인하세요.

matlab
% fit a custom model to data
x = linspace(0, 5, 50);
y = 2*exp(-0.5*x) + 0.1*randn(size(x));

% define model and fit
model = fittype('a*exp(-b*x)', 'independent', 'x', ...
    'coefficients', {'a','b'});
f = fit(x', y', model, 'StartPoint', [1 1]);
plot(f, x, y);

% predefined models
f2 = fit(x', y', 'exp2');     % two-term exponential
f3 = fit(x', y', 'poly2');    % quadratic polynomial

% nonlinear least squares with lsqcurvefit
fun = @(p, xdata) p(1)*exp(-p(2)*xdata);
[p, resnorm] = lsqcurvefit(fun, [1 1], x, y);

% confidence intervals
ci = confint(f, 0.95);
predint(f, x', 0.95, 'observation', 'functional');

% smoothing spline
sf = fit(x', y', 'smoothingspline');

정수와 조합 최적화

intlinprog는 혼합 정수 선형 계획을 풉니다 — 스케줄링, 라우팅, 할당 문제의 핵심입니다. matchpairs는 O(n^3)에 할당 문제를 최적으로 풉니다. 외판원 문제는 제약 집합이 지수적이므로 반복적 부투어 제거가 필요합니다. surrogateopt는 비싼 블랙박스 함수(예: 평가당 분 단위 시뮬레이션)를 위한 것입니다 — 서로게이트 모델을 구축하고 지능적으로 샘플링합니다. 정확한 방법으로는 너무 큰 조합 문제에는 ga나 사용자 정의 휴리스틱을 고려하세요.

matlab
% mixed-integer linear programming (TSP-like problems)
f = [-3 -2];             % maximize 3x + 2y
A = [1 1; 2 1]; b = [4; 6];
intcon = 1:2;            % both variables integer
[x, fval] = intlinprog(f, intcon, A, b, [], [], [0;0]);

% assignment problem (Hungarian algorithm)
cost = [4 1 3; 2 3 4; 3 4 1];
[assignment, cost_total] = matchpairs(cost, false);

% traveling salesman via intlinprog
n = 8;  % cities
distances = rand(n, n); distances = distances + distances';
% (build subtour elimination constraints iteratively)

% knapsack
weights = [2 3 4 5]; values = [3 4 5 6];
W = 5;
f = -values;
A = weights; b = W;
intcon = 1:4;
[x, fval] = intlinprog(f, intcon, A, b, [], [], zeros(4,1), ones(4,1));

% surrogate optimization (expensive black-box)
obj = @(x) expensive_eval(x);
[x, fval] = surrogateopt(obj, lb, ub);

최적화 작업 흐름과 모범 사례

올바른 솔버 선택이 가장 중요한 결정입니다 — 선형 계획에 fmincon을 사용하면 성능이 몇 자릿수 낭비됩니다. 해석적 기울기 제공(문제 기반 프레임워크나 optimoptions 통해)이 속도와 신뢰성을 크게 향상합니다. 변수를 1 근처로 스케일링하면 조건수가 개선됩니다. 수렴을 확인하려면 exitflag와 firstorderopt를 확인하세요. 문제 기반 프레임워크(optimproblem, optimvar)는 더 읽기 쉽고 MATLAB이 솔버를 자동 선택하게 합니다 — 새 코드에 선호됩니다.

matlab
% 1. choose solver based on problem type
%    smooth? -> fminunc/fmincon
%    linear? -> linprog/intlinprog
%    integer? -> intlinprog
%    nonsmooth/global? -> ga/particleswarm/GlobalSearch

% 2. provide gradients and Jacobians when possible
f = @(x) x(1)^2 + x(2)^2;
gradf = @(x) [2*x(1); 2*x(2)];
prob = optimproblem('Objective', f);
prob.Objective.Gradient = gradf;

% 3. scale variables to ~[1, 1]
x_scaled = (x - x0) / scale;

% 4. check optimality and feasibility
output.exitflag       % 1 = converged
output.firstorderopt  % should be near 0

% 5. warm start sequential problems
opts = optimoptions('quadprog','ObjectiveLimit',1e-8);
x_new = quadprog(H, c, A, b, [], [], lb, ub, x_old, opts);

% 6. use problem-based framework (cleaner)
x = optimvar('x', 2, 'LowerBound', 0);
prob = optimproblem('Objective', x(1)^2 + x(2)^2);
prob.Constraints.c1 = x(1) + x(2) >= 1;
sol = solve(prob);
15

병렬 컴퓨팅

parfor 루프와 병렬 풀

parfor는 병렬화로 가장 쉬운 길입니다 — 루프 반복을 워커에 분배합니다. 반복은 독립적이어야 합니다(k-1에 의존하는 반복 k 없음). 변수는 분류됩니다: 루프 변수(k), 슬라이스(k만으로 인덱스), 브로드캐스트(읽기 전용), 감소(+나 * 같은 결합 연산으로 결합). 통신 오버헤드로 인해 각 반복이 상당한 작업을 수행할 때만 parfor가 도움이 됩니다. 풀을 한 번 시작하고; 시작 비용을 피하기 위해 parfor 루프 간에 재사용하세요.

matlab
% start a parallel pool (workers = CPU cores)
pool = gcp('nocreate');
if isempty(pool)
    parpool;  % start default pool
end

% parfor: parallel for loop
n = 1e6;
results = zeros(1, n);
parfor k = 1:n
    results(k) = expensive_computation(k);
end

% restrictions:
% - iterations must be independent (no data dependencies)
% - variables classified as loop, sliced, broadcast, reduction
% - cannot break/continue

% reduction variables (combine results)
total = 0;
parfor k = 1:n
    total = total + compute(k);
end

% sliced variables (each iteration writes distinct element)
out = zeros(n, 1);
parfor k = 1:n
    out(k) = k^2;
end

% control pool size
delete(gcp('nocreate'));  % shut down
parpool('local', 4);      % 4 workers

spmd와 분산 배열

spmd는 각각을 식별하는 labidx와 함께 모든 워커에서 같은 코드를 실행합니다 — 각 워커가 청크를 처리하는 데이터 병렬 알고리즘에 유용합니다. Composite 변수(A{1}, A{2})는 워커별 결과를 저장합니다. 분산 배열은 단일 논리 배열을 워커에 분산하고; localpart가 로컬 청크를 줍니다. labSendrecv와 gcat/gplus가 워커 간 통신을 가능하게 합니다. parfor가 표현할 수 없는 세밀한 병렬화(예: 통신이 필요한 반복 알고리즘)에 spmd를 사용하세요.

matlab
% spmd: single program, multiple data
spmd
    labidx              % worker index (1 to n)
    numlabs             % total workers
    A = rand(1000) * labidx;
    % each lab has its own A
end

% access Composite (per-worker data)
A{1}                    % A from worker 1
A{2}                    % A from worker 2

% distributed arrays (spread across workers)
D = distributed.rand(10000);
size(D)                 % 10000x10000 total
L = localpart(D);       % this worker's chunk

% communicate between labs
spmd
    data = rand(100, 1);
    % send to next lab, receive from previous
    next_lab = mod(labidx, numlabs) + 1;
    prev_lab = mod(labidx - 2, numlabs) + 1;
    rcvd = labSendrecv(data, next_lab, prev_lab);
end

% gather distributed to local
D = distributed.rand(1000);
full_matrix = gather(D);

GPU 컴퓨팅

gpuArray가 GPU로 데이터를 전송하고; 후속 연산은 거기서 실행되어 gather()가 결과를 가져올 때까지 GPU에 머뭅니다. 대부분의 요소별과 선형 대수 함수가 GPU 지원됩니다. arrayfun이 GPU에서 사용자 정의 요소별 함수를 실행합니다(스칼라 연산만). 다중 GPU 시스템의 경우 gpuDevice(k)로 각 parfor 워커에 다른 GPU를 할당하세요. GPU 컴퓨팅은 큰 조밀 선형 대수와 요소별 연산에 뛰어나고; 데이터 전송 오버헤드로 작은 배열에는 비효율적입니다.

matlab
% move data to GPU
A = gpuArray(rand(10000));
B = gpuArray(eye(10000));

% operations execute on GPU
C = A * B;              % GPU matrix multiply
D = A + B;
E = sum(A, 1);

% gather results back to CPU
C_cpu = gather(C);

% many built-in functions are GPU-enabled
x = gpuArray.linspace(-10, 10, 1e6);
y = sin(x) .* exp(-x.^2);

% arrayfun on GPU (custom element-wise functions)
f = @(a, b) a.^2 + b.^2;
result = arrayfun(f, A, B);

% check GPU
gpuDevice            % info about current GPU
gpuDeviceCount       % number of available GPUs

% page multiple GPUs
parfor k = 1:4
    gpuDevice(k);
    A = gpuArray(rand(5000));
    % ... compute on GPU k
end

batch와 작업 스케줄링

batch는 함수를 백그라운드에서 비동기로 실행합니다 — 세션을 차단하지 않으려는 긴 계산에 유용합니다. 'Pool' 옵션과 함께 batch는 자체가 parfor를 사용하는 함수를 실행합니다. 더 낮은 수준의 작업/태스크 API가 스케줄링에 대한 미세 제어를 줍니다. parcluster가 클러스터 프로필을 선택하고; MATLAB은 Parallel Computing Toolbox의 일반 스케줄러 인터페이스를 통해 SLURM, PBS, LSF와 통합됩니다. HPC의 경우 공유 메모리에 의존하지 말고 데이터를 파일로 저장하고 스크립트를 제출하세요.

matlab
% run a function in background
job = batch(@my_function, 0, {arg1, arg2});

% check status
job.State              % 'queued', 'running', 'finished'
wait(job);             % block until done
load(job);             % retrieve results

% batch with parfor inside
job = batch(@my_parfor_func, 1, {input_data}, 'Pool', 4);

% job and task objects (lower-level)
job = createJob(pool);
task = createTask(job, @my_func, 1, {arg1});
submit(job);
wait(job);
result = fetchOutputs(task);

% cluster types
% 'local' - on this machine
% 'MJS' - MATLAB Job Scheduler (server cluster)
% 'SLURM'/'PBS' - HPC scheduler integration
c = parcluster('local');
c.NumWorkers = 8;
c.saveProfile;

성능과 병렬 코드 프로파일링

profile on -parallel로 병렬 코드를 프로파일하여 워커별 타임라인을 보세요. 가속은 암달의 법칙에 의해 제한됩니다: 코드의 10%가 직렬이면 워커 수와 관계없이 최대 10배 가속입니다. 일반적 함정: 너무 작은 반복(오버헤드가 작업 초과), 큰 브로드캐스트 변수(전송 비용), 과도한 감소 연산. parallel.pool.DataQueue로 워커에서 차단 없이 라이브 진행 업데이트를 가능하게 합니다 — 긴 병렬 작업 모니터링에 유용합니다. 병렬화가 실제로 도움이 되는지 확인하려면 항상 전후로 측정하세요.

matlab
% profile parallel code
profile on -parallel
parfor k = 1:100
    compute(k);
end
profile off
profview                % visualize

% measure speedup
tic;
serial_result = serial_compute();
t_serial = toc;

tic;
parfor_result = parallel_compute();
t_parallel = toc;

speedup = t_serial / t_parallel;
fprintf('Speedup: %.2fx using %d workers
', speedup, pool.NumWorkers);

% avoid common pitfalls:
% 1. too little work per iteration (overhead dominates)
% 2. large broadcast variables (transfer cost)
% 3. false sharing via reduction variables

% data queue for live updates from workers
Q = parallel.pool.DataQueue;
afterEach(Q, @update_plot);
parfor k = 1:n
    % ... compute ...
    send(Q, partial_result);
end
16

객체 지향 프로그래밍

클래스와 속성

MATLAB 클래스는 ClassName.m 파일에 있습니다. classdef 블록이 속성과 메서드를 포함합니다. 속성 속성이 접근을 제어합니다: SetAccess=protected는 클래스 메서드만 쓸 수 있음을 의미하고; Constant가 클래스 수준 상수를 정의합니다. 생성자는 클래스 이름의 메서드입니다. MATLAB은 기본적으로 값 의미론을 사용합니다(할당 시 객체 복사) — 참조 의미론을 위해 handle 클래스를 사용하세요. disp 같은 오버로드된 메서드가 기본 동작을 사용자 정의합니다.

matlab
% class definition in a file named Point.m
classdef Point
    properties
        x = 0       % public, with default
        y = 0
    end
    properties (SetAccess = protected)
        id          % settable only by class methods
    end
    properties (Constant)
        PI = 3.14159
    end

    methods
        function obj = Point(x, y)
            if nargin > 0
                obj.x = x;
                obj.y = y;
            end
            obj.id = randi(1e6);
        end

        function r = distance(obj)
            r = sqrt(obj.x^2 + obj.y^2);
        end

        function disp(obj)
            fprintf('Point(%.2f, %.2f) [id=%d]
', ...
                obj.x, obj.y, obj.id);
        end
    end
end

% usage
p = Point(3, 4);
p.distance()           % 5
disp(p)

handle과 value 클래스

value와 handle 클래스 간의 선택은 근본적입니다. value 클래스(기본)는 할당과 메서드 호출 시 복사됩니다 — 불변 데이터에 더 안전합니다. handle 클래스(handle 하위 클래스)는 참조입니다: 할당과 복사가 같은 객체를 가리키고, Java/Python 객체 같습니다. handle 클래스는 GUI 컴포넌트, 파일 핸들, 호출자 간 공유되는 가변 상태에 필요합니다. 불변성이 바람직한 수학적 객체(벡터, 행렬)에는 value 클래스를 사용하세요.

matlab
% value class (default): copies on assignment
classdef Vec
    properties
        data
    end
    methods
        function obj = Vec(d)
            obj.data = d;
        end
    end
end

v1 = Vec([1 2 3]);
v2 = v1;             % COPY
v2.data = [4 5 6];
disp(v1.data)        % still [1 2 3]

% handle class: references shared
classdef HVec < handle
    properties
        data
    end
    methods
        function obj = HVec(d)
            obj.data = d;
        end
    end
end

h1 = HVec([1 2 3]);
h2 = h1;             % REFERENCE (same object)
h2.data = [4 5 6];
disp(h1.data)        % [4 5 6] - changed!

% handle classes support delete method
% isequal(h1, h2) -> true (same object)

상속과 다형성

상속은 classdef 줄에 <를 사용하고; obj@SuperClass(args)가 슈퍼클래스 생성자를 호출합니다. MATLAB은 다중 상속을 지원하지만 드물고 다이아몬드 문제를 유발할 수 있습니다. 추상 메서드(methods (Abstract)에 선언)는 하위 클래스가 구현해야 하고; 기본 클래스는 인스턴스화할 수 없습니다. 다형성은 자연스럽게 작동합니다: 모든 객체에서 메서드를 호출하면 MATLAB이 올바른 구현으로 디스패치합니다. 런타임 타입 검사에는 isa(obj, 'ClassName')와 isprop/ismethod를 사용하세요.

matlab
% single inheritance
classdef Dog < Animal
    methods
        function obj = Dog(name)
            obj@Animal(name);  % call superclass constructor
        end
        function sound(obj)
            disp([obj.name ' says Woof']);
        end
    end
end

% multiple inheritance
classdef FlyingFish < Fish & Bird
    methods
        function obj = FlyingFish(name)
            obj@Fish(name);
            obj@Bird(name);
        end
    end
end

% abstract methods and classes
classdef Shape
    methods (Abstract)
        area(obj)
        perimeter(obj)
    end
end

classdef Circle < Shape
    properties
        radius
    end
    methods
        function obj = Circle(r)
            obj.radius = r;
        end
        function a = area(obj)
            a = pi * obj.radius^2;
        end
        function p = perimeter(obj)
            p = 2 * pi * obj.radius;
        end
    end
end

% polymorphism
shapes = {Circle(2), Square(3)};
for k = 1:numel(shapes)
    fprintf('Area: %.2f
', shapes{k}.area());
end

이벤트와 리스너

이벤트 모델은 옵저버 패턴을 구현합니다: 클래스가 이벤트를 선언하고, 리스너가 콜백을 등록하고, notify가 이벤트를 발생시킵니다. 이것은 생산자와 소비자를 분리합니다 — GUI, 시뮬레이션, 반응형 시스템에 필수적입니다. 속성 set 메서드(set.PropertyName)가 할당을 가로채고 이벤트를 유발할 수 있습니다. 리스너는 임시(addlistener, 객체 수명에 연결)이거나 영구(리스너 객체를 변수에 보관)일 수 있습니다. 메모리 누수를 방지하려면 완료 시 항상 리스너를 삭제하세요.

matlab
classdef TemperatureSensor < handle
    properties
        Temperature = 20
    end
    events
        TemperatureChanged
        Overheated
    end
    methods
        function set.Temperature(obj, t)
            obj.Temperature = t;
            notify(obj, 'TemperatureChanged');
            if t > 100
                notify(obj, 'Overheated');
            end
        end
        function obj = TemperatureSensor()
            % nothing
        end
    end
end

% create sensor and listen
s = TemperatureSensor();
addlistener(s, 'TemperatureChanged', @onTempChanged);
addlistener(s, 'Overheated', @onOverheat);

function onTempChanged(src, event)
    fprintf('Temp now: %.1f
', src.Temperature);
end

function onOverheat(src, event)
    warning('Overheated at %.1f!', src.Temperature);
end

% trigger
s.Temperature = 25;     % prints "Temp now: 25.0"
s.Temperature = 105;    % prints temp + warning

연산자 오버로딩과 인덱싱

연산자 오버로딩으로 사용자 클래스가 +, *, [] 등으로 작동하게 합니다. 각 연산자는 함수에 매핑됩니다(plus, mtimes, minus, mrdivide, horzcat, vertcat). subsref와 subsasgn이 인덱싱을 사용자 정의합니다(obj(i), obj.field, obj{i}). 현대 MATLAB은 속성 접근에 점 표기를 선호하지만, 가짜 인덱싱 패턴(예: T(1,2,3)이 요소를 추출하는 텐서 라이브러리)에는 여전히 subsref/subsasgn이 필요합니다. 읽기 쉬운 출력을 위해 disp를, 사용자 정의 인덱싱 의미론을 위해 end/numel을 오버로드하세요.

matlab
classdef Complex
    properties
        re
        im
    end
    methods
        function obj = Complex(re, im)
            obj.re = re; obj.im = im;
        end
        function r = plus(a, b)            % a + b
            r = Complex(a.re + b.re, a.im + b.im);
        end
        function r = mtimes(a, b)          % a * b
            r = Complex(a.re*b.re - a.im*b.im, ...
                        a.re*b.im + a.im*b.re);
        end
        function r = abs(obj)              % |obj|
            r = sqrt(obj.re^2 + obj.im^2);
        end
        function disp(obj)
            fprintf('%.2f %+.2fi
', obj.re, obj.im);
        end
    end
    methods
        function r = subsref(obj, S)       % obj(...)
            if strcmp(S(1).type, '()')
                r = obj.re + 1i*obj.im;
            end
        end
        function obj = subsasgn(obj, S, val)  % obj(...) = val
            % custom assignment
        end
    end
end

c1 = Complex(1, 2); c2 = Complex(3, 4);
c3 = c1 + c2;          % uses plus
c4 = c1 * c2;          % uses mtimes
abs(c1)                % uses abs
17

디버깅과 성능 튜닝

디버거와 중단점

dbstop이 중단점을 설정합니다 — 가장 강력한 디버깅 도구입니다. 조건부 중단점(dbstop ... if condition)은 술어가 참일 때만 일시 중지하여 큰 루프에서 버그를 찾는 데 필수적입니다. dbstop if error는 잡히지 않은 예외를 디버그 일시 중지로 바꾸어 실패 지점에서 작업 공간을 검사하게 합니다. catch 블록의 ME(MException) 객체가 .message, .identifier, .stack을 전달하여 풍부한 오류 처리를 합니다. dbstack으로 호출 스택을 탐색하고 dbup/dbdown으로 호출자 작업 공간을 검사하세요.

matlab
% set breakpoints in the Editor or programmatically
dbstop in my_function at 42      % line 42 of my_function.m
dbstop in my_function at 42 if x > 10  % conditional
dbstop if error                  % pause on any error
dbstop if naninf                 % pause on NaN/Inf
dbstop if warning                % pause on warnings
dbclear all                      % clear all breakpoints
dbclear in my_function           % clear in one file

% at a breakpoint, the command window enters debug mode K>>
whos                             % inspect workspace
x                                % view variables
dbstep                           % step to next line
dbstep in                        % step into function
dbstep out                       % step out of function
dbcont                           % continue execution
dbstack                          % show call stack
dbup / dbdown                    % move up/down stack frames
dbquit                           % exit debug mode

% error recovery
try
    risky_operation();
catch ME
    fprintf('Error: %s
', ME.message);
    fprintf('Stack:
');
    for k = 1:numel(ME.stack)
        fprintf('  %s (line %d)
', ME.stack(k).name, ME.stack(k).line);
    end
end

프로파일링과 핫스팟 검출

프로파일러(profile on/off + profile viewer)가 시간이 소비되는 곳을 줄 단위로 보여줍니다 — 최적화를 위한 가장 중요한 도구입니다. 최적화 전에 항상 프로파일하세요; 병목에 대한 직관은 종종 틀립니다. timeit는 함수를 여러 번 실행하고 오버헤드를 고려하므로 마이크로벤치마크에 tic/toc보다 정확합니다. -memory 옵션이 할당을 추적하여 메모리 누수나 과도한 복사를 찾는 데 유용합니다. 최대 효과를 위해 상위 몇 개의 핫 라인에 최적화 노력을 집중하세요.

matlab
% profile a script or function
profile on
my_expensive_script();
profile off

% view results
profile viewer                 % GUI
p = profile('info');           % structure
profsave(p, 'profile_results'); % HTML report

% time individual operations
tic; A = rand(5000); A = A * A; toc;   % ~0.5s

% timeit for accurate single-function timing
f = @() sort(rand(1e6,1));
t = timeit(f);

% memory profiling
profile on -memory
% ... run code ...
profile viewer   % shows memory allocation

% identify bottlenecks
% 1. profile viewer shows time per function/line
% 2. focus on the top few hottest lines
% 3. vectorize, preallocate, or use MEX for those

벡터화와 미리 할당

MATLAB에서 가장 큰 세 가지 성능 향상: (1) 루프에서 채우기 전에 배열 미리 할당(zeros, NaN, cell), (2) BLAS/LAPACK을 활용하기 위해 연산 벡터화, (3) JIT 친화적 패턴 사용(단순 루프는 이제 빠르지만, 배열을 키우는 것은 여전히 O(n^2)). 논리 인덱싱은 if/else 루프를 단일 벡터화 할당으로 대체합니다. GPU 지원이 필요하지 않는 한 arrayfun을 피하세요 — 단순한 미리 할당된 루프가 종종 더 빠릅니다. 개선을 확인하려면 tic/toc나 timeit로 측정하세요.

matlab
% BAD: growing array in loop
tic;
s = [];
for k = 1:100000
    s = [s, k^2];     % reallocates every iteration!
end
toc;                  % ~10 seconds

% GOOD: preallocate
tic;
s = zeros(1, 100000);
for k = 1:100000
    s(k) = k^2;
end
toc;                  % ~0.01 seconds

% BEST: vectorize
tic;
s = (1:100000).^2;
toc;                  % ~0.001 seconds

% vectorize conditional logic
x = rand(10000, 1);
% BAD:
% for k = 1:numel(x)
%     if x(k) > 0.5, y(k) = 1; else, y(k) = 0; end
% end
% GOOD:
y = double(x > 0.5);

% vectorize with logical indexing
y = zeros(size(x));
y(x > 0.5) = 1;
y(x > 0.8) = 2;

% use arrayfun/gpuArray only when truly needed
% (loops with preallocation are often faster than arrayfun)

MEX 파일과 C 통합

MEX 파일로 MATLAB에서 C/C++/Fortran을 호출할 수 있습니다 — 중요한 루프를 벡터화할 수 없거나 기존 라이브러리를 감쌀 때 필수적입니다. mex가 C 파일을 .mexw64(Windows)나 .mexa64(Linux) 바이너리로 컴파일합니다. 현대 C++ MATLAB Data API(R2018a+)는 구형 mxGetPr/mxCreate API보다 타입 안전하고 깔끔합니다. 외부 응용 프로그램에서 MATLAB을 호출하려면 MATLAB Engine API나 MATLAB Compiler SDK를 사용하세요. loadlibrary는 컴파일 없이 일반 공유 라이브러리를 감쌉니다. 먼저 프로파일하세요 — 실제 병목만 MEX화하세요.

matlab
% call C/C++/Fortran code from MATLAB via MEX
% write a C file (my_func.c):
/*
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
    double *x = mxGetPr(prhs[0]);
    size_t n = mxGetNumberOfElements(prhs[0]);
    plhs[0] = mxCreateDoubleMatrix(n, 1, mxREAL);
    double *y = mxGetPr(plhs[0]);
    for (size_t k = 0; k < n; k++) y[k] = x[k] * x[k];
}
*/

% compile
mex my_func.c           % produces my_func.mexw64
% usage:
y = my_func([1 2 3]);   % [1 4 9]

% C++ with MATLAB Data API (modern, R2018a+)
% #include "mex.hpp", "mexAdapter.hpp"
% use matlab::data::TypedArray<double>

% call MATLAB from C/C++ application (MATLAB Engine API)
% #include "engine.h"
% eng = engOpen("");
% engPutVariable(eng, "x", x);
% engEvalString(eng, "y = sqrt(x)");

% loadlibrary for generic shared libraries
loadlibrary('mylib.dll', 'mylib.h');
calllib('mylib', 'my_function', arg);
unloadlibrary('mylib');

메모리 관리와 큰 데이터

메모리는 큰 계산에서 종종 병목입니다. 메모리를 절반으로 줄이고 처리량을 두 배로 늘리려면 double 대신 single을 사용하세요. 희소 행렬은 0이 아닌 것만 저장합니다. memmapfile은 바이너리 파일을 로드하지 않고 메모리에 매핑합니다 — 순차적으로 접근하는 큰 데이터셋에 완벽합니다. tall 배열(datastore와 함께)이 RAM에 맞지 않는 청크로 데이터를 처리하며, 내부적으로 MapReduce를 사용합니다. R2018b부터 MATLAB은 일부 제자리 연산(A = A + 1)을 복사 없이 수행할 수 있지만, 명시적 A(:) = ...가 이를 보장합니다. 완료 시 항상 큰 변수를 지우세요.

matlab
% check memory usage
[usr, sys] = memory;
disp(usr.PhysicalMemory.Available);

% view variable sizes
whos                  % all variables with sizes
[x_size, x_bytes] = compute_size(x);

% clear large variables when done
clear big_array;

% use single precision when possible
A = rand(5000, 'single');   % half the memory of double
B = A * A;                   % single precision matmul

% sparse for mostly-zero matrices
S = sparse(1e5, 1e5);
S(1, 1) = 1;

% memory-mapped files for huge data
m = memmapfile('large.bin', 'Format', 'double', 'Offset', 0, ...
    'Repeat', 1e8);
m.Data(1)              % access without loading all

% tall arrays for out-of-core
ds = datastore('big.csv');
t = tall(ds);
mean_t = mean(t.Var1);
gather(mean_t);        % triggers computation

% avoid copies: in-place operations
A = A + 1;             % may modify A in place (since R2018b)
A(:) = A(:) + 1;       % definitely in place
18

플로팅 고급

서브플롯과 tiledlayout

tiledlayout(R2019b+)은 subplot의 현대적 대체품입니다 — 더 나은 간격, 더 쉬운 확장, title(..., 'tiledtitle')을 통한 공유 제목. nexttile([1 2])가 여러 타일에 걸쳐 확장합니다. subplot(n, m, k)는 레거시 코드에 여전히 작동하지만 덜 유연합니다.

matlab
% tiledlayout (R2019b+) replaces subplot
tiledlayout(2, 3, 'TileSpacing', 'compact', 'Padding', 'compact');

nexttile; plot(1:10);
nexttile; scatter(rand(1, 50), rand(1, 50));
nexttile; bar(rand(5, 3));
nexttile; imagesc(magic(10));
nexttile; histogram(randn(1000, 1), 30);
nexttile; pie([30 20 50]);

% span multiple tiles
nexttile(7, [1 2]); plot(sin(0:0.1:2*pi));

% shared title and labels
title('Dashboard Demo');
xlabel('X'); ylabel('Y');

% legacy subplot
subplot(2, 2, 1); plot(1:10);
subplot(2, 2, 2); plot(10:-1:1);

축 사용자 정의

대부분의 축 속성은 축 핸들(gca)으로 접근 가능합니다. xlim/ylim이 한계를 설정하고; xticks/xticklabels가 눈금 위치와 레이블을 제어합니다. \pi 같은 TeX 마크업이 그리스 문자를 렌더링합니다. set(gca, ...)는 레거시 구문이고; ax.Property = value가 현대적(R2014b+) 동등물입니다.

matlab
x = linspace(0, 2*pi, 100);
plot(x, sin(x));

% axis limits
xlim([0 2*pi]); ylim([-1.2 1.2]);

% ticks and labels
xticks(0:pi/2:2*pi);
xticklabels({'0', '\pi/2', '\pi', '3\pi/2', '2\pi'});

% grid and minor grid
grid on; grid minor on;

% axis appearance
box on;
ax = gca;
ax.FontSize = 12;
ax.FontName = 'Courier';
ax.LineWidth = 1.5;
ax.XColor = [0.5 0.5 0.5];
ax.YDir = 'reverse';

% log scale
semilogy(1:100, 2.^(1:100));
set(gca, 'YScale', 'log');

다중 플롯과 범례

hold on으로 같은 축에 여러 플롯을 겹칠 수 있습니다 — 놀라움을 피하기 위해 항상 hold off로 끝내세요. 'Location', 'best'가 가장 덜 겹치는 모서리를 선택합니다. 'Interpreter', 'latex' 옵션이 전체 LaTeX 수학을 가능하게 합니다. 일부 플롯만 포함하려면 특정 선 핸들을 legend에 전달하세요.

matlab
x = linspace(0, 2*pi, 100);
y1 = sin(x); y2 = cos(x); y3 = sin(x) + cos(x);

% hold on for multiple lines
plot(x, y1, 'r-', 'LineWidth', 2); hold on;
plot(x, y2, 'b--', 'LineWidth', 2);
plot(x, y3, 'g:', 'LineWidth', 2); hold off;

% legend with location
legend('sin(x)', 'cos(x)', 'sin+cos', ...
       'Location', 'best', 'Orientation', 'horizontal');

% legend with TeX
legend('$\sin(x)$', '$\cos(x)$', 'Interpreter', 'latex');

% specify which lines to include
h1 = plot(x, y1); hold on;
h2 = plot(x, y2);
h3 = plot(x, y3);
legend([h1 h3], 'sin', 'sin+cos');

3D 플로팅

surf가 색칠된 서피스를 그리고; mesh가 와이어프레임을 그립니다. contour와 contourf는 2D 투영을 보여주고; clabel이 레이블을 추가합니다. plot3는 3D 파라메트릭 곡선을 그립니다. view(az, el)가 카메라 각도(방위각, 고각, 단위 도)를 설정합니다. shading interp가 색 전환을 부드럽게 합니다.

matlab
[X, Y] = meshgrid(-2:0.1:2, -2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);

% surface plot
figure;
surf(X, Y, Z);
colorbar; shading interp;

% mesh plot (wireframe)
figure;
mesh(X, Y, Z);
hidden off;                      % show hidden lines

% contour
figure;
contour(X, Y, Z, 20); colorbar;
contourf(X, Y, Z, 20); colorbar; % filled
[c, h] = contour(X, Y, Z, 20); clabel(c, h);

% 3D parametric
t = 0:0.01:10;
plot3(sin(t), cos(t), t);
xlabel('x'); ylabel('y'); zlabel('z');
view(45, 30);                    % azimuth, elevation

애니메이션과 무비

애니메이션은 drawnow로 새로고침하며 루프 내에서 플롯 데이터를 업데이트합니다. 부드러운 비디오를 위해 VideoViewer(더 이상 사용되지 않는 avifile 대체)를 사용하세요. getframe이 현재 그림을 이미지로 캡처합니다. 비디오를 열기 전에 FrameRate를 설정하세요. 완료 시 항상 close(v)로 파일을 플러시하세요.

matlab
% animate a sine wave
figure;
h = plot(NaN, NaN);
xlim([0 2*pi]); ylim([-1 1]);

for k = 1:100
  x = linspace(0, 2*pi, k);
  set(h, 'XData', x, 'YData', sin(x));
  drawnow;
end

% capture frames and save as video
v = VideoWriter('animation.mp4', 'MPEG-4');
v.FrameRate = 30; open(v);

for k = 1:60
  plot(sin(0:0.1:k/10));
  frame = getframe(gcf);
  writeVideo(v, frame);
end
close(v);

% getframe for static snapshots
figure; plot(1:10);
frame = getframe;                % struct with cdata
19

행렬 연산 심층

선형 대수 필수

선형 시스템을 풀려면 항상 A\b(백슬래시)를 사용하세요 — 행렬에 따라 올바른 분해(LU, Cholesky, QR)로 디스패치합니다. inv(A)*b는 더 느리고 수치적으로 더 나쁩니다. eig가 고유벡터를 V의 열로, 고윳값을 D의 대각선으로 반환합니다. expm은 행렬 지수입니다(요소별 exp와 다름).

matlab
A = [1 2; 3 4];
b = [5; 6];

% solve Ax = b
x = A \ b;                       % preferred (LU-based)
x = inv(A) * b;                  % avoid — slower, less stable

% factorizations
[L, U, P] = lu(A);               % PA = LU
[Q, R] = qr(A);                  % A = QR
[V, D] = eig(A);                 % A V = V D
[U, S, V] = svd(A);              % A = U S V'

% properties
det(A); trace(A); rank(A); cond(A);
null(A);                         % null space
orth(A);                         % orthonormal basis of range

% matrix functions
expm(A); logm(A); sqrtm(A);      % matrix (not element-wise)

요소별 연산과 행렬 연산

접두 점(.*)은 요소별을 의미하고; 없으면 행렬 연산입니다. 가장 흔한 MATLAB 버그: x가 행 벡터일 때 x*x — 내적에는 x*x'를, 요소별 제곱에는 x.*x를 사용하세요. '는 켤레 전치(허수 부분 부호 변경)이고; .'는 일반 전치입니다.

matlab
A = [1 2; 3 4];
B = [5 6; 7 8];

% element-wise (use .)
A .* B                           % [5 12; 21 32]
A ./ B                           % element-wise divide
A .^ 2                           % [1 4; 9 16]
A .^ B                           % element-wise power

% matrix ops (no .)
A * B                            % matrix product
A / B                            % A * inv(B)
A \ B                            % inv(A) * B
A^2                              % A * A (matrix power)
A'                               % conjugate transpose
A.'                              % non-conjugate transpose

% common gotcha
x = [1 2 3];
x * x                            % ERROR: inner dims mismatch
x * x'                           % 14 (dot product)
x .* x                           % [1 4 9] (element-wise)

재구성과 인덱싱

MATLAB은 열 우선으로 행렬을 저장하므로, 4x4에서 A(5)는 A(1, 2)입니다. 논리 인덱싱(A(mask))은 강력하고 빠릅니다 — 루프 없이 조건에 맞는 요소를 추출하거나 수정합니다. reshape는 총 요소 수가 일치해야 합니다. permute는 전치를 N-D 배열로 일반화합니다.

matlab
A = magic(4);                  % 4x4 matrix

% linear indexing (column-major)
A(5)                             % A(1, 2)
A(:)                             % column vector of all elements
A(2:5)                           % elements 2-5

% submatrix
A(1:2, 2:4)                      % rows 1-2, cols 2-4
A(:, 3)                          % all rows, col 3
A(end, :)                        % last row
A(1:2:end, :)                    % odd rows (stride)

% logical indexing
mask = A > 10;
A(mask)                          % flat list of values > 10
A(A > 10) = 0;                   % threshold in-place

% reshape, permute, flip
B = reshape(A, 2, 8);
C = permute(A, [2 1]);           % transpose N-D
flip(A); flipud(A); fliplr(A);
repmat(A, 2, 3);                 % tile 2x3

희소 행렬

희소 행렬은 0이 아닌 요소만 저장합니다 — 주로 0인 큰 행렬(예: PDE 이산화에서)에 필수적입니다. 연산은 가능할 때 희소성을 보존합니다. 백슬래시 S\b는 희소 직접 솔버(UMFPACK)를 사용합니다 — 큰 희소 시스템에 full()\b보다 훨씬 빠르고 메모리 효율적입니다. spy가 희소 패턴을 시각화합니다.

matlab
% create sparse
S = sparse(1000, 1000);
S(1, 1) = 5;
S(500, 500) = 10;

% from triplets
i = [1 2 3 4];
j = [1 2 3 4];
v = [10 20 30 40];
S = sparse(i, j, v, 4, 4);

% sparse identity and diagonal
S = speye(1000);
S = spdiags(ones(1000, 1), 0, 1000, 1000);

% operations stay sparse
S = S + S';
S = S * S;
x = S \ b;                       % uses sparse solver

% convert
F = full(S);                     % sparse -> full
S = sparse(F);                   % full -> sparse
nnz(S)                           % count non-zeros
spy(S)                           % visualize sparsity

브로드캐스팅(암시적 확장)

R2016b부터 MATLAB이 자동으로 브로드캐스트합니다(NumPy처럼) — 크기 1인 차원이 일치하도록 확장됩니다. 그 전에는 bsxfun이 필요했습니다. 브로드캐스팅은 코드를 더 깔끔하게 합니다: M - mean(M, 2)가 repmat 없이 각 행을 중심화합니다. 차원이 호환되어야 합니다(같거나 하나가 1).

matlab
% R2016b+ — automatic broadcasting
A = magic(3);                    % 3x3
b = [1 2 3];                     % 1x3

% older MATLAB: error (dims mismatch)
% modern MATLAB: b is broadcast across rows
C = A + b;                       % 3x3 result
C = A - b';
C = A .* b;

% common uses
x = (1:5)';                      % column
y = (1:5);                       % row
outer = x * y;                   % 5x5 outer product
grid = x + y;                    % 5x5 addition grid

% mean across rows
M = magic(5);
row_means = mean(M, 2);          % 5x1
centered = M - row_means;        % broadcast subtraction

% bsxfun (legacy, pre-R2016b)
C = bsxfun(@plus, A, b);         % same as A + b
20

셀 배열과 구조체

셀 배열

셀 배열은 혼합 타입을 저장합니다. 내용에 접근하려면 {}를(셀 래퍼 제거), 하위 셀을 가져오려면 ()를 사용하세요. cellfun이 각 셀에 함수를 적용합니다 — 결과가 이질적이면 'UniformOutput', false를 전달하세요. 셀 배열은 다른 길이의 문자열을 저장하는 표준 방법입니다(문자열 배열 이전).

matlab
% heterogeneous container
C = {'hello', 42, [1 2 3], magic(3)};

% access
C{1}                             % 'hello' (contents)
C(1)                             % {1x1 cell} (cell)
C{4}(2, 2)                       % access inside

% build dynamically
C = {};
for k = 1:5
  C{k} = rand(k);
end

% multi-element
[a, b, c] = C{1:3};              % unpack
C{1:3}                           % comma-separated list

% cellfun
nums = {1, 2, 3, 4};
squared = cellfun(@(x) x^2, nums);
lengths = cellfun(@length, C);

% convert
cell([1 2 3])                    % {1, 2, 3}
cell2mat({1 2; 3 4})             % [1 2; 3 4]
mat2cell(magic(4), [2 2], [2 2]) % 2x2 cell of blocks

구조체 배열

구조체는 임의 타입의 이름이 있는 필드를 그룹화합니다. 구조체 배열은 여러 레코드를 저장합니다 — {arr.field}가 모든 요소에서 필드를 셀로, [arr.field]가 정규 배열로(호환되면) 모읍니다. 중첩 필드는 점 체이닝을 사용합니다. fieldnames가 필드를 나열하고; rmfield가 필드 없는 복사본을 반환합니다.

matlab
% scalar struct
s.name = 'Alice';
s.age = 30;
s.scores = [90 85 92];

% struct constructor
s = struct('name', 'Bob', 'age', 25, 'scores', {[80 70]});

% struct array
students(1).name = 'Alice';
students(1).age = 30;
students(2).name = 'Bob';
students(2).age = 25;

% access across array
names = {students.name};         % all names (cell)
ages = [students.age];           % all ages (vector)

% nested
s.course.code = 'CS101';
s.course.credits = 3;
s.course.instructor.name = 'Dr. Smith';

% field operations
fieldnames(s)                    % list fields
isfield(s, 'age')                % check field
rmfield(s, 'age')                % remove field
orderfields(s)                   % sort fields

테이블(표 형식 데이터)

테이블(R2013b+)은 표 형식 데이터를 저장하는 현대적 방법입니다 — pandas의 DataFrame 같습니다. 이름(T.Age)이나 인덱스(T.(2))로 열에 접근합니다. sortrows가 하나 이상의 열로 정렬합니다. readtable/writetable이 CSV, Excel 등을 처리합니다. summary가 열별 통계를 줍니다. 이질적 데이터에는 원시 행렬보다 테이블을 선호하세요.

matlab
% create table
Names = {'Alice'; 'Bob'; 'Carol'};
Age = [30; 25; 42];
Score = [90; 80; 95];
T = table(Names, Age, Score);

% access
T.Age                            % column as vector
T.(2)                            % column by index
T{1, 2}                          % row 1, col 2 (cell-style)
T(1:2, :)                        % first 2 rows

% add/remove columns
T.Grade = {'A'; 'B'; 'A'};
T.Grade = [];                    % remove column

% filtering
T(T.Age > 26, :)                 % rows where Age > 26
find(T.Age > 26);

% sorting
T = sortrows(T, 'Age');
T = sortrows(T, {'Age', 'Score'}, 'descend');

% summary
summary(T)
T.Properties.VariableNames

% read/write
T = readtable('data.csv');
writetable(T, 'out.csv')

타임테이블

타임테이블(R2016b+)은 행 타임스탬프가 있는 테이블입니다. retime이 리샘플링/집계합니다(예: 'hourly', 'daily', 또는 사용자 정의 TimeStep). synchronize가 여러 타임테이블을 공통 시간 벡터로 정렬합니다. lag/lead가 열을 이동합니다. 행렬에서 시간 인덱스를 수동으로 관리하는 것보다 훨씬 깔끔합니다.

matlab
% create timetable with timestamps
Time = datetime(2024, 1, 1) + hours(0:23)';
Temp = 20 + 5 * randn(24, 1);
TT = timetable(Time, Temp);

% indexing by time
TT.timerange(datetime(2024,1,1,6,0,0), datetime(2024,1,1,12,0,0))
TT(datetime(2024,1,1,10,0,0), :) % row at specific time
TT('2024-01-01 10:00:00', :)

% resample / synchronize
TT_30min = retime(TT, 'regular', 'mean', 'TimeStep', minutes(30));
TT_hourly = retime(TT, 'hourly', 'mean');

% aggregate
TT_daily = retime(TT, 'daily', @mean);
TT_daily_max = retime(TT, 'daily', 'max');

% combine timetables
TT2 = synchronize(TT1, TT2, 'union');

% lagging
TT.PrevTemp = lag(TT.Temp, 1);

맵(사전)

containers.Map은 레거시 해시 맵입니다 — 모든 MATLAB 버전에서 작동하지만 더 느리고 타입이 없습니다. dictionary(R2022b+)는 현대적 대체품입니다: 타입이 있고, 더 빠르고, 벡터화 조회를 지원합니다. 구조체 배열이나 셀을 검색하는 대신 O(1) 키 조회가 필요할 때 맵을 사용하세요.

matlab
% containers.Map (pre-R2022b)
m = containers.Map;
m('apple') = 1;
m('banana') = 2;
m('cherry') = 3;

% access
m('apple')                       % 1
m.Keys                           % {'apple', 'banana', 'cherry'}
m.Values                         % [1, 2, 3]
isKey(m, 'apple')                % true
remove(m, 'banana');

% iterate
keys = m.keys;
for k = 1:length(keys)
  fprintf('%s -> %d\n', keys{k}, m(keys{k}));
end

% R2022b+ dictionary (faster, typed)
d = dictionary({'apple', 'banana'}, [1, 2]);
d('cherry') = 3;
d('apple')                        % 1
keys(d); values(d)
21

최적화

fmincon 제약 최적화

fmincon은 제약 비선형 최소화의 핵심 도구입니다. nonlcon 함수는 c <= 0(부등식)과 ceq = 0(등식)인 [c, ceq]를 반환해야 합니다. deal은 익명 함수에서 여러 출력을 반환하는 깔끔한 방법입니다. 문제 타입에 따라 Algorithm을 설정하세요: 'interior-point'(일반), 'sqp'(소/중형, 종종 더 빠름).

matlab
% minimize objective with constraints
% min f(x) s.t. A*x <= b, Aeq*x = beq, lb <= x <= ub, c(x) <= 0, ceq(x) = 0

fun = @(x) (x(1) - 2)^2 + (x(2) - 3)^2;

% linear inequality: x1 + x2 <= 4
A = [1 1]; b = 4;
% linear equality: x1 - x2 = 0
Aeq = [1 -1]; beq = 0;
% bounds
lb = [0 0]; ub = [5 5];
% nonlinear: x1^2 + x2^2 >= 1 (so -(x1^2 + x2^2 - 1) <= 0)
nonlcon = @(x) deal(-(x(1)^2 + x(2)^2 - 1), []);

x0 = [1 1];
[x, fval, exitflag, output] = fmincon(fun, x0, A, b, Aeq, beq, lb, ub, nonlcon);

% options
opts = optimoptions('fmincon', 'Display', 'iter', ...
                    'Algorithm', 'interior-point');
[x, fval] = fmincon(fun, x0, A, b, Aeq, beq, lb, ub, nonlcon, opts);

fminunc 비제약

fminunc는 비제약 비선형 함수를 최소화합니다. 기울기 제공(SpecifyObjectiveGradient 통해)이 속도와 정확도를 크게 향상합니다. 기본 BFGS 헤시안 근사는 부드러운 문제에 잘 작동하고; 큰 문제에는 'lbfgs'가 메모리를 제한합니다. exitflag(>0 = 수렴)와 firstorderopt(아주 작아야 함)를 확인하세요.

matlab
% unconstrained minimization
fun = @(x) 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2;  % Rosenbrock

x0 = [-1.2 1];
[x, fval, flag, out] = fminunc(fun, x0);

% with gradient (faster, more accurate)
syms x1 x2
f = 100*(x2 - x1^2)^2 + (1 - x1)^2;
grad = gradient(f, [x1, x2]);
fun_grad = matlabFunction(f, grad, 'Vars', {x1, x2});

opts = optimoptions('fminunc', 'SpecifyObjectiveGradient', true, ...
                    'Display', 'iter');
[x, fval] = fminunc(@(x) fun_grad(x(1), x(2)), x0, opts);

% check optimality
disp(out.firstorderopt)           % should be near 0

% Hessian option
opts.Hessian = 'bfgs';            % quasi-Newton (default)
opts.Hessian = 'lbfgs';           % for large sparse problems

linprog 선형 계획

linprog는 선형 계획을 풉니다. 정수/바이너리 변수에는 intlinprog를(더 이상 사용되지 않는 bintprog 대체) 사용하세요. intcon이 어떤 변수가 정수 제약인지 나열합니다. 바이너리를 위해 lb=0, ub=1을 설정하세요. dual-simplex 알고리즘이 기본값이고 대부분의 문제에 가장 빠릅니다.

matlab
% min f'*x s.t. A*x <= b, Aeq*x = beq, lb <= x <= ub

% example: min -x1 - 2*x2
%   s.t.  x1 + x2 <= 4
%          x1 + 3*x2 <= 6
%          x1, x2 >= 0
f = [-1; -2];
A = [1 1; 1 3];
b = [4; 6];
lb = [0; 0];

opts = optimoptions('linprog', 'Display', 'iter');
[x, fval, exitflag, output] = linprog(f, A, b, [], [], lb, [], opts);

% integer programming (intlinprog)
intcon = 1:2;                     % variables 1 and 2 are integers
[x, fval] = intlinprog(f, intcon, A, b, [], [], lb, []);

% binary variables: set lb=0, ub=1, and add to intcon
lb = [0; 0]; ub = [1; 1];
[x, fval] = intlinprog(f, intcon, A, b, [], [], lb, ub);

lsqcurvefit과 곡선 피팅

lsqcurvefit은 최소제곱으로 파라메트릭 모델을 데이터에 피팅합니다. polyfit은 다항식을 위한 쉬운 선택입니다. R²(결정 계수)는 수동으로 계산하세요: 1 - SSE/SST. Levenberg-Marquardt 알고리즘은 비제약 문제에 좋고; trust-region-reflective는 범위를 처리합니다.

matlab
% fit y = a*exp(b*x) to data
xdata = linspace(0, 5, 50)';
ydata = 2.5 * exp(-0.7 * xdata) + 0.05 * randn(50, 1);

model = @(p, x) p(1) * exp(p(2) * x);

x0 = [1, -1];
[params, resnorm, residual, exitflag] = lsqcurvefit(model, x0, xdata, ydata);

% with bounds
lb = [0, -5]; ub = [10, 0];
[params, resnorm] = lsqcurvefit(model, x0, xdata, ydata, lb, ub);

% polyfit for polynomials
p = polyfit(xdata, ydata, 3);     % cubic
yfit = polyval(p, xdata);

% fit with custom output
opts = optimoptions('lsqcurvefit', 'Display', 'off', ...
                    'Algorithm', 'levenberg-marquardt');
[params, resnorm] = lsqcurvefit(model, x0, xdata, ydata, [], [], opts);

% goodness of fit
sse = sum((ydata - model(params, xdata)).^2);
sst = sum((ydata - mean(ydata)).^2);
r2 = 1 - sse / sst;

전역 최적화

전역 최적화 도구(Global Optimization Toolbox)는 국소 솔버가 갇히는 비볼록 문제에 도움을 줍니다. MultiStart는 많은 무작위 시작에서 국소 솔버를 실행합니다. GlobalSearch는 더 똑똑합니다 — 유망한 시작을 필터링합니다. ga(유전 알고리즘)와 simulannealbnd는 도함수가 없습니다. patternsearch는 비부드러운 문제에 좋습니다.

matlab
% MultiStart: run local solver from many points
fun = @(x) x(1)^2 + x(2)^2 + 10*sin(x(1)) + 10*sin(x(2));
ms = MultiStart('Display', 'iter');
opts = optimoptions('fmincon', 'Algorithm', 'interior-point');
problem = createOptimProblem('fmincon', 'objective', fun, ...
                            'x0', [0 0], 'lb', [-5 -5], 'ub', [5 5]);
[x, fval] = run(ms, problem, 50);  % 50 starting points

% GlobalSearch: smarter, fewer starts
gs = GlobalSearch;
[x, fval] = run(gs, problem);

% ga (genetic algorithm)
[x, fval] = ga(fun, 2, [], [], [], [], [-5 -5], [5 5]);

% simulannealbnd (simulated annealing)
[x, fval] = simulannealbnd(fun, [0 0], [-5 -5], [5 5]);

% patternsearch
[x, fval] = patternsearch(fun, [0 0]);
22

이미지 처리

이미지 읽기와 표시

imread는 대부분의 이미지 형식에 uint8 배열을 반환합니다. rgb2gray가 RGB를 회색조로 변환합니다. im2double는 [0, 1]로 스케일합니다 — 부동소수점 처리 전에 double()이 아닌 이것을 사용하세요. imshow는 double 이미지를 자동 스케일합니다: [0, 1]이 예상 범위입니다. imwrite가 품질/압축 옵션을 지원합니다.

matlab
% read and display
img = imread('photo.jpg');
imshow(img);

% info
size(img)                         % rows x cols x channels
class(img)                        % usually uint8
imfinfo('photo.jpg')              % metadata

% convert types
gray = rgb2gray(img);             % RGB -> gray
img_double = im2double(img);      % uint8 [0,255] -> double [0,1]
img_uint8 = im2uint8(img_double);

% write
imwrite(gray, 'gray.png');
imwrite(img, 'compressed.jpg', 'Quality', 80);

% display multiple
figure;
subplot(1, 2, 1); imshow(img); title('Original');
subplot(1, 2, 2); imshow(gray); title('Grayscale');

% pixel info
impixelinfo;                      % interactive pixel values
img(100, 200, :)                  % pixel at (row, col)

필터링과 합성곱

imgaussfilt는 현대적 가우시안 블러입니다(fspecial('gaussian') + imfilter 대체). medfilt2는 소금-후추 잡음에 올바른 선택입니다(평균 필터는 그냥 번지게 합니다). fspecial이 일반 커널(sobel, prewitt, laplacian, gaussian, disk, motion)을 생성합니다. imfilter는 기본적으로 상관을 수행합니다 — 참 합성곱을 위해 'conv'를 전달하세요.

matlab
img = imread('cameraman.tif');
img = im2double(img);

% Gaussian blur
blurred = imgaussfilt(img, 2);    % sigma = 2
blurred = imgaussfilt(img, 2, 'FilterSize', 7);

% median filter (great for salt-and-pepper noise)
noisy = imnoise(img, 'salt & pepper', 0.05);
denoised = medfilt2(noisy, [3 3]);

% custom kernel
h = fspecial('sobel');            % edge detection
edges = imfilter(img, h);
h = fspecial('laplacian', 0);
sharpened = img - imfilter(img, h);

% 2D convolution vs correlation
out_conv = imfilter(img, h, 'conv');
out_corr = imfilter(img, h, 'corr');  % default

% unsharp masking
sharp = imsharpen(img, 'Amount', 1.5, 'Radius', 2);

형태학적 연산

형태학적 연산은 이진 이미지에 작동합니다. erode는 객체를 축소하고; dilate는 키웁니다. open(침식 후 팽창)은 작은 잡음을 제거하고; close(팽창 후 침식)는 작은 틈을 채웁니다. strel이 구조 요소를 생성합니다 — disk/square/line/octagon. bwareaopen은 작은 객체를 제거하고; imfill은 구멍을 채우고; bwperim는 경계를 추출합니다.

matlab
bw = imread('text.png');
bw = imbinarize(bw);              % grayscale -> binary

% basic ops
eroded = imerode(bw, strel('square', 3));
dilated = imdilate(bw, strel('disk', 2));
opened = imopen(bw, strel('square', 5));
closed = imclose(bw, strel('square', 5));

% structuring elements
se = strel('square', 3);
se = strel('disk', 5);
se = strel('line', 10, 45);       % length 10, angle 45 deg
se = strel('octagon', 3);

% remove small objects
clean = bwareaopen(bw, 50);       % remove <50 pixels

% skeleton
skel = bwmorph(bw, 'skel', Inf);

% fill holes
filled = imfill(bw, 'holes');

% boundary
boundary = bwperim(bw);

에지 검출과 분할

edge에 'canny'가 가장 강건한 에지 검출기입니다([low high] 임계값과 sigma 지정). imbinarize에 'adaptive'는 불균일한 조명을 처리합니다. bwconncomp가 연결된 컴포넌트를 찾고; regionprops가 측정(Area, Centroid, BoundingBox 등)을 추출합니다. watershed는 닿아 있는 객체를 분리합니다 — 경계를 찾으려면 그래디언트에서 계산하세요.

matlab
img = imread('coins.png');
img = im2double(img);

% edges
edges_sobel = edge(img, 'sobel');
edges_canny = edge(img, 'canny', [0.1 0.2], 1.5);
edges_prewitt = edge(img, 'prewitt');

% thresholding
bw = imbinarize(img);
bw_otsu = imbinarize(img, 'adaptive');  % local threshold

% connected components
cc = bwconncomp(bw);
stats = regionprops(cc, 'Area', 'Centroid', 'BoundingBox');
areas = [stats.Area];
[~, idx] = sort(areas, 'descend');
biggest = stats(idx(1));

% watershed segmentation
grad = imgradient(img);
L = watershed(grad);
L(L == 0) = NaN;
imshow(img); hold on; imshow(L, []);

색과 변환

rgb2hsv, rgb2lab가 색 공간을 변환합니다 — HSV는 색 선택에 직관적이고; L*a*b*는 휘도를 색에서 분리합니다(색 차이에 좋음). fft2 + fftshift가 필터링을 위해 스펙트럼을 중심에 놓습니다. imresize/imrotate/imcrop은 기하학적 연산입니다 — 'bilinear'(기본값)가 보통 가장 좋고; 'nearest'는 가장 빠르지만 블록 현상이 있습니다.

matlab
img = imread('peppers.png');

% color space conversion
hsv = rgb2hsv(img);
lab = rgb2lab(img);
gray = rgb2gray(img);
rgb = hsv2rgb(hsv);

% extract channels
R = img(:, :, 1);
G = img(:, :, 2);
B = img(:, :, 3);

% Fourier transform
f = fft2(double(gray));
f = fftshift(f);                  % center zero freq
mag = log(1 + abs(f));
imshow(mag, []);

% inverse
f_filtered = f;
f_filtered(abs(f) < 100) = 0;    % low-pass filter
filtered = real(ifft2(ifftshift(f_filtered)));
imshow(filtered, []);

% resize, rotate
small = imresize(img, 0.5);
rotated = imrotate(img, 45, 'bilinear', 'crop');
cropped = imcrop(img, [50 50 200 150]);  % [x y w h]
23

GUI/App Designer

App Designer 기초

App Designer(R2016a+)는 GUIDE를 대체하는 현대적 GUI 도구입니다. 컴포넌트는 app.<Name>으로 접근합니다. 콜백은 (app, event)를 받습니다. 사용자 정의 속성(Code View에서)이 콜백 간 상태를 공유합니다. .mlapp(바이너리)로 저장하거나 .m으로 내보냅니다. 명령 창에서 앱 이름을 입력하여 실행하세요.

matlab
% Open App Designer:
%   >> appdesigner
% Drag components from the left, set properties on the right.

% Callback structure (auto-generated):
function ButtonPushed(app, event)
    x = linspace(0, 2*pi, 100);
    plot(app.UIAxes, x, sin(x));
    app.ResultEditField.Value = 'Plot done';
end

% Access components via app.<ComponentName>
%   app.UIAxes, app.Button, app.EditField, app.Slider, ...

% Property panel: add custom properties
properties (Access = private)
    data;                          % shared between callbacks
end

% Startup callback:
function startupFcn(app)
    app.data = rand(10);
    app.Slider.Value = 50;
end

% Save as .mlapp, run with:
%   >> myApp  (if named myApp.mlapp)
% Or export to a standalone .m file.

uifigure를 사용한 프로그래밍 방식 UI

uifigure(R2016b+)는 현대적 프로그래밍 방식 UI 프레임워크입니다 — figure가 지원하지 않는 현대적 위젯(gauge, knob, switch, tree)을 지원합니다. 익명 함수 @(src, event) ...를 사용해 *Fcn 속성으로 콜백을 설정하세요. uiwait가 그림이 닫힐 때까지 차단하고; uiresume이 해제합니다.

matlab
% modern uifigure (R2016b+) — preferred
fig = uifigure('Name', 'My App', 'Position', [100 100 600 400]);

ax = uiaxes(fig, 'Position', [200 100 350 250]);
plot(ax, 1:10);

btn = uibutton(fig, 'Text', 'Plot', 'Position', [50 100 100 30]);
btn.ButtonPushedFcn = @(~,~) plot(ax, rand(1, 10));

slider = uislider(fig, 'Position', [50 200 100 3]);
slider.ValueChangedFcn = @(s,~) disp(s.Value);

% dropdown
dd = uidropdown(fig, 'Items', {'a', 'b', 'c'}, 'Position', [50 250 100 30]);
dd.ValueChangedFcn = @(s,~) fprintf('Selected: %s\n', s.Value);

% list box
lb = uilistbox(fig, 'Items', {'one', 'two', 'three'}, ...
               'Multiselect', 'on', 'Position', [50 50 100 80]);

% wait for user to close
uiwait(fig);

일반 UI 컴포넌트

현대 UI 컴포넌트: uieditfield(텍스트 또는 숫자), uibuttongroup(라디오 버튼 관리), uicheckbox, uitable(테이블에 바인딩), uitabgroup/uitab(탭). 모두 첫 번째 인자로 parent를 받고 속성을 위해 Name-Value 쌍을 사용합니다. 콜백은 사용자 상호작용 시 발생하며, source 인자를 통해 새 값을 접근합니다.

matlab
fig = uifigure;

% label
lbl = uilabel(fig, 'Text', 'Enter value:', 'Position', [20 200 100 22]);

% edit field
ef = uieditfield(fig, 'numeric', 'Value', 42, 'Position', [130 200 100 22]);
ef.ValueChangedFcn = @(s,~) fprintf('New: %g\n', s.Value);

% button group with radio buttons
bg = uibuttongroup(fig, 'Title', 'Mode', 'Position', [20 100 200 80]);
r1 = uiradiobutton(bg, 'Text', 'A', 'Position', [10 40 100 22]);
r2 = uiradiobutton(bg, 'Text', 'B', 'Position', [10 10 100 22]);
r1.Value = true;

% check box
cb = uicheckbox(fig, 'Text', 'Enable', 'Position', [20 50 100 22]);

% table
tdata = table({'A'; 'B'}, [1; 2], 'VariableNames', {'Name', 'Value'});
uit = uitable(fig, 'Data', tdata, 'Position', [250 50 200 150]);

% tab group
tg = uitabgroup(fig);
t1 = uitab(tg, 'Title', 'Tab 1');
t2 = uitab(tg, 'Title', 'Tab 2');
plot(uiaxes(t1), 1:10);

대화상자와 프롬프트

inputdlg는 텍스트 입력을 수집; questdlg는 yes/no/cancel; listdlg는 선택; uigetfile/uiputfile는 파일 선택기; msgbox/errordlg/warndlg는 알림. fullfile은 이식 가능하게 경로를 결합합니다(문자열 연결보다 낫습니다). 사용자가 취소하지 않았는지 항상 확인하세요(빈 반환 또는 ok == false).

matlab
% input dialog
answer = inputdlg({'Name:', 'Age:'}, 'User Info', [1 50; 1 10]);
if ~isempty(answer)
    name = answer{1};
    age = str2double(answer{2});
end

% question dialog
btn = questdlg('Save changes?', 'Confirm', 'Yes', 'No', 'Cancel', 'Yes');
switch btn
    case 'Yes', save_data();
    case 'No',  % discard
    case 'Cancel', return;
end

% list dialog
[sel, ok] = listdlg('PromptString', 'Select items:', ...
                    'ListString', {'Apple', 'Banana', 'Cherry'}, ...
                    'SelectionMode', 'multiple');

% file dialogs
[file, path] = uigetfile('*.csv', 'Select CSV');
[file, path] = uiputfile('*.mat', 'Save as');
fullpath = fullfile(path, file);

% message dialog
msgbox('Done!', 'Info', 'help');
errordlg('Something went wrong', 'Error');
warndlg('Check this', 'Warning');

공유와 배포

공유의 경우: .mlapp 파일은 MATLAB이 필요; 독립형 앱(MATLAB Compiler를 통해)은 MATLAB 없이 실행되지만 무료 MATLAB Runtime이 필요; 웹 앱은 MATLAB Web App Server를 통해 브라우저에서 실행됩니다. .m으로 내보내면 읽을 수 있는 소스 코드를 얻습니다. Add-Ons를 통해 배포용으로 툴박스로 패키징하세요.

matlab
% Run as standalone app
%   1. In App Designer: Designer Tab > App Store Details > Save as .mlapp
%   2. Share the .mlapp file — others open it in MATLAB

% Create standalone app (requires MATLAB Compiler)
%   >> mcr.build('myApp.mlapp')        % R2024a+
%   or
%   >> deploytool                       % legacy

% Web App (requires MATLAB Web App Server)
%   >> compiler.build.webApp('myApp.mlapp')

% Export to code (readable .m)
%   In App Designer: Designer Tab > Export > Export to .m file

% Pack as toolbox (for sharing with colleagues)
%   >> matlab.addons.toolbox.packageToolbox('myApp.prj)

% Tips:
%   - Use try/catch in callbacks to avoid silent failures
%   - Set app.UIFigure.Name to identify your app
%   - Test on a clean MATLAB session before deploying
24

파일 I/O 고급

저수준 파일 I/O

fopen은 실패 시 -1을 반환 — 항상 확인하세요. fgetl은 줄바꿈 없이 한 줄을 읽고; fgets는 줄바꿈을 유지합니다. fscanf는 형식화된 데이터를 읽고; fread는 바이너리를 읽습니다. fseek/ftell로 탐색합니다. 완료 시 항상 fclose하세요(안전을 위해 onCleanup 사용: c = onCleanup(@() fclose(fid));).

matlab
fid = fopen('data.txt', 'r');   % r, w, a, r+, w+
if fid == -1; error('Cannot open file'); end

% read line by line
while ~feof(fid)
  line = fgetl(fid);              % without newline
  fprintf('%s\n', line);
end

% formatted read
% data.txt: "Alice 30 90.5"
A = fscanf(fid, '%s %d %f', [3 1]);

% formatted write
fprintf(fid, '%s, %d, %.2f\n', 'Bob', 25, 85.3);

% binary I/O
data = fread(fid, [10 5], 'double');  % 10x5 doubles
fwrite(fid, data, 'double');

% position
fseek(fid, 0, 'bof');             % beginning
fseek(fid, 0, 'eof');             % end
pos = ftell(fid);

fclose(fid);                      % ALWAYS close

혼합 데이터를 위한 textscan

textscan은 fscanf보다 유연합니다 — 혼합 타입, 사용자 정의 구분자를 처리하고 열의 cell 배열을 반환합니다. 'TreatAsEmpty'는 자리표시자를 NaN으로 변환합니다. 'CollectOutput'은 같은 타입의 열을 하나의 배열로 그룹화합니다. fileread는 전체 파일을 문자열로 읽어 들입니다 — 작은 파일이나 정규식 처리에 편리합니다.

matlab
fid = fopen('data.csv', 'r');

% skip header line
header = fgetl(fid);

% parse remaining
% Format: Alice,30,90.5,B+
C = textscan(fid, '%s %d %f %s', ...
             'Delimiter', ',', ...
             'MultipleDelimsAsOne', true, ...
             'TreatAsEmpty', {'NA', 'N/A'}, ...
             'HeaderLines', 0);
fclose(fid);

names = C{1}; ages = C{2}; scores = C{3}; grades = C{4};

% alternative: read whole file at once
str = fileread('data.txt');

% from string
C = textscan('1 2 3\n4 5 6', '%d %d %d');
% C{1} = [1; 4], C{2} = [2; 5], C{3} = [3; 6]

% collectoutput (group columns of same type)
C = textscan(fid, '%s %d %d %f', 'CollectOutput', true);
% C{2} = [ages, more_ints] as one matrix

MAT 파일과 save/load

save/load와 .mat 파일은 변수 타입과 구조를 보존합니다. -v7.3은 2GB 이상 파일을 지원합니다(현대 MATLAB의 기본값). -append는 재작성 없이 변수를 추가합니다. 큰 파일의 경우 이름으로 필요한 것만 로드하세요. 텍스트 내보내기에는 -ascii(제한적) 또는 더 많은 제어를 위해 writematrix/writetable을 사용하세요.

matlab
A = magic(5);
B = struct('name', 'Alice', 'age', 30);
C = rand(100);

% save variables
save('data.mat', 'A', 'B', 'C');
save('data.mat', 'A', 'B', '-v7.3');  % large files > 2GB
save('data.mat', '-append', 'C');     % add to existing

% load
loaded = load('data.mat');       % struct with variables
loaded.A
loaded.B.age

% or load into workspace
load('data.mat');                % A, B, C now in workspace

% partial load (huge files)
info = whos('-file', 'bigdata.mat');
loaded = load('bigdata.mat', 'A');  % only A

% save specific format
save('data.txt', 'A', '-ascii', '-double');
save('data.csv', 'A', '-ascii', '-delimiter', ',');

% compressed
save('data.mat', 'A', '-v7.3', '-nocompression');

HDF5와 과학 형식

HDF5는 대용량 수치 데이터셋의 표준입니다 — 청킹, 압축, 확장 가능한 차원을 지원합니다. start/count와 함께 h5read를 사용하면 전체 파일을 로드하지 않고 슬라이스를 읽을 수 있습니다. NetCDF는 기후/해양 과학에서 흔히 사용; FITS는 천문학에서 사용됩니다. MATLAB은 TIFF, DICOM, 오디오, 비디오 형식도 기본 지원합니다.

matlab
% HDF5 (great for large scientific datasets)
% write
h5create('data.h5', '/dataset1', [100 50 20]);
data = rand(100, 50, 20);
h5write('data.h5', '/dataset1', data);

% read
info = h5info('data.h5');
data = h5read('data.h5', '/dataset1');
partial = h5read('data.h5', '/dataset1', [1 1 1], [10 10 5]);

% append (extendable datasets)
h5create('data.h5', '/growable', [100 Inf], 'ChunkSize', [100 100]);
for k = 1:5
  h5write('data.h5', '/growable', rand(100, 100), [1 (k-1)*100+1]);
end

% NetCDF (climate/ocean data)
ncid = netcdf.open('data.nc', 'NC_NOWRITE');
varid = netcdf.inqVarID(ncid, 'temperature');
data = netcdf.getVar(ncid, varid);
netcdf.close(ncid);

% FITS (astronomy)
fitsdisp('image.fits');
data = fitsread('image.fits');

JSON과 XML

jsonencode/jsondecode(R2016b+)는 JSON을 기본 처리합니다. 구조체는 JSON 객체가 되고; cell 배열은 배열이 됩니다. XML의 경우, xmlread는 Java DOM 객체를 반환 — 탐색에 Java 메서드를 사용하세요. xmlwrite는 DOM을 파일로 다시 직렬화합니다. 복잡한 XML의 경우 타사 xml2struct 또는 DOM API를 직접 고려하세요.

matlab
% JSON (R2016b+)
data = struct('name', 'Alice', 'age', 30, 'scores', [90 80 85]);
txt = jsonencode(data, 'PrettyPrint', true);
disp(txt);

decoded = jsondecode(txt);
decoded.name                     % 'Alice'

% JSON with cell arrays for mixed types
data = struct('items', {{'apple', 42, [1 2 3]}});
txt = jsonencode(data);

% read JSON file
txt = fileread('config.json');
config = jsondecode(txt);

% XML
doc = xmlread('data.xml');
root = doc.getDocumentElement;
children = root.getChildNodes;
for k = 0:children.getLength - 1
  node = children.item(k);
  if node.getNodeType == doc.ELEMENT_NODE
    fprintf('%s: %s\n', node.getNodeName, char(node.getTextContent));
  end
end

% write XML
doc = com.mathworks.xml.XMLUtils.createDocument('root');
root = doc.getDocumentElement;
child = doc.createElement('item');
child.appendChild(doc.createTextNode('hello'));
root.appendChild(child);
xmlwrite('out.xml', doc);
25

병렬 컴퓨팅

parfor 루프

parfor는 워커 전체에 걸쳐 루프 반복을 병렬로 실행합니다. 반복은 독립적이어야 합니다. 변수는 분류됩니다: sliced(각 반복이 고유한 인덱스를 다룸), broadcast(읽기 전용), reduction(+나 * 같은 결합 연산으로 결합), temp(내부에서 생성). 분류는 허용되는 것을 결정합니다.

matlab
% requires Parallel Computing Toolbox
% start pool
pool = gcp('nocreate');
if isempty(pool), parpool; end

% parfor: parallel for loop
N = 1000;
results = zeros(1, N);
parfor k = 1:N
  results(k) = some_expensive_function(k);
end

% constraints:
%   - iterations must be independent (no order dependency)
%   - body cannot contain break/return
%   - variables classified as sliced, broadcast, reduction, temp

% reduction variables
total = 0;
parfor k = 1:N
  total = total + compute(k);
end

% sliced variables (independent indexing)
data = rand(N, 100);
out = zeros(N, 1);
parfor k = 1:N
  out(k) = mean(data(k, :));
end

spmd와 분산 배열

spmd는 모든 워커에서 같은 코드를 실행하며, labindex가 각각을 식별합니다. 워커가 통신하는 데이터 병렬 알고리즘에 사용하세요(예: MPI 스타일). 분산 배열은 큰 행렬을 워커에 분산 — 그 위의 연산은 분산 상태를 유지; gather()는 결과를 클라이언트로 가져옵니다. Composite은 워커별 값을 저장합니다.

matlab
% spmd: single program, multiple data
spmd
  % code runs on every worker
  % labindex: this worker's ID (1 to numlabs)
  % numlabs: total workers
  fprintf('Worker %d of %d\n', labindex, numlabs);

  % each worker computes a chunk
  local_data = rand(100, 1);
  local_sum = sum(local_data);
end

% combine results
total = sum([local_sum{:}]);

% distributed arrays (split across workers)
D = distributed.rand(10000, 10000);  % huge matrix
local_size = size(D, 'local')        % each worker's chunk
total_size = size(D)                  % logical total

% operations auto-distribute
S = D * D';
S_local = gather(S);                  % pull to client (if fits)

% Composite (cell-like, one per worker)
C = Composite();
spmd
  C{labindex} = magic(labindex + 1);
end
C{1}                              % access worker 1's value

gpuArray

gpuArray는 데이터를 GPU로 이동; gpuArray 위의 연산은 자동으로 GPU에서 실행됩니다. gather()는 데이터를 다시 가져옵니다. 요소별 및 행렬 곱셈 연산이 가장 큰 가속을 보고; 스칼라 또는 분기 코드는 그렇지 않습니다. gpuArray 위의 arrayfun은 CUDA를 작성하지 않고 GPU에서 사용자 정의 요소별 함수를 실행할 수 있게 합니다.

matlab
% requires GPU support (most NVIDIA GPUs)
% move data to GPU
A = gpuArray(rand(10000));
B = gpuArray(rand(10000));

% operations run on GPU
C = A * B;                        % still on GPU
D = sin(A) + cos(B);
E = sum(A, 1);

% bring back to CPU
C_cpu = gather(C);

% check GPU
gpuDevice                        % info about current GPU
gpuDeviceCount                   % number of available GPUs
gpuDevice(1)                     % select device 1

% element-wise ops are typically fastest on GPU
% matrix multiply also very fast (cuBLAS)

% custom kernels (PTX)
k = parallel.gpu.CUDAKernel('my_kernel.ptx', 'my_kernel.cu');
result = feval(k, A, B);

% arrayfun on GPU (element-wise custom functions)
f = @(x) x^2 + sin(x);
result = arrayfun(f, A);

batch와 job

batch는 백그라운드에서 함수나 스크립트를 실행 — MATLAB 세션을 차단하고 싶지 않은 긴 작업에 유용합니다. wait(job)은 완료될 때까지 차단; fetchOutputs는 결과를 검색합니다. 항상 delete(job)로 리소스를 해제하세요. 'Pool', N은 batch 함수 내부의 parfor에 N개의 추가 워커를 사용합니다.

matlab
% run a function in background
job = batch(@my_function, 0, {arg1, arg2});

% check status
job.State                        % 'queued', 'running', 'finished'
wait(job);                       % block until done

% get results
results = fetchOutputs(job);
delete(job);                     % clean up

% batch script
job = batch('my_script.m');

% with pool
job = batch(@my_func, 1, {x}, 'Pool', 4);  % 4 extra workers

% batch with attached files
job = batch(@my_func, 1, {x}, ...
            'AttachedFiles', {'data.mat', 'helper.m'}, ...
            'CurrentFolder', '/path/to/work');

% list jobs
jobs = findJob(pool);
for j = jobs
  fprintf('Job %d: %s\n', j.ID, j.State);
end

% parallel pool settings
parpool('local', 4);              % 4 workers
delete(gcp('nocreate'));          % shut down pool

성능 팁

배열을 미리 할당(zeros/ones) — 루프에서 배열을 키우는 것이 #1 MATLAB 성능 킬러입니다. 벡터화(sin(x)를 루프 대신) — 더 명확하고 종종 더 빠릅니다. JIT는 단순 루프를 빠르게 만들지만, 수학의 경우 벡터화가 여전히 이깁니다. profile viewer는 병목을 찾습니다. 큰 데이터에는 단정밀도를 사용; 진정한 핫스팟에는 MEX 파일을 작성하세요.

matlab
% 1. Preallocate arrays
% BAD
for k = 1:1000
  x(k) = k^2;                    % grows array each iteration
end

% GOOD
x = zeros(1, 1000);
for k = 1:1000
  x(k) = k^2;
end

% 2. Vectorize instead of looping
% BAD
for k = 1:length(x)
  y(k) = sin(x(k));
end

% GOOD
y = sin(x);                      % one vectorized call

% 3. Use JIT-friendly patterns
% simple loops are now fast (JIT), but vectorize for clarity

% 4. Profile to find bottlenecks
profile on;
my_function();
profile viewer;

% 5. Prefer single precision for huge data
A = rand(10000, 'single');       % half the memory

% 6. MEX for critical sections
% compile C code: mex my_func.c
26

객체 지향

클래스 정의

classdef를 <ClassName>.m이라는 파일에 저장하세요. 속성은 데이터를 보유; 메서드는 동작을 정의합니다. 생성자는 클래스 이름으로 명명되어야 하고 nargin==0을 처리해야 합니다(인자가 없을 때 호출). Dependent 속성은 get.X 메서드를 통해 접근 시 계산됩니다. disp는 표시를 재정의합니다. 정적 메서드는 obj를 받지 않습니다.

matlab
% file: Point.m
classdef Point
  properties
    x = 0
    y = 0
  end

  properties (Dependent)
    r                              % computed on access
  end

  methods
    function obj = Point(x, y)
      if nargin > 0
        obj.x = x;
        obj.y = y;
      end
    end

    function r = get.r(obj)
      r = sqrt(obj.x^2 + obj.y^2);
    end

    function obj = move(obj, dx, dy)
      obj.x = obj.x + dx;
      obj.y = obj.y + dy;
    end

    function disp(obj)
      fprintf('Point(%.2f, %.2f), r=%.2f\n', obj.x, obj.y, obj.r);
    end
  end

  methods (Static)
    function p = origin()
      p = Point(0, 0);
    end
  end
end

값 vs handle 클래스

값 클래스는 할당 시 복사(int나 struct처럼); handle 클래스는 참조로 전달(Java 객체처럼). 가변 객체(데이터베이스 연결, UI 컴포넌트)에는 handle을 사용하세요. 값 클래스는 불변 데이터에 더 간단하고 안전합니다. handle 클래스는 handle에서 상속하고 이벤트/리스너와 delete 소멸자를 지원합니다.

matlab
% Value class (default) — copied on assignment
classdef VPoint
  properties; x; end
  methods
    function obj = VPoint(x); obj.x = x; end
    function obj = setX(obj, x); obj.x = x; end
  end
end

p = VPoint(1);
p2 = p;                           % copy
p2 = setX(p2, 5);
disp(p.x)                         % still 1 (unchanged)

% Handle class — passed by reference
classdef HPoint < handle
  properties; x; end
  methods
    function obj = HPoint(x); obj.x = x; end
    function setX(obj, x); obj.x = x; end   % no return needed
  end
end

h = HPoint(1);
h2 = h;                           % same object
h2.setX(5);
disp(h.x)                         % 5 (shared)

% handle class features:
%   - events and listeners
%   - destructor (delete method)
%   - copy() method

상속과 다형성

<로 서브클래스를 만드세요. obj@SuperClass(args)로 슈퍼클래스 생성자를 호출하세요. 다형성은 자연스럽게 작동 — 기본 타입에서 메서드를 호출하면 올바른 재정의가 실행됩니다. MATLAB은 다중 상속을 지원(슈퍼클래스를 &로 구분)하지만, 하나만 구체 클래스일 수 있고; 나머지는 인터페이스여야 합니다.

matlab
% base class
classdef Animal
  properties; name; end
  methods
    function obj = Animal(name); obj.name = name; end
    function speak(obj)
      error('Abstract: subclass must override');
    end
    function describe(obj)
      fprintf('%s says: ', obj.name);
      obj.speak();
      fprintf('\n');
    end
  end
end

% subclass
classdef Dog < Animal
  methods
    function obj = Dog(name); obj = obj@Animal(name); end
    function speak(obj); fprintf('Woof'); end
  end
end

classdef Cat < Animal
  methods
    function obj = Cat(name); obj = obj@Animal(name); end
    function speak(obj); fprintf('Meow'); end
  end
end

% polymorphism
animals = {Dog('Rex'), Cat('Whiskers'), Dog('Buddy')};
for k = 1:length(animals)
  animals{k}.describe();
end

% multiple inheritance
classdef FlyingDog < Dog & IFlyable
  ...
end

이벤트와 리스너

이벤트는 handle 클래스가 필요합니다. events 블록에서 이벤트를 선언하세요. notify는 이벤트를 트리거; addlistener는 구독합니다. 리스너는 함수 또는 익명 함수 @(src, event)일 수 있습니다. 사용자 정의 이벤트 데이터는 event.EventData를 서브클래스화합니다. 리스너는 소스 객체가 삭제될 때 삭제됩니다(또는 명시적으로 삭제할 수 있습니다).

matlab
classdef Thermometer < handle
  properties
    temperature = 20
  end

  events
    temperatureChanged
    overheat
  end

  methods
    function set.temperature(obj, t)
      obj.temperature = t;
      notify(obj, 'temperatureChanged');
      if t > 100
        notify(obj, 'overheat');
      end
    end

    function obj = Thermometer()
      % add listener to own event
      addlistener(obj, 'overheat', @(s,e) disp('WARNING: too hot!'));
    end
  end
end

% usage
t = Thermometer();
lh = addlistener(t, 'temperatureChanged', @(s,e) ...
  fprintf('Now: %.1f\n', s.temperature));
lh2 = addlistener(t, 'overheat', @onOverheat);

t.temperature = 25;               % triggers temperatureChanged
t.temperature = 105;              % triggers both

% custom event data
classdef OverheatData < event.EventData
  properties; temp; end
end
% notify(obj, 'overheat', OverheatData(t));

열거형과 속성

열거형 클래스는 고정된 인스턴스를 정의 — 상태 기계, 옵션, 타입에 유용합니다. 각 enum 값은 속성을 통해 데이터를 전달할 수 있습니다. 속성 속성은 접근을 제어: SetAccess=private는 외부에서 읽기 전용으로 만들고; Constant는 컴파일 타임 상수; Hidden은 표시에서 숨기고; Access={?Class1, ?Class2}는 특정 클래스로 제한합니다.

matlab
% enumeration class
classdef Color
  enumeration
    Red [1 0 0]
    Green [0 1 0]
    Blue [0 0 1]
  end
  properties
    rgb
  end
  methods
    function obj = Color(rgb)
      obj.rgb = rgb;
    end
  end
end

c = Color.Red;
disp(c.rgb)                       % [1 0 0]

% switch on enum
switch c
  case Color.Red; disp('red');
  case Color.Green; disp('green');
end

% property attributes
classdef Account
  properties (SetAccess = private)
    balance = 0                   % readable outside, settable only inside
  end
  properties (Access = {?Account, ?Bank})
    internal_id                   % only Account and Bank classes
  end
  properties (Constant)
    PI = 3.14159                  % compile-time constant
  end
  properties (Hidden)
    cache                         % not shown by disp/struct
  end
end

Was this helpful?