이번에는 정규식에서 가장 기본이 되는 리터럴(문자 그대로 찾기)을 배워 볼게요. 정규식이라고 하면 복잡한 기호부터 떠오르지만, 사실 가장 단순한 정규식은 '찾고 싶은 글자를 그냥 그대로 적는 것'이에요. 여기서부터 시작하면 하나도 안 어려우니 편하게 따라오세요.

02.1 리터럴이 뭐예요?

리터럴(literal)은 '특별한 뜻 없이 글자 그대로'라는 말이에요. 정규식에서 특별한 기호(\d, . 같은 것들)를 빼고 그냥 보통 글자를 적으면, 그건 '그 글자 그대로를 찾아라'라는 뜻이 돼요. 예를 들어 패턴에 cat이라고 적으면 'c 다음에 a 다음에 t가 이 순서로 붙어 있는 곳'을 찾는 거예요.


그러니까 정규식의 절반 이상은 사실 이 리터럴이에요. 특별한 기호는 '조금 더 똑똑하게 찾고 싶을 때' 양념처럼 얹는 거고, 뼈대는 그냥 우리가 아는 글자들이랍니다. 정규식이 무섭게 느껴졌다면, 이 사실 하나만으로도 마음이 한결 놓이시죠? 기호는 나중에 얹으면 되고, 지금은 이 뼈대부터 편하게 익혀요.

02.2 어디까지 그대로 찾는 거예요?

리터럴은 글자 하나만 되는 게 아니라, 여러 글자를 이어 적어도 돼요. 심지어 공백(빈칸)까지 하나의 글자로 쳐요. 예를 들어 패턴에 'good day'처럼 가운데 빈칸을 포함해 적으면, 컴퓨터는 g, o, o, d, 빈칸, d, a, y가 이 순서 그대로 붙어 있는 곳을 찾아요. 빈칸도 엄연히 한 글자라서, 하나 더 넣거나 빼면 아예 다른 패턴이 돼 버려요.


그래서 리터럴을 쓸 때는 '내가 적은 글자와 순서·개수가 정확히 같은 곳'을 찾는다고 생각하면 편해요. 이 단순한 규칙이 정규식의 바탕이고, 다른 특수 기호들은 이 바탕 위에 '조금 느슨하게', '조금 똑똑하게' 찾도록 얹어 주는 것뿐이에요.

02.3 'cat'을 찾으면 정확히 무엇이 잡혀요?

여기서 초보분들이 살짝 오해하기 쉬운 부분이 있어요. 문장에서 cat을 찾으면 딱 '고양이'라는 단어만 잡힐 것 같지만, 그렇지 않아요. 한번 볼게요.


패턴: cat

대상: cat category concatenate

매치: ['cat', 'cat', 'cat']


어라, 세 개나 잡혔죠? cat이라는 독립된 단어뿐 아니라, category의 앞부분 cat, 그리고 concatenate 속에 숨은 cat까지 전부 잡혔어요. 리터럴은 '단어 단위'가 아니라 '글자 조합 단위'로 찾기 때문이에요. c, a, t가 이 순서로 붙어 있기만 하면 그게 단어 한가운데든 어디든 다 잡아요.


파이썬 코드로는 이렇게 확인해요.


re.findall(r'cat', 'cat category concatenate')

결과: ['cat', 'cat', 'cat']


여기서 re.findall은 '패턴에 맞는 걸 전부 찾아 목록으로 돌려줘'라는 명령이에요. 처음엔 좀 낯설어도 '다 찾아서 목록으로 준다' 정도로만 알아도 돼요. 온전한 단어 cat만 잡으려면 경계라는 개념이 따로 필요한데, 지금 단계에서는 '리터럴은 글자 조합으로 잡는다'만 확실히 기억해 두면 충분해요.

02.4 대문자랑 소문자를 구별하나요?

또 하나 꼭 알아야 할 게 있어요. 정규식은 기본적으로 대문자와 소문자를 다른 글자로 구별해요. 그러니까 appleAppleAPPLE은 정규식 눈에는 전부 다른 글자예요. 대문자로 시작하는 Apple만 찾아볼게요.


패턴: Apple

대상: apple Apple APPLE

매치: ['Apple']


보시다시피 소문자 apple과 전부 대문자인 APPLE은 쏙 빠지고, 대문자 A로 시작하는 Apple 하나만 잡혔어요. 대소문자를 구별한다는 걸 모르면 '분명 apple이 있는데 왜 안 잡히지?' 하고 한참 헤맬 수 있어요. 사실 이건 정규식만의 이야기가 아니에요. 파일 이름, 비밀번호, 코드 속 변수 이름처럼 대소문자가 다르면 다른 것으로 취급하는 경우가 컴퓨터 세상엔 정말 많거든요. 그러니 초보 때 이 감각을 확실히 잡아 두면 두고두고 도움이 돼요.


재밌는 예로, 검색창에 'Apple'이라고 쳤는데 원하던 'apple 요리법' 글이 안 나와서 당황한 적 있으신가요? 대소문자를 가리는 검색이었다면 충분히 생길 수 있는 일이에요. 정규식도 똑같아서, '분명 있는데 왜 안 잡히지?' 싶을 때 대소문자부터 의심해 보면 답이 빨리 나올 때가 많답니다.

02.5 대소문자 상관없이 찾고 싶어요

그런데 실제로는 대소문자 안 가리고 다 찾고 싶을 때가 훨씬 많죠? 그럴 땐 플래그(flag, 옵션)라는 걸 켜 주면 돼요. 파이썬에서는 re.I(IGNORECASE, 대소문자 무시)를 옵션으로 넘겨요.


패턴: apple (대소문자 무시 옵션 re.I)

대상: apple Apple APPLE

매치: ['apple', 'Apple', 'APPLE']


이번엔 철자만 같으면 대소문자에 상관없이 셋 다 잡혔죠? 여기서 중요한 점 하나. 대소문자 무시는 패턴 자체를 바꿔서 하는 게 아니라, '옵션(플래그)을 켜서' 한다는 거예요. 패턴은 그대로 두고 동작 방식만 살짝 바꾸는 거죠. 파이썬 코드로는 이렇게 써요.


re.findall(r'apple', 'apple Apple APPLE', re.I)

결과: ['apple', 'Apple', 'APPLE']


맨 뒤에 re.I만 살짝 붙였을 뿐인데 결과가 확 달라졌죠? 이런 옵션이 몇 개 더 있는데, 지금은 '대소문자 무시는 re.I' 하나만 알아도 충분해요. 필요할 때 하나씩 꺼내 쓰면 되니까요.


참고로 대소문자 무시는 실생활 검색에서 특히 반가운 기능이에요. 사람들이 글을 쓸 때 Hello, hello, HELLO를 제멋대로 섞어 쓰잖아요? 그런 걸 전부 한 번에 잡고 싶을 때 re.I 하나면 해결되니, 알아 두면 정말 든든해요.

02.6 하나만 찾을까, 전부 찾을까?

같은 리터럴로 찾더라도, '몇 개를 찾느냐'는 명령에 따라 달라져요. 파이썬을 예로 들면, re.search는 패턴에 맞는 맨 처음 하나만 찾고 멈춰요. 반대로 우리가 계속 써 온 re.findall은 맞는 걸 전부 찾아 목록으로 돌려주고요.


그래서 'cat이 들어 있긴 한가?'만 궁금하면 re.search로 하나만 확인하면 되고, 'cat이 몇 번 나오나, 다 어디 있나?'가 궁금하면 re.findall로 전부 긁어오면 돼요. 똑같은 패턴이라도 찾는 목적에 맞게 도구를 골라 쓰는 거죠. 지금은 '하나만 볼지 전부 볼지 고를 수 있다' 정도만 알아 두면 충분해요.

02.7 오늘 배운 내용 정리

정리해 볼게요. 가장 단순한 정규식은 리터럴, 즉 찾고 싶은 글자를 그대로 적는 거예요. 이때 리터럴은 내가 적은 글자와 순서·개수가 똑같은 곳을 찾고, '단어 단위'가 아니라 '글자 조합 단위'로 잡아요. 그래서 cat은 category나 concatenate 속의 cat까지 전부 잡히는 거예요.


또 정규식은 대소문자를 구별하기 때문에 Appleapple은 서로 다른 글자로 보고요. 대소문자 안 가리고 찾고 싶으면 re.I 같은 플래그(옵션)를 켜면 돼요. 그리고 '몇 개를 찾을지'는 re.search(맨 처음 하나)와 re.findall(전부)로 골라 쓸 수 있다는 것도 배웠고요. 오늘 배운 리터럴은 모든 패턴의 뼈대가 되니, 편하게 여러 번 소리 내어 읽어 두시면 좋아요. 여기까지 오셨으면 정규식의 기초 절반은 이미 손에 넣으신 거예요. 어렵지 않죠?