Ch.3 §3.4 — The Complete Solution to Ax = b

특정해 + 영공간 = 완전해, 가해 조건, 4가지 랭크 경우

Ax=b의 완전해(complete solution)가 특정해(particular solution)와 영공간의 합으로 구성됨을 증명한다. 첨가 행렬 [A|b]로 가해 조건을 도출하고, 전랭크(full column/row rank) 각각의 해 구조를 이해한다. 랭크 r, m, n의 관계로 결정되는 네 가지 경우를 정리한다.

Mathematics
Linear Algebra
저자

Kwangmin Kim

공개

2026년 04월 09일

1 핵심 질문

§3.2에서 \(\mathbf{A}\mathbf{x} = \mathbf{0}\) 을 완전히 풀었다. 이제 우변이 \(\mathbf{0}\) 이 아닌 \(\mathbf{b}\) 인 경우다.

\(\mathbf{A}\mathbf{x} = \mathbf{b}\)모든 해를 어떻게 체계적으로 기술하는가?

답은 두 부분의 합이다: 특정해(particular solution) + 영공간(nullspace).

\[\mathbf{x} = \mathbf{x}_p + \mathbf{x}_n\]

\(\mathbf{x}_p\)\(\mathbf{A}\mathbf{x} = \mathbf{b}\) 를 만족하는 임의의 해 하나, \(\mathbf{x}_n\)\(\mathbf{A}\mathbf{x} = \mathbf{0}\) 의 임의의 해다.


2 완전해 구조 — 왜 xp + xn 인가

증명: 완전해 = 특정해 + 영공간

\(\mathbf{x}_p\)\(\mathbf{A}\mathbf{x}_p = \mathbf{b}\) 를 만족하고, \(\mathbf{x}_n\)\(\mathbf{A}\mathbf{x}_n = \mathbf{0}\) 를 만족한다면:

\[\mathbf{A}(\mathbf{x}_p + \mathbf{x}_n) = \mathbf{A}\mathbf{x}_p + \mathbf{A}\mathbf{x}_n = \mathbf{b} + \mathbf{0} = \mathbf{b}\]

따라서 \(\mathbf{x}_p + \mathbf{x}_n\)\(\mathbf{A}\mathbf{x} = \mathbf{b}\) 의 해다.

반대로: \(\mathbf{x}\)\(\mathbf{x}_p\) 가 모두 해라면, \(\mathbf{A}(\mathbf{x} - \mathbf{x}_p) = \mathbf{b} - \mathbf{b} = \mathbf{0}\), 즉 \(\mathbf{x} - \mathbf{x}_p \in N(\mathbf{A})\).

따라서 모든 해는 \(\mathbf{x}_p + (\text{영공간 벡터})\) 형태다. (Strang, 2016, Ch.3)

기하학적 직관: 해 집합은 원점에서 \(\mathbf{x}_p\) 만큼 이동한 “평행 이동된 영공간”이다. \(\mathbf{b} = \mathbf{0}\) 이면 해 집합 = 영공간 (원점 통과). \(\mathbf{b} \neq \mathbf{0}\) 이면 해 집합 = 영공간 + 이동량 \(\mathbf{x}_p\) (원점 불통과, 부분공간 아님).


3 첨가 행렬 [A|b]와 가해 조건

우변 \(\mathbf{b}\) 에도 같은 행 연산을 적용해야 한다. 이를 위해 첨가 행렬(augmented matrix) \([\mathbf{A}\ |\ \mathbf{b}]\) 를 소거한다.

예시: \(3 \times 4\) 행렬 \(\mathbf{A}\), \(\mathbf{b} = (1, 6, 7)^\top\)

\[[\mathbf{A}\ |\ \mathbf{b}] = \begin{bmatrix} 1 & 3 & 0 & 2 & 1 \\ 0 & 0 & 1 & 4 & 6 \\ 1 & 3 & 1 & 6 & 7 \end{bmatrix}\]

row3 \(-\) row1 \(-\) row2 를 수행하면:

\[[\mathbf{R}\ |\ \mathbf{d}] = \begin{bmatrix} 1 & 3 & 0 & 2 & 1 \\ 0 & 0 & 1 & 4 & 6 \\ 0 & 0 & 0 & 0 & 0 \end{bmatrix}\]

세 번째 행의 마지막 성분이 \(7 - 1 - 6 = 0\) 이므로 \(0 = 0\) 이다. 해가 존재한다.

만약 \(b_1 + b_2 \neq b_3\) 이었다면 세 번째 행이 \(0 = (\text{nonzero})\) 가 되어 해가 없다.

가해 조건 (Solvability Condition)

\(\mathbf{A}\mathbf{x} = \mathbf{b}\) 가 해를 가지려면, \(\mathbf{R}\) 에서 영행이 되는 행에 대응하는 \(\mathbf{d}\) 의 성분도 0이어야 한다.

\[\text{가해} \iff \mathbf{b} \in C(\mathbf{A}) \iff \mathbf{b} \text{ 가 } \mathbf{A}\text{의 열들의 선형결합}\]

직관: \(\mathbf{A}\) 의 행들 사이에 선형 의존 관계가 있으면, 같은 관계가 \(\mathbf{b}\) 에도 성립해야 한다. 예: 1행 + 2행 = 3행이면 반드시 \(b_1 + b_2 = b_3\) 이어야 일관성이 있다.


4 특정해 구하기: 자유 변수 = 0

\([\mathbf{R}\ |\ \mathbf{d}]\) 에서 특정해 \(\mathbf{x}_p\) 를 구하는 가장 쉬운 방법:

자유 변수를 모두 0으로 설정하고, 피벗 방정식에서 피벗 변수를 역대입으로 구한다.

위 예시에서 \(x_2 = x_4 = 0\) 으로 설정하면:

  • 2번째 방정식 \(x_3 + 4(0) = 6\)\(x_3 = 6\)
  • 1번째 방정식 \(x_1 + 3(0) + 2(0) = 1\)\(x_1 = 1\)

\[\mathbf{x}_p = \begin{bmatrix} 1 \\ 0 \\ 6 \\ 0 \end{bmatrix}\]

왜 자유 변수 = 0이 좋은가? \(\mathbf{R}\) 의 피벗 행에서 자유 변수 항이 사라지므로, 피벗 변수는 \(\mathbf{d}\) 의 해당 성분에서 바로 읽힌다. 계산이 가장 단순하다.


5 완전해 작성

영공간 특수해 \(\mathbf{s}_1 = (-3, 1, 0, 0)\), \(\mathbf{s}_2 = (-2, 0, -4, 1)\) 을 합치면 완전해:

\[\mathbf{x} = \mathbf{x}_p + \mathbf{x}_n = \underbrace{\begin{bmatrix} 1 \\ 0 \\ 6 \\ 0 \end{bmatrix}}_{\mathbf{x}_p} + x_2 \underbrace{\begin{bmatrix} -3 \\ 1 \\ 0 \\ 0 \end{bmatrix}}_{\mathbf{s}_1} + x_4 \underbrace{\begin{bmatrix} -2 \\ 0 \\ -4 \\ 1 \end{bmatrix}}_{\mathbf{s}_2}\]

\(x_2\)\(x_4\) 는 임의의 실수다.

핵심 구분:

  • \(\mathbf{x}_p\) 는 임의 상수를 곱하지 않는다 — 이것은 특정 점이다.
  • \(\mathbf{x}_n\) (특수해들)은 임의 상수를 곱한다 — 이것이 무한히 많은 해를 만든다.

6 기하학적 그림

x 공간 (R^4 를 단순화하여 2D로 표현)

         x_p + N(A)        : Ax = b 의 해 집합 (영공간에 평행한 평면/선)
             ↑
     xp .... xp + x_n .... (직선 또는 평면)
    /
   O ........... x_n ..... (원점에서의 영공간: Ax = 0 의 해)

\(\mathbf{x}_p + N(\mathbf{A})\) 는 영공간 \(N(\mathbf{A})\)평행이동(translate) 이다. 두 집합은 동일한 방향을 가지지만, \(\mathbf{x}_p\) 만큼 이동했다.


7 예시 1: 전열랭크 (Full Column Rank, r = n)

전열랭크 행렬은 세로로 길고 좁다 (\(m \geq n\)). 모든 열에 피벗이 있다.

\[\mathbf{A} = \begin{bmatrix} 1 & 1 \\ 1 & 2 \\ -2 & -3 \end{bmatrix}, \quad \mathbf{b} = \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix}\]

첨가 행렬을 소거하면:

\[[\mathbf{A}\ |\ \mathbf{b}] \rightarrow \begin{bmatrix} 1 & 0 & 2b_1 - b_2 \\ 0 & 1 & b_2 - b_1 \\ 0 & 0 & b_3 + b_1 + b_2 \end{bmatrix} = [\mathbf{R}\ |\ \mathbf{d}]\]

가해 조건: \(b_3 + b_1 + b_2 = 0\) (\(\mathbf{A}\) 의 행 합이 0이므로 \(\mathbf{b}\) 의 행 합도 0이어야 함)

해의 구조: 자유 변수 없음 (\(n - r = 2 - 2 = 0\)), 영공간 = \(\{\mathbf{0}\}\)

\[\mathbf{x} = \mathbf{x}_p + \mathbf{0} = \begin{bmatrix} 2b_1 - b_2 \\ b_2 - b_1 \end{bmatrix}\]

→ 해가 존재하면 유일하다.

전열랭크 행렬의 특성 (\(r = n\)):

성질 내용
피벗 열 모든 \(n\) 개 열이 피벗 열
자유 변수 없음
영공간 \(N(\mathbf{A}) = \{\mathbf{0}\}\)
해의 수 0개 또는 1개
\(\mathbf{R}\) 형태 \(\mathbf{R} = \begin{bmatrix} \mathbf{I}_n \\ \mathbf{0} \end{bmatrix}\)

8 예시 2: 전행랭크 (Full Row Rank, r = m)

전행랭크 행렬은 가로로 짧고 넓다 (\(m \leq n\)). 모든 행에 피벗이 있다.

\[\mathbf{A} = \begin{bmatrix} 1 & 1 & 1 \\ 1 & 2 & -1 \end{bmatrix}, \quad \mathbf{b} = \begin{bmatrix} 3 \\ 4 \end{bmatrix}\]

소거:

\[\begin{bmatrix} 1 & 1 & 1 & 3 \\ 1 & 2 & -1 & 4 \end{bmatrix} \rightarrow \begin{bmatrix} 1 & 0 & 3 & 2 \\ 0 & 1 & -2 & 1 \end{bmatrix} = [\mathbf{R}\ |\ \mathbf{d}]\]

가해 조건: 영행이 없으므로 조건 없음. \(\mathbf{A}\mathbf{x} = \mathbf{b}\)어떤 \(\mathbf{b}\) 에 대해서도 반드시 해를 가진다.

특정해: \(x_3 = 0\) 으로 설정 → \(\mathbf{x}_p = (2, 1, 0)^\top\)

특수해: \(x_3 = 1\) 로 설정 → \(\mathbf{s} = (-3, 2, 1)^\top\)

\[\mathbf{x} = \begin{bmatrix} 2 \\ 1 \\ 0 \end{bmatrix} + x_3 \begin{bmatrix} -3 \\ 2 \\ 1 \end{bmatrix}\]

기하학적으로 이것은 \(\mathbb{R}^3\)직선이다 (특정 점 + 한 방향으로의 이동).

전행랭크 행렬의 특성 (\(r = m\)):

성질 내용
피벗 행 모든 \(m\) 개 행이 피벗 행
\(\mathbf{R}\) 의 영행 없음
가해 조건 항상 성립 (\(C(\mathbf{A}) = \mathbb{R}^m\))
해의 수 항상 무한히 많음 (\(n - r = n - m\) 개의 자유 변수)
\(\mathbf{R}\) 형태 \(\mathbf{R} = [\mathbf{I}_m \ \ \mathbf{F}]\)

9 랭크에 따른 네 가지 경우

\(m \times n\) 행렬의 랭크 \(r\)\(m\), \(n\) 과 어떤 관계인지에 따라 해의 구조가 완전히 결정된다.

경우 조건 \(\mathbf{R}\) 형태 \(\mathbf{A}\mathbf{x} = \mathbf{b}\) 의 해
1 \(r = m = n\) (정사각 가역) \(\mathbf{I}\) 항상 유일해
2 \(r = m < n\) (가로 행렬) \([\mathbf{I}\ \mathbf{F}]\) 항상 \(\infty\) 개의 해
3 \(r = n < m\) (세로 행렬) \(\begin{bmatrix}\mathbf{I}\\\mathbf{0}\end{bmatrix}\) 해 없음 또는 유일해
4 \(r < m\), \(r < n\) (일반 경우) \(\begin{bmatrix}\mathbf{I}&\mathbf{F}\\\mathbf{0}&\mathbf{0}\end{bmatrix}\) 해 없음 또는 \(\infty\)
  • 경우 1, 2 (행 전랭크 \(r = m\)): \(C(\mathbf{A}) = \mathbb{R}^m\) → 임의의 \(\mathbf{b}\) 에 대해 해 존재
  • 경우 1, 3 (열 전랭크 \(r = n\)): \(N(\mathbf{A}) = \{\mathbf{0}\}\) → 해가 있으면 유일

가해 조건의 기하학: \(\mathbf{b} \in C(\mathbf{A})\) 이어야 한다. \(C(\mathbf{A})\)\(\mathbb{R}^m\) 의 진부분공간이면 (경우 3, 4), 대부분의 \(\mathbf{b}\) 에서 해가 없다.


10 3×4 심화 예시: 전 과정

\[\mathbf{A} = \begin{bmatrix} 1 & 2 & 3 & 5 \\ 2 & 4 & 8 & 12 \\ 3 & 6 & 7 & 13 \end{bmatrix}, \quad \mathbf{b} = \begin{bmatrix} b_1 \\ b_2 \\ b_3 \end{bmatrix}\]

10.1 소거: [A|b] → [U|c]

\[[\mathbf{A}\ |\ \mathbf{b}] \rightarrow \begin{bmatrix} 1 & 2 & 3 & 5 & b_1 \\ 0 & 0 & 2 & 2 & b_2 - 2b_1 \\ 0 & 0 & 0 & 0 & b_3 + b_2 - 5b_1 \end{bmatrix}\]

가해 조건: \(b_3 + b_2 - 5b_1 = 0\)

이 조건이 성립하는 \(\mathbf{b}\) 들의 집합이 바로 열 공간 \(C(\mathbf{A})\) 다 — \(\mathbb{R}^3\) 의 평면.

10.2 RREF로 변환: [R|d]

\[[\mathbf{R}\ |\ \mathbf{d}] = \begin{bmatrix} 1 & 2 & 0 & 2 & b_1 - \frac{3}{2}(b_2 - 2b_1) \\ 0 & 0 & 1 & 1 & \frac{1}{2}(b_2 - 2b_1) \\ 0 & 0 & 0 & 0 & 0 \end{bmatrix}\]

구체적으로 \(\mathbf{b} = (0, 6, -6)^\top\) (\(b_3 + b_2 - 5b_1 = -6 + 6 - 0 = 0\), 가해 조건 충족):

\[\mathbf{x}_p = \begin{bmatrix} -9 \\ 0 \\ 3 \\ 0 \end{bmatrix}, \quad \mathbf{s}_1 = \begin{bmatrix} -2 \\ 1 \\ 0 \\ 0 \end{bmatrix}, \quad \mathbf{s}_2 = \begin{bmatrix} -1 \\ 0 \\ -1 \\ 1 \end{bmatrix}\]

\[\mathbf{x} = \begin{bmatrix} -9 \\ 0 \\ 3 \\ 0 \end{bmatrix} + x_2 \begin{bmatrix} -2 \\ 1 \\ 0 \\ 0 \end{bmatrix} + x_4 \begin{bmatrix} -1 \\ 0 \\ -1 \\ 1 \end{bmatrix}\]


11 왜 완전해 구조가 중요한가

머신러닝/데이터 과학에서의 의미:

  • 과결정 시스템 (\(m > n\), 경우 3): 관측치 수 > 특성 수. 일반적으로 정확한 해가 없어 최소제곱법으로 근사한다.
  • 과소결정 시스템 (\(m < n\), 경우 2): 관측치 수 < 특성 수. 해가 무수히 많아 정규화(regularization) 로 하나를 선택한다.
  • L2 정규화 (Ridge): 영공간에서 원점에 가장 가까운 해 \(\mathbf{x}_p\) 를 선택하는 것과 동일하다.
  • 희소 해 (Lasso): 영공간에서 0 성분이 많은 해를 선택한다.

선형대수 전체 구조와의 연결:

\[\text{완전해} = \mathbf{x}_p + N(\mathbf{A}) \quad \longleftrightarrow \quad \text{해 집합의 기하학}\] \[\dim(\text{해 집합}) = \dim(N(\mathbf{A})) = n - r\]


12 응용 분야

분야 상황 해 구조
선형 회귀 \(m \gg n\), 과결정 정확한 해 없음 → 최소제곱 근사
신경망 훈련 \(n \gg m\), 과소결정 무수한 해 → 경사하강이 최소 노름 해 선택
이미지 복원 관측 = 픽셀 일부 조건 \(b \in C(A)\) 가 핵심
제어 이론 입력-출력 방정식 전행랭크면 임의 목표 상태 달성 가능
회로 분석 키르히호프 법칙 영공간 = 순환 전류 (자유도)

13 코드 예시

13.0.1 Step 1: 첨가 행렬 소거로 가해 조건 및 완전해 계산 (원리)

import numpy as np

def complete_solution(A, b):
    """
    Ax = b의 완전해 x = xp + xn을 계산한다.
    - xp: 특정해 (자유 변수 = 0)
    - xn_basis: 영공간 기저 (특수해들의 목록)
    - solvable: 가해 여부
    """
    m, n = A.shape
    b = b.astype(float).reshape(-1, 1)
    Ab = np.hstack([A.astype(float), b])  # 첨가 행렬 [A|b]

    pivot_cols = []
    row = 0

    for col in range(n):
        pivot = None
        for r in range(row, m):
            if abs(Ab[r, col]) > 1e-10:
                pivot = r
                break
        if pivot is None:
            continue

        Ab[[row, pivot]] = Ab[[pivot, row]]
        Ab[row] /= Ab[row, col]

        for r in range(m):
            if r != row and abs(Ab[r, col]) > 1e-10:
                Ab[r] -= Ab[r, col] * Ab[row]

        pivot_cols.append(col)
        row += 1

    r = len(pivot_cols)
    R = Ab[:, :n]
    d = Ab[:, n]

    # 가해 조건 확인: R의 영행에서 d도 0인지 확인
    solvable = True
    for i in range(r, m):
        if abs(d[i]) > 1e-10:
            solvable = False
            break

    if not solvable:
        return None, None, False

    # 자유 열
    free_cols = [c for c in range(n) if c not in pivot_cols]

    # 특정해 xp: 자유 변수 = 0
    xp = np.zeros(n)
    for i, pc in enumerate(pivot_cols):
        xp[pc] = d[i]

    # 영공간 기저 (특수해들)
    xn_basis = []
    for fc in free_cols:
        s = np.zeros(n)
        s[fc] = 1.0
        for i, pc in enumerate(pivot_cols):
            s[pc] = -R[i, fc]
        xn_basis.append(s)

    return xp, xn_basis, True


# 3×4 예시
A = np.array([
    [1, 3, 0, 2],
    [0, 0, 1, 4],
    [1, 3, 1, 6]
], dtype=float)

b = np.array([1, 6, 7], dtype=float)

xp, xn_basis, solvable = complete_solution(A, b)

if solvable:
    print(f"특정해 xp = {xp}")
    print("특수해 (영공간 기저):")
    for i, s in enumerate(xn_basis):
        print(f"  s{i+1} = {s}")
    print(f"\n검증 A @ xp - b = {np.round(A @ xp - b, 10)}")

# 해 없는 경우 테스트
b_no_sol = np.array([1, 6, 8], dtype=float)  # 1 + 6 ≠ 8
xp2, _, solvable2 = complete_solution(A, b_no_sol)
print(f"\nb = (1,6,8)의 가해 여부: {solvable2}")  # False

13.0.2 Step 2: NumPy / SciPy를 이용한 최소 노름 특정해 (실무)

import numpy as np
from scipy.linalg import lstsq, null_space

A = np.array([
    [1, 3, 0, 2],
    [0, 0, 1, 4],
    [1, 3, 1, 6]
], dtype=float)

b = np.array([1, 6, 7], dtype=float)

# lstsq: 최소 노름 특정해 (과소결정 시스템에서 ||xp||가 최소)
xp_min_norm, residuals, rank, sv = lstsq(A, b)
print(f"최소 노름 특정해 xp = {xp_min_norm}")
print(f"||xp||^2 = {np.sum(xp_min_norm**2):.4f}")
print(f"랭크 = {rank}")
print(f"잔차 ||Axp - b|| = {np.linalg.norm(A @ xp_min_norm - b):.2e}")

# 영공간 기저 (정규직교화)
N = null_space(A)
print(f"\n영공간 기저 (정규직교):\n{N}")

# 완전해: xp + 영공간의 임의 결합
c1, c2 = 2.0, -1.5  # 임의의 계수
x_complete = xp_min_norm + c1 * N[:, 0] + c2 * N[:, 1]
print(f"\n완전해 x = xp + c1*s1 + c2*s2:")
print(f"  x = {x_complete}")
print(f"  검증 Ax = b: {np.allclose(A @ x_complete, b)}")

13.0.3 Step 3: 네 가지 랭크 경우 시각화

import numpy as np
import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

cases = [
    {
        "title": "경우 1: r=m=n (정사각 가역)\n해 항상 유일",
        "A": np.array([[1, 2], [3, 7]], dtype=float),
        "b": np.array([3, 8], dtype=float),
        "color": "steelblue"
    },
    {
        "title": "경우 2: r=m<n (가로 행렬)\n해 항상 무한히 많음",
        "A": np.array([[1, 1, 1], [1, 2, -1]], dtype=float),
        "b": np.array([3, 4], dtype=float),
        "color": "green"
    },
    {
        "title": "경우 3: r=n<m (세로 행렬)\n해 없거나 유일",
        "A": np.array([[1, 1], [1, 2], [-2, -3]], dtype=float),
        "b": np.array([2, 3, -5], dtype=float),  # b1+b2=b3 조건 충족
        "color": "orange"
    },
    {
        "title": "경우 4: r<m, r<n (일반)\n해 없거나 무한히 많음",
        "A": np.array([[1, 1, 2], [2, 2, 4], [1, 1, 2]], dtype=float),
        "b": np.array([3, 6, 3], dtype=float),  # 가해 조건 충족
        "color": "red"
    }
]

for ax, case in zip(axes.flatten(), cases):
    A, b = case["A"], case["b"]
    m, n = A.shape
    r = np.linalg.matrix_rank(A)

    from scipy.linalg import lstsq, null_space
    xp, res, rank, sv = lstsq(A, b)
    residual = np.linalg.norm(A @ xp - b)
    null_dim = n - rank

    text = (
        f"A: {m}×{n}, 랭크 r={r}\n"
        f"n-r={null_dim} (자유 변수 수)\n"
        f"잔차 ||Axp-b|| = {residual:.2e}"
    )
    ax.text(0.5, 0.5, text, transform=ax.transAxes,
            ha='center', va='center', fontsize=11,
            bbox=dict(boxstyle='round', facecolor=case["color"], alpha=0.3))
    ax.set_title(case["title"], fontsize=10, fontweight='bold')
    ax.axis('off')

plt.suptitle("Ax=b의 네 가지 경우 (랭크 r, 행 수 m, 열 수 n)", fontsize=13)
plt.tight_layout()
plt.show()

14 핵심 정리

개념 내용
완전해 구조 \(\mathbf{x} = \mathbf{x}_p + \mathbf{x}_n\) (특정해 + 영공간)
특정해 자유 변수 = 0, 피벗 변수 = \(\mathbf{d}\) 에서 역대입
가해 조건 \(\mathbf{b} \in C(\mathbf{A})\) ↔︎ \(\mathbf{R}\) 의 영행에서 \(\mathbf{d}\) 도 0
\(r = m\) (전행랭크) \(C(\mathbf{A}) = \mathbb{R}^m\) → 항상 해 존재, \(n-m\) 개 특수해
\(r = n\) (전열랭크) \(N(\mathbf{A}) = \{\mathbf{0}\}\) → 해 있으면 유일, \(m-n\) 개 가해 조건
\(r = m = n\) 가역 행렬, 항상 유일해 \(\mathbf{x} = \mathbf{A}^{-1}\mathbf{b}\)
해 집합의 차원 \(\dim(N(\mathbf{A})) = n - r\)

15 관련 주제

선행 지식

후속 주제

다른 카테고리 연결

Subscribe

Enjoy this blog? Get notified of new posts by email: