이상치란 무엇일까? IQR로 찾고 처리하는 방법

데이터 분석이나 머신러닝을 진행하다 보면 다른 값들과 비교했을 때 유난히 크거나 작은 데이터를 발견하게 됩니다.

이러한 값을 이상치(Outlier)라고 합니다.

이상치는 단순한 입력 오류일 수도 있지만, 실제로 중요한 사건이나 특별한 고객 행동을 나타내는 데이터일 수도 있습니다.

따라서 이상치를 발견했다고 해서 무조건 삭제해서는 안 됩니다. 이상치가 발생한 원인과 데이터의 의미를 먼저 확인해야 합니다.

이번 글에서는 이상치가 무엇인지, 왜 발생하는지, 분석 결과에 어떤 영향을 주는지, 그리고 Pandas와 IQR을 이용해 이상치를 찾고 처리하는 방법을 알아보겠습니다.


이상치란?

이상치란 대부분의 데이터와 비교했을 때 지나치게 크거나 작은 값을 의미합니다.

예를 들어 다음과 같은 고객의 월 소득 데이터가 있다고 가정해 보겠습니다.

고객 월 소득
고객 A 320만 원
고객 B 350만 원
고객 C 290만 원
고객 D 340만 원
고객 E 5,000만 원

고객 E의 월 소득은 다른 고객과 비교했을 때 매우 큽니다. 이 값은 이상치로 판단될 가능성이 높습니다.

하지만 고객 E가 실제 고소득자라면 잘못된 데이터가 아닙니다. 반대로 500만 원을 입력해야 하는데 5,000만 원으로 잘못 입력한 것이라면 데이터 오류에 해당합니다.

핵심
이상치는 다른 값과 크게 다르다는 뜻이지, 반드시 틀린 데이터라는 뜻은 아닙니다.

이상치는 왜 발생할까?

1. 데이터 입력 오류

사람이 직접 데이터를 입력하는 과정에서 숫자를 잘못 입력할 수 있습니다.

정상 입력: 35세
잘못된 입력: 350세

이런 경우는 명확한 오류이므로 수정하거나 제거하는 것이 적절합니다.

2. 측정 장비나 센서 오류

센서가 고장 나거나 통신에 문제가 생기면 비정상적으로 크거나 작은 값이 기록될 수 있습니다.

09:00 온도 22.1℃
10:00 온도 21.9℃
11:00 온도 145.0℃
12:00 온도 22.3℃

일반적인 환경이라면 145℃는 센서 오류일 가능성이 높습니다.

3. 단위가 서로 다른 경우

일부 데이터는 센티미터로 입력되고 일부는 미터로 입력되면 값의 범위가 크게 달라질 수 있습니다.

170cm
165cm
1.8m

단위를 통일하지 않으면 1.8이라는 값이 이상치처럼 보일 수 있습니다.

4. 실제로 드문 사건이 발생한 경우

이상치는 데이터 오류가 아니라 현실에서 실제로 발생한 특별한 사건일 수도 있습니다.

  • 갑작스러운 매출 급증
  • 대규모 주문
  • 질병 발생
  • 금융 사기 거래
  • 시스템 장애

특히 금융 사기 탐지나 의료 데이터 분석에서는 이상치 자체가 가장 중요한 분석 대상이 될 수 있습니다.

5. 서로 다른 집단이 섞인 경우

일반 고객과 기업 고객의 구매 데이터를 함께 분석하면 기업 고객의 구매 금액이 이상치처럼 보일 수 있습니다.

이 경우에는 이상치를 제거하기보다 고객 유형을 나누어 분석하는 것이 더 적절할 수 있습니다.


이상치가 분석에 미치는 영향

1. 평균값을 크게 왜곡할 수 있다

다음과 같은 데이터가 있다고 가정해 보겠습니다.

300, 320, 330, 350, 5000

대부분의 값은 300대이지만 5,000이라는 큰 값이 포함되어 있습니다.

이 데이터를 평균으로 계산하면 실제 대다수 데이터보다 훨씬 큰 값이 나올 수 있습니다.

통계값 결과
평균 1,260
중앙값 330

이처럼 이상치가 존재할 때는 평균보다 중앙값이 데이터의 중심을 더 잘 나타낼 수 있습니다.

2. 머신러닝 모델의 학습을 방해할 수 있다

선형 회귀처럼 오차를 기반으로 학습하는 모델은 큰 이상치 하나에도 큰 영향을 받을 수 있습니다.

이상치 때문에 회귀선이 정상적인 데이터 구간에서 벗어나면 전체 예측 성능이 떨어질 수 있습니다.

3. 스케일링 결과를 왜곡할 수 있다

MinMaxScaler는 최솟값과 최댓값을 기준으로 데이터를 변환합니다.

매우 큰 이상치가 하나 존재하면 나머지 값들이 좁은 범위에 몰릴 수 있습니다.

4. 잘못 제거하면 중요한 정보를 잃을 수 있다

사기 거래, 질병, 장애 발생처럼 드문 사건을 분석하는 경우 이상치를 제거하면 가장 중요한 데이터를 잃게 됩니다.

따라서 이상치 처리는 모델 성능만 보고 결정하는 것이 아니라 분석 목적과 업무 맥락을 함께 고려해야 합니다.


Pandas로 데이터 분포 확인하기

이상치를 찾기 전에 먼저 데이터의 전체적인 분포를 확인해야 합니다.

import pandas as pd

df = pd.DataFrame({
    "Salary": [300, 320, 330, 350, 370, 400, 420, 5000]
})

print(df)

describe()로 요약 통계 확인하기

df["Salary"].describe()

describe()를 실행하면 다음 정보를 확인할 수 있습니다.

  • 데이터 개수
  • 평균
  • 표준편차
  • 최솟값
  • 25% 지점
  • 중앙값
  • 75% 지점
  • 최댓값

평균과 중앙값의 차이가 지나치게 크거나 최댓값이 75% 값보다 매우 크다면 이상치가 있을 가능성을 확인할 수 있습니다.

주의
describe()만으로 이상치를 확정할 수는 없습니다. 데이터의 분포를 빠르게 확인하는 용도로 사용하는 것이 좋습니다.

IQR이란?

이상치를 찾는 대표적인 방법 중 하나가 IQR(Interquartile Range)입니다.

IQR은 데이터의 75% 지점인 Q3에서 25% 지점인 Q1을 뺀 범위입니다.
Q1 = 데이터의 25% 지점
Q2 = 데이터의 50% 지점, 중앙값
Q3 = 데이터의 75% 지점
IQR = Q3 - Q1

IQR 방식에서는 일반적으로 다음 범위를 벗어난 값을 이상치 후보로 판단합니다.

하한값 = Q1 - 1.5 × IQR
상한값 = Q3 + 1.5 × IQR

하한값보다 작거나 상한값보다 큰 값을 이상치로 판단합니다.

1.5는 무엇일까?
1.5는 IQR 방식에서 일반적으로 사용하는 기준값입니다. 절대적인 법칙은 아니며 데이터 특성에 따라 조정할 수 있습니다.

Pandas로 IQR 계산하기

Q1 = df["Salary"].quantile(0.25)
Q3 = df["Salary"].quantile(0.75)

IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

print("Q1:", Q1)
print("Q3:", Q3)
print("IQR:", IQR)
print("하한값:", lower_bound)
print("상한값:", upper_bound)

quantile(0.25)는 25% 지점인 Q1을 구하고, quantile(0.75)는 75% 지점인 Q3를 구합니다.

이상치 행 찾기

outliers = df[
    (df["Salary"] < lower_bound) |
    (df["Salary"] > upper_bound)
]

print(outliers)

조건은 다음 두 경우를 의미합니다.

  • Salary가 하한값보다 작은 경우
  • Salary가 상한값보다 큰 경우

두 조건 중 하나라도 만족하면 이상치 후보로 조회합니다.

HTML 작성 시 주의
코드 안의 작은 부등호는 &lt;, 큰 부등호는 &gt; 형태로 작성해야 티스토리 HTML에서 정상적으로 표시됩니다.

정상 범위 데이터만 조회하기

이상치를 제외하고 정상 범위에 있는 데이터만 조회할 수도 있습니다.

normal_data = df[
    (df["Salary"] >= lower_bound) &
    (df["Salary"] <= upper_bound)
]

print(normal_data)

이 코드는 Salary 값이 하한값 이상이며 상한값 이하인 행만 선택합니다.

하지만 이 결과를 바로 이상치 제거 결과로 사용하기 전에 반드시 해당 값이 실제 오류인지 확인해야 합니다.


이상치를 처리하는 방법

1. 이상치 제거

이상치가 명확한 입력 오류이거나 센서 오류라면 해당 행을 제거할 수 있습니다.

df_removed = df[
    (df["Salary"] >= lower_bound) &
    (df["Salary"] <= upper_bound)
]

다만 데이터 수가 적을 때 행을 제거하면 정보 손실이 커질 수 있습니다.

2. 상한값과 하한값으로 변경

이상치를 완전히 제거하지 않고 경계값으로 제한하는 방법도 있습니다.

df["Salary"] = df["Salary"].clip(
    lower=lower_bound,
    upper=upper_bound
)

상한값보다 큰 값은 상한값으로, 하한값보다 작은 값은 하한값으로 변경됩니다.

이러한 방식을 클리핑(Clipping) 또는 윈저라이징(Winsorizing)이라고 부르기도 합니다.

3. 중앙값으로 대체

이상치가 오류라고 판단되지만 행 자체를 제거하기 어려운 경우 중앙값으로 대체할 수 있습니다.

median_value = df["Salary"].median()

df.loc[
    (df["Salary"] < lower_bound) |
    (df["Salary"] > upper_bound),
    "Salary"
] = median_value

중앙값은 이상치의 영향을 적게 받기 때문에 평균보다 안정적인 대체값이 될 수 있습니다.

4. 로그 변환

소득, 매출, 집값처럼 값의 범위가 크고 오른쪽으로 치우친 데이터는 로그 변환을 사용할 수 있습니다.

import numpy as np

df["Salary_log"] = np.log1p(df["Salary"])

log1p()는 값에 1을 더한 뒤 로그를 계산합니다. 값이 0인 경우에도 사용할 수 있다는 장점이 있습니다.

로그 변환은 이상치를 삭제하는 방법이 아니라 큰 값의 영향력을 줄이는 방법입니다.

5. 그룹을 나누어 분석

이상치처럼 보이는 값이 실제로 다른 집단에 속한 정상 데이터라면 그룹을 분리하여 분석하는 것이 좋습니다.

예를 들어 개인 고객과 기업 고객을 분리하면 기업 고객의 큰 구매 금액이 더 이상 이상치로 보이지 않을 수 있습니다.

6. 이상치를 그대로 유지

이상치가 분석의 핵심인 경우에는 제거하지 않아야 합니다.

  • 금융 사기 탐지
  • 불량 제품 탐지
  • 질병 이상 징후 탐지
  • 서버 장애 탐지
  • 비정상 사용자 행동 탐지

이 경우에는 이상치를 제거하는 것이 아니라 이상치를 예측하고 탐지하는 모델을 만들어야 합니다.


이상치는 언제 제거해야 할까?

제거를 고려할 수 있는 경우

  • 명확한 입력 오류인 경우
  • 센서나 측정 장비의 오류인 경우
  • 분석 대상과 관련 없는 데이터인 경우
  • 단위 변환 오류가 발생한 경우
  • 이상치가 모델 성능을 크게 왜곡하는 경우

유지해야 하는 경우

  • 실제로 발생한 정상적인 값인 경우
  • 비즈니스적으로 중요한 고객이나 거래인 경우
  • 사기, 장애, 질병처럼 드문 사건을 분석하는 경우
  • 해당 값이 새로운 패턴을 의미하는 경우
판단 기준
이상치를 제거할지 결정할 때는 통계 기준뿐 아니라 데이터가 만들어진 업무 환경과 분석 목적을 함께 고려해야 합니다.

머신러닝에서 주의할 점

머신러닝에서는 전체 데이터를 학습용과 테스트용으로 나눈 뒤 이상치 처리 기준을 계산해야 합니다.

전체 데이터에서 먼저 Q1, Q3, IQR을 계산하면 테스트 데이터의 정보가 학습 과정에 포함될 수 있습니다.

이를 데이터 누수(Data Leakage)라고 합니다.

올바른 순서는 다음과 같습니다.

전체 데이터를 학습용과 테스트용으로 분리

학습 데이터에서 Q1, Q3, IQR 계산

학습 데이터 이상치 처리

같은 기준을 테스트 데이터에 적용
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=42
)

Q1 = X_train["Salary"].quantile(0.25)
Q3 = X_train["Salary"].quantile(0.75)
IQR = Q3 - Q1

lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

X_train["Salary"] = X_train["Salary"].clip(
    lower=lower_bound,
    upper=upper_bound
)

X_test["Salary"] = X_test["Salary"].clip(
    lower=lower_bound,
    upper=upper_bound
)

테스트 데이터에서 별도로 IQR을 계산하지 않고 학습 데이터에서 계산한 기준을 동일하게 적용해야 합니다.


전체 실습 예제

import pandas as pd

df = pd.DataFrame({
    "Name": ["Kim", "Lee", "Park", "Choi", "Jung", "Han"],
    "Salary": [300, 320, 330, 350, 370, 5000]
})

# 데이터 요약 확인
print(df["Salary"].describe())

# Q1과 Q3 계산
Q1 = df["Salary"].quantile(0.25)
Q3 = df["Salary"].quantile(0.75)

# IQR 계산
IQR = Q3 - Q1

# 이상치 경계값 계산
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR

print("Q1:", Q1)
print("Q3:", Q3)
print("IQR:", IQR)
print("하한값:", lower_bound)
print("상한값:", upper_bound)

# 이상치 조회
outliers = df[
    (df["Salary"] < lower_bound) |
    (df["Salary"] > upper_bound)
]

print("이상치")
print(outliers)

# 정상 범위 데이터 조회
normal_data = df[
    (df["Salary"] >= lower_bound) &
    (df["Salary"] <= upper_bound)
]

print("정상 범위 데이터")
print(normal_data)

위 코드를 통해 데이터의 분포를 확인하고, IQR 기준으로 이상치 후보와 정상 범위 데이터를 구분할 수 있습니다.

단, 코드에서 이상치로 분류되었다는 이유만으로 바로 삭제하지 말고 실제 데이터의 의미를 반드시 확인해야 합니다.


자주 사용하는 이상치 관련 함수

함수 및 방법 역할
describe() 데이터의 요약 통계 확인
quantile(0.25) Q1, 25% 지점 계산
quantile(0.75) Q3, 75% 지점 계산
clip() 값을 상한과 하한 범위로 제한
median() 이상치 영향을 적게 받는 중앙값 계산
np.log1p() 큰 값의 영향력을 줄이기 위한 로그 변환
IQR 사분위 범위를 이용한 이상치 탐지

마무리

이상치는 대부분의 데이터와 다른 값을 의미하지만 반드시 잘못된 데이터는 아닙니다.

입력 오류나 센서 오류일 수도 있고, 실제로 발생한 중요한 사건일 수도 있습니다.

따라서 이상치를 발견하면 다음 질문을 먼저 확인해야 합니다.

  • 이 값은 실제로 발생할 수 있는가?
  • 입력이나 측정 과정에서 오류가 있었는가?
  • 단위가 다른 데이터가 섞여 있는가?
  • 이상치가 분석 목적에서 중요한 의미를 가지는가?
  • 제거했을 때 중요한 정보가 사라지지 않는가?
이상치 처리는 튀는 값을 무조건 삭제하는 작업이 아니라, 데이터의 원인과 의미를 확인한 뒤 적절한 방법을 선택하는 과정입니다.

핵심 정리

  • 이상치는 대부분의 데이터보다 지나치게 크거나 작은 값입니다.
  • 이상치는 입력 오류일 수도 있고 실제로 중요한 데이터일 수도 있습니다.
  • describe()로 데이터의 분포와 통계값을 확인할 수 있습니다.
  • IQR은 Q3에서 Q1을 뺀 사분위 범위입니다.
  • 일반적으로 Q1 - 1.5 × IQR보다 작거나 Q3 + 1.5 × IQR보다 큰 값을 이상치 후보로 판단합니다.
  • 이상치는 제거, 대체, 클리핑, 로그 변환, 그룹 분리 등의 방법으로 처리할 수 있습니다.
  • 분석 목적에 따라 이상치를 그대로 유지해야 할 수도 있습니다.
  • 머신러닝에서는 학습 데이터에서 계산한 이상치 기준을 테스트 데이터에도 동일하게 적용해야 합니다.

다음 글 예고

다음 글에서는 중복 데이터가 무엇인지, 중복 데이터가 분석 결과와 머신러닝 모델에 어떤 영향을 주는지 알아보겠습니다.

또한 Pandas의 duplicated()drop_duplicates()를 사용하여 중복 데이터를 찾고 제거하는 방법을 실습해 보겠습니다.

결측치란 무엇일까? Null, NaN, None의 차이와 처리 방법

데이터 분석이나 머신러닝을 시작하면 가장 먼저 만나게 되는 문제가 있습니다. 바로 결측치(Missing Value)입니다.

실제 데이터에는 값이 비어 있거나, 수집되지 않았거나, 여러 시스템을 합치는 과정에서 누락된 데이터가 자주 포함됩니다.

결측치를 제대로 처리하지 않으면 분석 결과가 왜곡되거나 머신러닝 모델이 정상적으로 학습하지 못할 수 있습니다.

이번 글에서는 결측치가 무엇인지, 왜 발생하는지, 그리고 Pandas에서는 어떻게 확인하고 처리하는지 알아보겠습니다.


결측치란?

결측치란 데이터가 존재해야 하는 위치에 값이 없는 상태를 의미합니다.

예를 들어 다음과 같은 고객 데이터가 있다고 가정해 보겠습니다.

이름 나이 성별 연봉
홍길동 35 5,000
김철수 NaN 4,200
이영희 28 NaN
박민수 41 6,000

위 데이터에서는 다음 두 값이 비어 있습니다.

  • 김철수의 나이
  • 이영희의 연봉

이처럼 값이 있어야 할 위치에 데이터가 존재하지 않는 상태를 결측치라고 합니다.


결측치는 왜 발생할까?

1. 사용자가 값을 입력하지 않은 경우

회원가입이나 설문조사에서 선택 입력 항목이 있다면 사용자가 해당 값을 입력하지 않을 수 있습니다.

이름: 홍길동
전화번호: 입력하지 않음
주소: 서울

전화번호가 필수 항목이 아니라면 해당 위치에는 결측치가 발생할 수 있습니다.

2. 센서나 장비에 오류가 발생한 경우

온도 센서, GPS, IoT 장비 등은 통신 장애나 장비 오류로 인해 특정 시간의 값을 기록하지 못할 수 있습니다.

10:00 온도 22.5
11:00 온도 NaN
12:00 온도 23.1

3. 데이터 수집 과정에서 누락된 경우

API 호출 실패, 네트워크 오류, 파일 저장 실패 등의 이유로 일부 데이터가 수집되지 않을 수 있습니다.

4. 여러 데이터를 합치는 과정에서 발생한 경우

고객 정보와 주문 정보를 합쳤는데 특정 고객의 주문 정보가 없다면 해당 위치에 결측치가 생길 수 있습니다.

5. 사람이 입력을 누락하거나 삭제한 경우

엑셀이나 관리 시스템에 데이터를 직접 입력하는 과정에서도 값을 빼먹거나 실수로 삭제할 수 있습니다.


NULL, None, NaN의 차이

결측치를 공부하다 보면 NULL, None, NaN이라는 표현을 자주 만나게 됩니다. 모두 값이 없다는 의미로 사용되지만 사용되는 환경이 다릅니다.

표현 주로 사용하는 환경 의미
NULL 데이터베이스 값이 존재하지 않음
None Python 값이 없는 Python 객체
NaN Pandas, NumPy 숫자 데이터의 결측값 표현

NULL

NULL은 주로 데이터베이스에서 값이 존재하지 않는 상태를 표현할 때 사용합니다.

SELECT *
FROM member
WHERE phone IS NULL;

None

None은 Python에서 값이 존재하지 않는 상태를 표현하는 객체입니다.

name = None

print(name)

NaN

NaN은 Not a Number의 약자이며, NumPy와 Pandas에서 결측값을 표현할 때 자주 사용합니다.

import numpy as np

age = np.nan

print(age)
주의할 점
NULL, None, NaN은 완전히 동일한 객체는 아니지만, 데이터 분석에서는 모두 결측 상태를 표현하는 용도로 자주 사용됩니다.

결측치를 그대로 두면 어떤 문제가 생길까?

1. 계산 결과가 왜곡될 수 있다

평균, 합계, 비율 등을 계산할 때 결측치 처리 방식에 따라 결과가 달라질 수 있습니다.

2. 머신러닝 모델 학습 중 오류가 발생할 수 있다

많은 머신러닝 알고리즘은 결측치가 포함된 데이터를 그대로 입력받지 못합니다.

from sklearn.linear_model import LinearRegression

model = LinearRegression()
model.fit(X, y)

데이터에 결측치가 있다면 다음과 같은 오류가 발생할 수 있습니다.

ValueError: Input X contains NaN

3. 데이터의 대표성이 달라질 수 있다

특정 집단에서 결측치가 많이 발생한다면 데이터를 삭제하는 과정에서 해당 집단의 정보가 지나치게 줄어들 수 있습니다.

따라서 결측치를 무조건 삭제하기보다는 결측치가 발생한 이유와 데이터의 특성을 함께 확인해야 합니다.


Pandas에서 결측치 확인하기

다음과 같은 DataFrame을 만들어 보겠습니다.

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "Name": ["Kim", "Lee", "Park", "Choi"],
    "Age": [25, np.nan, 31, 42],
    "Salary": [3000, 4200, np.nan, 5100]
})

print(df)

1. isna()

isna()는 각각의 값이 결측치인지 확인합니다.

df.isna()

결측치라면 True, 결측치가 아니라면 False가 반환됩니다.

2. isnull()

isnull()도 결측치를 확인하는 함수입니다.

df.isnull()

Pandas에서 isna()isnull()은 같은 결과를 반환합니다.

3. 컬럼별 결측치 개수 확인

df.isna().sum()

예상 결과는 다음과 같습니다.

Name      0
Age       1
Salary    1
dtype: int64

4. 전체 결측치 개수 확인

df.isna().sum().sum()

전체 DataFrame에 존재하는 결측치의 개수를 확인할 수 있습니다.

5. 결측치가 있는 행만 확인

df[df.isna().any(axis=1)]

any(axis=1)은 행을 기준으로 하나라도 결측치가 있는지 확인합니다.

6. 특정 컬럼의 결측치 행 확인

df[df["Age"].isna()]

Age 컬럼에서 값이 비어 있는 행만 조회할 수 있습니다.


결측치를 제거하는 방법

1. 결측치가 있는 행 제거

df.dropna()

기본적으로 결측치가 하나라도 포함된 행을 제거합니다.

주의
원본 DataFrame을 직접 변경하려면 결과를 다시 변수에 저장해야 합니다.
df = df.dropna()

2. 특정 컬럼에 결측치가 있는 행만 제거

df.dropna(subset=["Age"])

Age 컬럼이 비어 있는 행만 제거합니다. Salary 컬럼의 결측치는 제거 조건에 포함되지 않습니다.

3. 모든 값이 결측치인 행만 제거

df.dropna(how="all")

행의 모든 값이 결측치인 경우에만 해당 행을 제거합니다.

4. 결측치가 많은 컬럼 제거

df.drop(columns=["Salary"])

특정 컬럼에 결측치가 지나치게 많고 분석에 중요하지 않다면 컬럼 자체를 제거할 수도 있습니다.


결측치를 채우는 방법

결측치가 포함된 데이터를 모두 제거하면 중요한 정보까지 사라질 수 있습니다.

이 경우에는 fillna()를 사용하여 적절한 값으로 결측치를 채울 수 있습니다.

1. 평균값으로 채우기

df["Age"] = df["Age"].fillna(df["Age"].mean())

숫자형 데이터의 결측치를 평균값으로 채우는 방법입니다.

다만 이상치가 많은 데이터에서는 평균값 자체가 왜곡될 수 있습니다.

2. 중앙값으로 채우기

df["Salary"] = df["Salary"].fillna(df["Salary"].median())

중앙값은 데이터를 크기순으로 정렬했을 때 가운데에 위치한 값입니다.

연봉, 집값처럼 이상치가 큰 영향을 줄 수 있는 데이터에서는 평균보다 중앙값이 더 적절할 수 있습니다.

3. 최빈값으로 채우기

df["Gender"] = df["Gender"].fillna(df["Gender"].mode()[0])

최빈값은 데이터에서 가장 자주 등장한 값입니다.

성별, 지역, 등급처럼 범주형 데이터의 결측치를 채울 때 자주 사용합니다.

4. 특정 값으로 채우기

df["Address"] = df["Address"].fillna("Unknown")

결측 상태 자체에 의미가 있다면 Unknown, 미입력, 정보 없음 같은 별도의 값으로 채울 수 있습니다.

5. 이전 값으로 채우기

df["Temperature"] = df["Temperature"].ffill()

앞에 있는 값을 사용해 결측치를 채우는 방법입니다. 시계열 데이터에서 자주 사용합니다.

6. 다음 값으로 채우기

df["Temperature"] = df["Temperature"].bfill()

뒤에 있는 값을 사용해 결측치를 채우는 방법입니다.

7. 보간법 사용하기

df["Temperature"] = df["Temperature"].interpolate()

앞뒤 값의 흐름을 이용해 결측치를 계산합니다. 연속적으로 측정되는 온도, 속도, 가격 등의 데이터에 활용할 수 있습니다.


평균, 중앙값, 최빈값 중 무엇을 사용해야 할까?

방법 적합한 데이터 주의점
평균값 분포가 비교적 균형적인 숫자 데이터 이상치에 영향을 많이 받음
중앙값 연봉, 집값처럼 이상치가 있는 숫자 데이터 데이터 분포를 먼저 확인해야 함
최빈값 성별, 지역, 등급 같은 범주형 데이터 가장 많은 범주로 편향될 수 있음
특정 값 미입력 자체가 의미 있는 데이터 기존 범주와 구분되는 값을 사용해야 함

결측치는 언제 삭제하고 언제 채워야 할까?

삭제를 고려할 수 있는 경우

  • 전체 데이터에 비해 결측치가 매우 적은 경우
  • 데이터가 충분히 많은 경우
  • 결측치가 있는 행의 신뢰도가 낮은 경우
  • 해당 컬럼이 분석에 중요하지 않은 경우

예를 들어 데이터가 10만 건이고 결측치가 5건뿐이라면 해당 행을 제거해도 전체 분석에 미치는 영향이 작을 수 있습니다.

채우기를 고려할 수 있는 경우

  • 데이터의 양이 적은 경우
  • 행을 제거하면 중요한 정보가 사라지는 경우
  • 고객이나 환자처럼 각 데이터가 중요한 경우
  • 결측값을 합리적으로 추정할 수 있는 경우
핵심 판단 기준
결측치 비율만 보는 것이 아니라, 결측치가 발생한 이유와 해당 변수가 분석에 얼마나 중요한지를 함께 확인해야 합니다.

머신러닝에서 특히 주의할 점

머신러닝에서는 전체 데이터를 학습용 데이터와 테스트용 데이터로 나눕니다.

이때 평균값이나 중앙값을 전체 데이터에서 먼저 계산하면 테스트 데이터의 정보가 학습 과정에 포함될 수 있습니다.

이를 데이터 누수(Data Leakage)라고 합니다.

올바른 순서는 다음과 같습니다.

전체 데이터 분리

학습 데이터에서 평균 또는 중앙값 계산

학습 데이터 결측치 처리

같은 값을 테스트 데이터에 적용
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X,
    y,
    test_size=0.2,
    random_state=42
)

age_median = X_train["Age"].median()

X_train["Age"] = X_train["Age"].fillna(age_median)
X_test["Age"] = X_test["Age"].fillna(age_median)

테스트 데이터의 중앙값을 별도로 계산하지 않고 학습 데이터에서 구한 중앙값을 동일하게 사용해야 합니다.


전체 실습 예제

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "Name": ["Kim", "Lee", "Park", "Choi"],
    "Age": [25, np.nan, 31, 42],
    "Gender": ["M", "F", np.nan, "F"],
    "Salary": [3000, 4200, np.nan, 5100]
})

# 컬럼별 결측치 개수
print(df.isna().sum())

# 나이는 중앙값으로 채우기
df["Age"] = df["Age"].fillna(df["Age"].median())

# 성별은 최빈값으로 채우기
df["Gender"] = df["Gender"].fillna(df["Gender"].mode()[0])

# 연봉은 평균값으로 채우기
df["Salary"] = df["Salary"].fillna(df["Salary"].mean())

print(df)
print(df.isna().sum())

결측치 처리가 끝난 뒤에는 반드시 isna().sum()을 다시 실행하여 결측치가 남아 있는지 확인하는 것이 좋습니다.


자주 사용하는 결측치 처리 함수

함수 역할
isna() 결측치 여부 확인
isnull() 결측치 여부 확인
notna() 결측치가 아닌 값 확인
dropna() 결측치가 포함된 행 또는 열 제거
fillna() 결측치를 특정 값으로 채우기
ffill() 이전 값으로 결측치 채우기
bfill() 다음 값으로 결측치 채우기
interpolate() 앞뒤 값의 흐름을 이용해 결측치 보간

마무리

결측치는 단순히 비어 있는 값처럼 보이지만, 데이터의 품질과 머신러닝 모델의 성능에 큰 영향을 줄 수 있습니다.

따라서 결측치를 발견하면 무조건 삭제하거나 평균으로 채우기보다 다음 질문을 먼저 확인해야 합니다.

  • 결측치는 왜 발생했는가?
  • 결측치의 비율은 어느 정도인가?
  • 해당 컬럼은 분석에 중요한가?
  • 삭제했을 때 정보 손실은 얼마나 발생하는가?
  • 평균, 중앙값, 최빈값 중 어떤 방식이 적절한가?
결측치 처리는 단순히 빈 값을 없애는 작업이 아니라, 데이터의 의미를 유지하면서 분석 가능한 형태로 만드는 과정입니다.

핵심 정리

  • 결측치는 데이터가 있어야 할 위치에 값이 없는 상태입니다.
  • 데이터베이스에서는 NULL, Python에서는 None, Pandas에서는 NaN으로 표현되는 경우가 많습니다.
  • isna()isnull()로 결측치를 확인할 수 있습니다.
  • dropna()는 결측치를 제거하고, fillna()는 결측치를 채웁니다.
  • 숫자형 데이터는 평균이나 중앙값, 범주형 데이터는 최빈값을 고려할 수 있습니다.
  • 결측치를 무조건 삭제하지 말고 발생 원인과 데이터의 중요도를 함께 판단해야 합니다.
  • 머신러닝에서는 학습 데이터에서 계산한 값을 테스트 데이터에도 동일하게 적용해야 합니다.

다음 글 예고

다음 글에서는 이상치(Outlier)가 무엇인지, 이상치가 데이터 분석과 머신러닝 결과에 어떤 영향을 주는지 알아보겠습니다.

또한 Pandas의 describe()와 IQR 방식을 사용하여 이상치를 찾고 처리하는 방법을 실습해 보겠습니다.

데이터 처리를 왜 하는 것일까?

AI와 머신러닝을 공부하다 보면 가장 먼저 접하게 되는 개념이 데이터 처리(Data Processing) 또는 데이터 전처리(Data Preprocessing)입니다.

많은 초보자는 모델만 잘 만들면 된다고 생각합니다. 하지만 실제 AI 프로젝트에서는 모델을 선택하는 것만큼 데이터를 어떻게 정리하고 가공하느냐가 중요합니다.

이번 글에서는 데이터 처리가 무엇인지, 왜 필요한지, 그리고 실제로 어떤 작업을 수행하는지 알아보겠습니다.


데이터 처리란?

데이터 처리는 현실 세계의 데이터를 컴퓨터와 AI가 이해하고 활용할 수 있는 형태로 만드는 과정입니다.

현실에서 수집한 데이터는 대부분 완벽하지 않습니다. 사람이 직접 입력하거나 여러 시스템에서 데이터를 수집하기 때문에 빈 값, 잘못된 값, 중복된 값 등이 포함될 수 있습니다.

예를 들어 다음과 같은 고객 데이터가 있다고 가정해 보겠습니다.

이름 나이 성별 연봉
홍길동 35 5,000
김철수 NULL Male 6,000
이영희 120 F -100

이 데이터에는 다음과 같은 문제가 있습니다.

  • 나이가 비어 있는 결측치
  • 120세처럼 현실적으로 보기 어려운 이상치
  • 음수로 입력된 잘못된 연봉
  • 남, Male, F처럼 서로 다른 성별 표기

이러한 데이터를 그대로 사용하면 분석 결과가 왜곡되거나 머신러닝 모델이 잘못된 규칙을 학습할 수 있습니다.


데이터 처리를 하는 이유

1. 데이터 품질을 높이기 위해

데이터의 품질이 낮으면 아무리 좋은 AI 모델을 사용하더라도 정확한 결과를 얻기 어렵습니다.

데이터 품질을 높이기 위해 다음과 같은 작업을 수행합니다.

  • 결측치 제거 또는 대체
  • 이상치 확인 및 처리
  • 중복 데이터 제거
  • 오타와 잘못된 값 수정
  • 날짜, 통화, 길이 등의 단위 통일

예를 들어 나이가 비어 있다면 평균이나 중앙값으로 채울 수 있고, 해당 데이터가 분석에 적합하지 않다면 행 자체를 제거할 수도 있습니다.

2. 컴퓨터가 이해할 수 있도록 만들기 위해

사람은 남자, 여자 같은 문자 데이터를 쉽게 이해할 수 있습니다. 하지만 많은 머신러닝 알고리즘은 숫자 형태의 데이터를 입력으로 사용합니다.

따라서 문자 데이터를 숫자로 변환하는 과정이 필요합니다.

Label Encoding

남자 → 0
여자 → 1

One-Hot Encoding

남자 여자
1 0
0 1

이처럼 범주형 데이터를 숫자로 바꾸는 작업을 인코딩(Encoding)이라고 합니다.

3. 모델이 더 안정적으로 학습하도록 만들기 위해

다음과 같은 데이터가 있다고 가정해 보겠습니다.

키   : 170
연봉 : 80,000,000

키와 연봉은 숫자의 크기 차이가 매우 큽니다. 거리나 크기에 민감한 일부 머신러닝 모델에서는 연봉처럼 큰 숫자를 가진 변수가 학습에 지나치게 큰 영향을 줄 수 있습니다.

이를 해결하기 위해 데이터를 일정한 범위나 분포로 변환하는 스케일링(Scaling)을 수행합니다.

  • StandardScaler
  • MinMaxScaler
  • RobustScaler

스케일링은 모든 모델에 반드시 필요한 것은 아니지만, KNN, SVM, 선형 모델, 신경망처럼 데이터 크기에 영향을 받는 모델에서는 중요합니다.

4. 새로운 정보를 만들기 위해

원본 데이터에 다음과 같은 날짜가 있다고 가정해 보겠습니다.

2026-07-13 14:33:25

이 값을 그대로 사용하기보다 다음과 같이 나눌 수 있습니다.

  • 연도
  • 요일
  • 시간
  • 주말 여부

예를 들어 쇼핑몰 데이터에서는 구매 시간 자체보다 주말 여부나 시간대가 구매 행동을 예측하는 데 더 유용할 수 있습니다.

이처럼 기존 데이터를 이용해 새로운 변수를 만드는 과정을 특성 공학(Feature Engineering)이라고 합니다.

5. 분석과 의사결정에 활용하기 위해

데이터 처리는 머신러닝 모델을 만들 때만 필요한 것이 아닙니다. 회사나 조직이 데이터를 기반으로 의사결정을 내릴 때도 필요합니다.

쇼핑몰 주문 데이터에 다음 항목만 있다고 가정해 보겠습니다.

  • 주문번호
  • 상품명
  • 가격
  • 구매시간

이 데이터를 가공하면 다음과 같은 정보를 얻을 수 있습니다.

  • 월별 매출
  • 시간대별 주문량
  • 인기 상품
  • 고객별 평균 구매금액
  • 재구매율
  • 고객 등급

즉, 데이터 처리는 단순히 데이터를 정리하는 작업이 아니라 원본 데이터에서 의미 있는 정보를 발견하는 과정입니다.


머신러닝에서 데이터 처리가 중요한 이유

데이터 분야에는 다음과 같은 표현이 있습니다.

Garbage In, Garbage Out
잘못된 데이터를 입력하면 잘못된 결과가 나온다.

머신러닝 모델은 스스로 현실을 이해하는 것이 아니라 주어진 데이터를 바탕으로 규칙을 학습합니다.

좋은 데이터 + 평범한 모델 → 좋은 결과
나쁜 데이터 + 뛰어난 모델 → 신뢰하기 어려운 결과

따라서 실무에서는 새로운 모델을 적용하기 전에 데이터에 오류가 없는지, 필요한 정보가 충분한지, 잘못된 편향이 포함되어 있지는 않은지 먼저 확인해야 합니다.


실제 AI 프로젝트의 흐름

현실 세계

데이터 수집

데이터 처리 및 전처리

데이터 분석

머신러닝 모델 학습

모델 평가

예측 및 서비스 적용

의사결정

데이터 처리는 데이터 수집 이후부터 모델 학습 이전까지 수행되는 핵심 기반 작업입니다.

경우에 따라 모델 학습 결과를 확인한 뒤 다시 데이터 처리 단계로 돌아가 결측치 처리 방식이나 특성을 수정하기도 합니다.


데이터 처리에서 자주 수행하는 작업

작업 목적 대표 함수 및 기법
결측치 처리 비어 있는 값 제거 또는 대체 fillna(), dropna()
이상치 처리 비정상적인 값 확인 및 조정 IQR, Z-Score
중복 제거 동일한 데이터 제거 drop_duplicates()
인코딩 문자 데이터를 숫자로 변환 Label Encoding, One-Hot Encoding
스케일링 숫자 데이터의 범위 조정 StandardScaler, MinMaxScaler
특성 생성 새로운 의미를 가진 변수 생성 날짜 분리, 구간화, 파생변수
데이터 분할 학습 데이터와 평가 데이터 분리 train_test_split()

마무리

데이터 처리는 단순히 데이터를 깨끗하게 정리하는 작업이 아닙니다.

현실의 데이터를 분석 가능한 형태로 바꾸고, 컴퓨터가 이해할 수 있도록 변환하며, 데이터 안에 숨어 있는 의미를 발견하는 과정입니다.

머신러닝 모델은 데이터로부터 학습합니다. 따라서 데이터의 품질이 좋아질수록 모델의 예측 결과도 더욱 신뢰할 수 있게 됩니다.

데이터 처리는 데이터를 깨끗하게 만들고, 컴퓨터가 이해할 수 있도록 변환하며, 분석과 머신러닝에 필요한 의미 있는 정보를 만드는 과정입니다.

핵심 정리

  • 데이터 처리는 현실 데이터를 컴퓨터가 활용할 수 있도록 만드는 과정입니다.
  • 결측치, 이상치, 중복, 잘못된 값을 처리해 데이터 품질을 높입니다.
  • 문자 데이터를 숫자로 변환해 머신러닝 모델이 학습할 수 있도록 합니다.
  • 스케일링을 통해 변수 간 숫자 크기의 차이를 조정할 수 있습니다.
  • 특성 공학을 통해 기존 데이터에서 새로운 정보를 만들 수 있습니다.
  • 좋은 데이터는 머신러닝 모델의 성능과 신뢰도를 높입니다.

1. 라이브러리 설정시 오라클을 다운받지 못하는 문제가 있다.

  •   이 경우 아래와 같이 repositories에 아래와 같은 경로를 추가 해주면 정상적으로 다운로드가 가능하다 .



repositories {
    mavenCentral()
    jcenter()

    maven { url "https://code.lds.org/nexus/content/groups/main-repo"}
}

dependencies {
    //compile('javax.servlet:jstl')
    //compile("org.apache.tomcat.embed:tomcat-embed-jasper")
    compile 'com.oracle:ojdbc7:12.1.0.2'
}

1. 이클립스 프로젝트에서 "mybatis"를 검색합니다 .

  •   mybatis Generator1.4.0을 받아줍니다. 

 

 

2. 프로젝트 내부에 적절한 위치에 "Mybatis Generator"를 사용하기위한  xml 파일을 생성해줍니다. 

 

 

3. generatorConfig.xml을 생성 후 아래와 같은 내용을 작성해줍니다. 

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC
 "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
 "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
	<context id="simple" targetRuntime="MyBatis3simple">
		<jdbcConnection
			connectionURL="URL을 적엉주세요 "
			driverClass="oracle.jdbc.driver.OracleDriver" password="비밀번호"
			userId="아이디" />

		<javaModelGenerator
			targetPackage="com.project.domain"
			targetProject="board/src/main/java">
			<property name="enableSubPackages" value="true" />
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<sqlMapGenerator 
			targetPackage="mybatis.mapper"
			targetProject="board/src/main/resources" />

		<javaClientGenerator
			targetPackage="example.mapper" 
			targetProject="board/src/main/java"
			type="XMLMAPPER" />

		<table tableName="usertb" />
		<table tableName="member" />
	</context>
</generatorConfiguration>

 

     3-1.xml 파일을 보시면 tragetRuntime이 있습니다. 이곳을 적절하게 바꿔주시면 다양한 generator를 사용가능 

 

MyBatis Generator Core – MyBatis Generator Quick Start Guide

MyBatis Generator Quick Start Guide MyBatis Generator (MBG) generates code in different styles depending on how it is configured. This is controlled by specifying the targetRuntime attribute on a configuration element. The table below summarizes the differ

mybatis.org

4. RUN MyBatis Generator를 실행해주면 정상적으로 파일이 생성되게 됩니다.

 

 

 

5. 결과 

 

 

 

 

 

 

#mapper 파일이 생성 안되는 경우 

  • targetRunTime의 속성 값을 "MyBatis3Simple" 을 추가 해주시거나 수정해주세요 
<context id="simple" targetRuntime="MyBatis3simple">

 

 

#mybatis "src/main/resources"에 mapper파일 생성 방법 

  • 아래와 같이 "targetPrject"에 "src/main/resources"를 작성해주세요 
		<sqlMapGenerator 
			targetPackage="mybatis.mapper"
			targetProject="board/src/main/resources" />

SLF4j 특징

 

SLF4j(Simple Log Facade for Java) 는 사용자가 원하는 로깅 프레임워크(log4j, logback, 등)으로 변경하여 사용 할수 있도록 추상화하는 기능을 제공한다.

 

 

1. gralde  추가 


    compile("org.slf4j:slf4j-api:1.7.7")
    compile('ch.qos.logback:logback-classic:1.1.2')

 

2. logback.xml 파일을 src/main/resource 아래 생성 후 아래 내용을 추가해준다. 

<?xml version="1.0" encoding="UTF-8"?>
<!-- 30초마다 설정 파일의 변경을 확인한다. 파일이 변경되면 다시 로딩한다 -->
<configuration scan="true" scanPeriod="30 seconds">

    <!-- 외부 설정파일을 사용할 수 있다. -->
    <property resource="resource.properties"/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern> %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${APP_HOME}/sujemall-webapp.log</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <!-- 파일이 하루에 한개씩 생성된다 -->
            <fileNamePattern>sujemall-webapp.%d{yyyy-MM-dd}.log</fileNamePattern>

            <!-- maxHIstory 설정은 위 부분에 롤링 정책에 따라 적용되 된다고 보면된다.
             위 설정데로 라면 30일이 지난 파일은 삭제가 된다.-->
            <maxHistory>30</maxHistory>
        </rollingPolicy>

        <encoder>
            <pattern>%-4relative [%thread] %-5level %logger{35} - %msg%n</pattern>
        </encoder>
    </appender>

    <logger name="org.springframework" level="info"/>
    <logger name="org.hibernate" level="debug"/>
    <logger name="com.sujemall.webapp" level="debug"/>
    <if condition='property("RUN_MODE").equals("SERVICE")'>
        <then>
            <!-- 설정파일에 RUN_MODE 가 SERVICE로 정의되어 있으면 로깅 레벨을 INFO로 지정 -->
            <root level="info">
                <appender-ref ref="console"/>
                <appender-ref ref="FILE"/>
            </root>
        </then>
        <!-- 설정파일에 RUN_MODE 가 SERVICE로 정의되어 있지 않으면  로깅 레벨을 DEBUG 지정 -->
        <else>
            <root level="debug">
                <appender-ref ref="console"/>
                <appender-ref ref="FILE"/>
            </root>
        </else>
    </if>
</configuration>

3. Anotation을 이용하여 Log찍어보기 

 

@Slf4j
public class App {
    public static void main(String[] args) {
        log.debug("test {}","asdf");
        log.debug("test {}","asdf");
        log.debug("test {}","asdf");
    }
}
    • 영속성 컨텍스트란 무엇인가.
        • 실제 DB 저장하는 것이 아니라 
        • 엔티티를 "영속컨텍스트에" 저장한다는 의미이다.

          • JPA 이해하는데 가장 중요한영어
          • "엔티티를 영구 저장하는 환경"이라는 의미를 가진다.
          • EntityManager.persist(entity)
          • 매니저(EntityManager)를 통해 영속성 컨텍스트(persistence)에 접근한다.
        • 비영속 컨텍스트
          • 영속성 컨텍스트와 전혀 관계가 없는 새로운 상태
          • JPA 관리하지 않는 상태
      //객체를 생성한 상태(비영속)
      
      Admin admin = new Admin();
      
      admin.setId("member1");
      
      admin.setUsername("회원1");
      
      //영속상태
      em.persist()

       

       

      • 준영속 (detached)
        • 영속성 컨텍스트에 저장되었다가 분리된 상태 
          //
          회원 엔티티를 영속성 컨텍스트에서 분리, 준영속 상태
        • em.detach()
      Admin admin = em.find(Admin.class , 101L);
      admin.setName("AAAAAA");
                  
      //JPA에서 관리하지 않는다. 
      em.detach(admin);
      
      //영속성 컨테스트의 내용을 전부 초기화 
      em.clear();

       

      • 그렇다면 영속성 속성을 클리어하고 다시 조회 하게 어떻게 될까 ? 
        • 아래의 예시를 보면 "em.clear" 또는 em.detach를 사용시에는 영속성관리를 하지 않게 됨으로 
        • admin 과 admin1은 1차캐시된 데이터를 가져오지 않으므로  false가 나오게 된다. 

       

                  Admin admin = em.find(Admin.class , 101L);
                  admin.setName("AAAAAA");
      
                  //JPA에서 관리하지 않는다.
                  em.detach(admin);
      
                  em.clear();
      
                  Admin admin1 = em.find(Admin.class,101L);
      
                  System.out.println(admin == admin1);

       

       

      • 영속이란 
        • 실제 영속컨테스트가 관리하는 1차캐시에 데이터가 없으면 DB에서 데이터를 가져와 캐시에 담아 JPA가 관리하는 것 
      • 데이터의 동일성
        • JPA "영속엔티티" 동일성을 보장해준다.
        • 1 캐시로 반복가능한 읽기(RePEATABLE READ) 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공
      • 엔티티 수정 감지
        • JPA 변경감지 기능이 있어서 "엔티티" 변경
        • JPA 자바의 Collection 변경하듯이 "값만 변경했지만update 되었다 .

                  Admin admin = em.find(Admin.class,101L);

                  admin .setName("나승후1111");

       

      프로시저 사용법 

      1. 프로시저 변수 값 지정 방법 

      작성자 Your name
      만든 날짜 Today's date
      설명 Returns employee data
      Procedure_name HumanResources.uspGetEmployeesTest
      @Param1 @LastName
      @Datatype_For_Param1 nvarchar(50)
      Default_Value_For_Param1 NULL
      @Param2 @FirstName
      @Datatype_For_Param2 nvarchar(50)
      Default_Value_For_Param2 NULL

       

       

      2. 프로시저 생성 방법 


      CREATE [ OR ALTER ] { PROC | PROCEDURE 
          [schema_name.] procedure_name [ ; number ]   
          [ { @parameter [ type_schema_name. ] data_type }  
              [ VARYING ] [ = default ] [ OUT | OUTPUT | [READONLY]  
          ] [ ,...n ]   
      [ WITH  [ ,...n ] ]  
      [ FOR REPLICATION ]   
      AS { [ BEGIN ] sql_statement [;] [ ...n ] [ END ] }  
      [;]  
        
       ::=   
          [ ENCRYPTION ]  
          [ RECOMPILE ]  
          [ EXECUTE AS Clause ]

       

      [알아보고 가요] 

      SET NOCOUNT

      Transact-SQL 문 또는 저장 프로시저의 영향을 받은 행 수를 나타내는 메시지가 결과 집합의 일부로 반환되지 않도록 합니다.

       

      3. TRANSAION ISOLATION LEVEL 설정에 대한 설명 

      https://docs.microsoft.com/ko-kr/sql/t-sql/statements/set-transaction-isolation-level-transact-sql?view=sql-server-2017

       

      4. 프로시저 전체 조회 쿼리문 

      전체프로시저 조회 방법 

      SELECT * FROM  INFORMATION_SCHEMA.ROUTINES

       

       

       

       

      참고 사이트 https://docs.microsoft.com/ko-kr/sql/t-sql/statements/set-nocount-transact-sql?view=sql-server-2017

      + Recent posts