문자열이 하나 주어졌을 때, 해당 입력이 유효한 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)에서 허용되는 형식까지 포괄적으로 처리하므로, 코딩 테스트처럼 축약 표기를 금지하는 등 엄격한 규칙이 요구되는 경우에는 위에서 소개한 수동 검증 방식을 사용하는 것이 좋습니다.