본문 바로가기
C.W.K.
Stream
Lesson 03 of 12 · published

IP 주소 검증

~8 min · ip, validation

Level 0패턴 호기심
0 XP0/90 lessons0/15 achievements
0/100 XP to next level100 XP to go0% complete

단순한 후보 추출 패턴

IPv4 주소처럼 보이는 문자열은 점으로 나뉜 숫자 네 묶음으로 찾을 수 있어. \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}에 앵커를 붙이면 ^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$가 돼.

하지만 이 패턴은 실제 IP 주소가 아닌 999.999.999.999도 받아들여. 각 옥텟의 유효 범위는 0부터 255까지이기 때문이야.

엄격한 패턴

각 옥텟을 0부터 255까지로 제한하려면 다음과 같이 범위를 나눠 표현할 수 있어.

(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])

이 표현은 처음부터 [0-9]를 사용해 ASCII 숫자만 허용해. 25[0-5]는 250부터 255까지, 2[0-4][0-9]는 200부터 249까지, 1[0-9]{2}는 100부터 199까지, [1-9]?[0-9]는 0부터 99까지를 나타내.

네 옥텟과 문자열 전체의 경계를 합친 패턴은 다음과 같아.

^((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$

이 전체 패턴도 ASCII 숫자만 허용해. 다만 실서비스에서는 표준 라이브러리를 사용하는 편이 더 정확해.

표준 라이브러리에 검증 맡기기

Python의 ipaddress.ip_address(s) 같은 IP 주소 파서는 IPv4와 IPv6를 모두 다루고, CIDR 표기와 여러 예외 규칙도 알고 있어. 정규식은 IP 주소처럼 보이는 문자열을 찾는 데 사용하고, 실제로 유효한 주소인지는 전용 라이브러리로 검증해.

IPv6는 정규식으로 직접 검증하지 마

IPv6에는 16진수 그룹뿐 아니라 :: 압축과 IPv4가 섞인 표기 등 여러 형태가 있어. 이를 모두 처리하는 정규식은 길고 복잡해지면서도 유효한 형태를 빠뜨리기 쉬워. Python에서는 ipaddress, Go에서는 net.ParseIP 같은 전용 도구를 사용해.

Code

IP 패턴·python
import re

# 순진한 추출 — IP처럼 생긴 문자열만 찾고 옥텟 범위는 검증하지 않음
IP_NAIVE = re.compile(r'\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b')
re.findall(IP_NAIVE, 'server at 192.168.1.1 and 999.999.999.999')
# ['192.168.1.1', '999.999.999.999'] — 둘 다 후보로 잡힘

# 엄격한 ASCII IPv4 — 각 옥텟은 0-255
OCTET = r'(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])'
IP_STRICT = re.compile(rf'^{OCTET}\.{OCTET}\.{OCTET}\.{OCTET}$')

bool(IP_STRICT.fullmatch('192.168.1.1'))      # True
bool(IP_STRICT.fullmatch('999.999.999.999'))  # False
bool(IP_STRICT.fullmatch('256.0.0.1'))        # False
bool(IP_STRICT.fullmatch('١.2.3.4'))          # False — Unicode 숫자는 제외

# 가장 안전한 조합: 정규식으로 추출하고 라이브러리로 검증
import ipaddress
for candidate in re.findall(IP_NAIVE, 'log: 192.168.1.1 and 999.999.999.999'):
    try:
        addr = ipaddress.ip_address(candidate)
        print(f'{addr} valid')
    except ValueError:
        print(f'{candidate} not a real IP')
# 192.168.1.1 valid
# 999.999.999.999 not a real IP

External links

Exercise

로그에서 IP 주소처럼 보이는 문자열을 정규식으로 추출한 뒤 ipaddress.ip_address를 통과한 값만 출력하는 스크립트를 작성해. 잘못된 옥텟과 정상 주소가 섞인 로그에 실행해 추출과 검증의 차이를 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.