Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

파이썬으로 IP 주소 유효성 검사하기: IPv4/IPv6 판별 방법


문자열이 하나 주어졌을 때, 해당 입력이 유효한 IPv4 주소인지, IPv6 주소인지, 아니면 둘 다 아닌지 판별해야 합니다. 이 글에서는 문제의 조건을 정리하고, 파이썬으로 이를 해결하는 알고리즘과 예제 코드를 소개합니다.

IPv4와 IPv6 주소 형식 이해하기

IPv4 주소 형식

IPv4 주소는 점으로 구분되는 십진수 표기법(dotted-decimal notation)으로 표현됩니다. 즉, 0부터 255 범위의 십진수 네 개가 점(".")으로 구분된 형태입니다. 예를 들어 192.168.254.1은 유효한 IPv4 주소입니다.

단, 각 자리의 선행 0(leading zero)은 허용되지 않습니다. 따라서 192.168.254.01처럼 앞에 불필요한 0이 붙은 주소는 유효하지 않습니다.

IPv6 주소 형식

IPv6 주소는 16비트를 나타내는 4자리 16진수 여덟 개의 그룹으로 구성되며, 각 그룹은 콜론(":")으로 구분됩니다. 예를 들어 2001:0db8:85a3:0000:0000:8a2e:0370:7334는 유효한 IPv6 주소입니다.

또한 각 그룹 내에서 일부 선행 0을 생략할 수 있고, 16진수 문자는 대소문자를 혼용할 수 있습니다. 따라서 2001:db8:85a3:0:0:8A2E:0370:7334 역시 유효한 주소입니다.

다만, 이 문제에서는 단순화를 위해 연속된 0 그룹을 두 개의 콜론(::)으로 축약하는 표기를 허용하지 않습니다. 따라서 2001:0db8:85a3::8A2E:0370:7334는 유효하지 않은 IPv6 주소로 처리됩니다. 아울러 그룹당 자릿수를 초과하는 선행 0도 허용되지 않으므로, 02001:0db8:85a3:0000:0000:8a2e:0370:7334 역시 유효하지 않습니다.

해결 접근 방법

이 문제는 다음 단계로 해결할 수 있습니다.

  • checkv4(x) 메서드 정의: x가 0 이상 255 이하의 범위에 속하면 true를, 그렇지 않으면 false를 반환합니다.

  • checkv6(x) 메서드 정의: 다음 규칙으로 동작합니다.

    • x의 길이가 4보다 크면 false를 반환합니다.
    • x의 10진수 변환값이 0 이상이고 첫 문자가 '-'가 아니면 true를, 그렇지 않으면 false를 반환합니다.
  • 메인 로직:

    • 입력 문자열에 점(.)이 정확히 3개 있고, 분리된 모든 부분이 checkv4를 통과하면 "IPv4"를 반환합니다.
    • 입력 문자열에 콜론(:)이 정확히 7개 있고, 분리된 모든 부분이 checkv6를 통과하면 "IPv6"를 반환합니다.
    • 두 조건을 모두 만족하지 않으면 "Neither"를 반환합니다.

예제 코드 (Python)

아래 구현 예제를 통해 더 잘 이해해 보겠습니다.

class Solution(object):
    def validIPAddress(self, IP):
        """
        :type IP: str
        :rtype: str
        """
        def isIPv4(s):
            try: return str(int(s)) == s and 0 <= int(s) <= 255
            except: return False
        def isIPv6(s):
            if len(s) > 4:
                return False
            try: return int(s, 16) >= 0 and s[0] != '-'
            except:
                return False
        if IP.count(".") == 3 and all(isIPv4(i) for i in IP.split(".")):
            return "IPv4"
        if IP.count(":") == 7 and all(isIPv6(i) for i in IP.split(":")):
            return "IPv6"
        return "Neither"

ob = Solution()
print(ob.validIPAddress("172.16.254.1"))

실행 결과

입력

"172.16.254.1"

출력

"IPv4"

참고: ipaddress 모듈 활용하기

실무 환경에서는 Python 3.3부터 제공되는 표준 라이브러리 ipaddress 모듈을 사용하면 훨씬 간편하게 IP 주소를 검증할 수 있습니다.

import ipaddress

def validate_ip(ip):
    try:
        ipaddress.IPv4Address(ip)
        return "IPv4"
    except ValueError:
        pass
    try:
        ipaddress.IPv6Address(ip)
        return "IPv6"
    except ValueError:
        return "Neither"

print(validate_ip("172.16.254.1"))   # IPv4
print(validate_ip("2001:db8::1"))    # IPv6
print(validate_ip("256.100.50.25"))  # Neither

다만 ipaddress 모듈은 :: 축약 표기 등 실제 인터넷 표준(RFC 5952)에서 허용되는 형식까지 포괄적으로 처리하므로, 코딩 테스트처럼 축약 표기를 금지하는 등 엄격한 규칙이 요구되는 경우에는 위에서 소개한 수동 검증 방식을 사용하는 것이 좋습니다.