파이썬 문자열 슬라이싱·인덱싱, 직접 삽질하며 깨달은 핵심 원리

파이썬 문자열 슬라이싱과 인덱싱은 문법 자체는 단순한데, 막상 쓰면 헷갈리는 대표적인 주제입니다. start와 end 범위가 왜 한 칸 어긋나는지, 음수 인덱스는 어디서부터 세는 건지 — 직접 코드를 쳐보면서 정리한 내용을 공유할게요.

처음 파이썬 독학할 때 문자열 다루는 게 이렇게 까다로울 줄 몰랐거든요. “Hello”에서 “ell”만 뽑아내라는 간단한 문제도 인덱스 번호가 0부터 시작한다는 걸 모르니까 계속 틀렸어요. 심지어 s[1:4]라고 쓰면 4번 인덱스가 포함 안 된다는 것도 한참 뒤에야 체감했습니다.

그때 화가 나서 케이스별로 직접 다 쳐보고 정리했는데, 그 과정이 오히려 가장 효과적이었더라고요. 오늘 글도 같은 방식으로 갑니다. 이론 먼저 장황하게 늘어놓는 게 아니라, 코드 결과를 보면서 “아 이래서 이렇구나” 하고 감 잡을 수 있게 구성했어요.

인덱싱과 슬라이싱, 대체 뭐가 다른 건지

처음에 이 두 개념이 비슷해 보여서 혼란스러웠어요. 근데 막상 구분하면 단순합니다. 인덱싱은 문자 하나를 꺼내는 것이고, 슬라이싱은 범위를 지정해서 여러 문자를 잘라내는 것이에요. 영어 단어 그대로 index는 “위치”, slice는 “조각”이니까요.

파이썬에서 문자열은 순서가 있는 시퀀스(sequence) 자료형이거든요. 각 문자마다 고유한 번호가 매겨져 있어서, 그 번호로 접근하는 게 인덱싱입니다. s = “Python”이면 s[0]은 “P”, s[1]은 “y”가 되는 식이죠.

슬라이싱은 콜론(:)을 사용해요. s[0:3]이라고 쓰면 0번부터 2번까지, 그러니까 “Pyt”가 나옵니다. 여기서 핵심은 end 인덱스가 포함되지 않는다는 건데, 이게 처음엔 정말 직관적이지 않아요. 나중에 설명하겠지만 이 설계에는 이유가 있습니다.

그리고 하나 더. 파이썬 문자열은 불변(immutable)이에요. 인덱싱으로 꺼내서 읽을 순 있지만, s[0] = “J”처럼 직접 바꾸려고 하면 TypeError가 뜹니다. 문자열을 수정하려면 슬라이싱으로 새 문자열을 조합해야 하는데, 이건 실수 모음 섹션에서 다시 다룰게요.

인덱싱 기본 — 한 글자씩 꺼내는 법

인덱싱의 출발점은 하나예요. 파이썬은 0부터 센다. 이거 머리로는 아는데 실전에서 자꾸 까먹거든요. s = “Hello”일 때 s[1]이 “e”라는 걸 이해하려면, 0번이 “H”를 차지하고 있다는 감각이 몸에 배야 합니다.

실제로 코드를 쳐보면 이렇습니다. s = “Hello”에서 s[0]은 “H”, s[1]은 “e”, s[4]는 “o”예요. 그런데 s[5]를 시도하면? 문자열 길이가 5인데 인덱스 5는 존재하지 않으니 IndexError: string index out of range가 터집니다. 처음 이 에러를 봤을 때 진짜 당황했어요.

재미있는 건 음수 인덱스도 된다는 거예요. s[-1]은 마지막 문자 “o”를 돌려줍니다. s[-2]는 “l”이고요. 이건 뒤에서 더 깊게 다루겠지만, 일단 “마지막 글자를 꺼내고 싶으면 -1을 쓴다”는 것만 기억해 두세요.

인덱싱 결과의 자료형도 중요합니다. s[0]의 결과는 “H”인데, 타입이 str이에요. 파이썬에는 별도의 char 타입이 없거든요. 길이 1짜리 문자열이 곧 한 글자입니다. C나 자바 배경이 있는 분들이 여기서 한 번 헷갈려 하더라고요.

📊 실제 데이터

파이썬 공식 문서 기준, 길이가 n인 문자열의 유효 인덱스 범위는 양수 0 ~ n-1, 음수 -n ~ -1입니다. 이 범위를 벗어나면 IndexError가 발생해요. 반면 슬라이싱에서는 범위를 초과해도 에러 없이 가능한 범위까지만 잘라줍니다 — 이 차이가 실무에서 꽤 중요하거든요.

슬라이싱 문법 start:end 제대로 이해하기

슬라이싱의 기본 문법은 s[start:end]입니다. start 인덱스부터 end-1 인덱스까지를 잘라서 새 문자열로 돌려줘요. 여기서 “end는 포함 안 됨”이 핵심인데, 처음엔 솔직히 왜 이렇게 만들었는지 의문이었어요.

나중에 찾아보니 이유가 있더라고요. s[0:3]의 결과 길이가 딱 3-0=3이 되거든요. end에서 start를 빼면 바로 슬라이싱 결과의 길이가 나오는 거예요. 그리고 s[:3] + s[3:]을 하면 원래 문자열 전체가 복원됩니다. 이런 깔끔한 수학적 성질 때문에 “end 미포함” 규칙이 채택된 거죠.

start나 end를 생략할 수도 있어요. s[:4]는 처음부터 3번 인덱스까지, s[2:]는 2번부터 끝까지입니다. 둘 다 생략한 s[:]는 문자열 전체의 복사본을 만들어요. 저는 이걸 처음 알았을 때 “이걸 어디에 쓰지?” 싶었는데, 리스트에서 얕은 복사할 때 꽤 쓰이더라고요.

그리고 아까 인덱싱에선 범위 초과 시 IndexError가 터진다고 했잖아요. 슬라이싱은 달라요. s = “Hello”일 때 s[1:100]을 해도 에러 없이 “ello”가 나옵니다. 파이썬이 자동으로 유효 범위까지만 잘라주거든요. 이 관대한 동작 덕분에 길이 체크 없이도 안전하게 슬라이싱할 수 있어요.

슬라이싱 표현 결과 (s=”freeCodeCamp”) 설명
s[0:4] “free” 0~3번 문자
s[4:] “CodeCamp” 4번부터 끝까지
s[-5:] “eCamp” 뒤에서 5글자
s[1:-4] “reeCode” 양수·음수 혼합
s[:] “freeCodeCamp” 전체 복사

음수 인덱스, 뒤에서부터 세는 감각

음수 인덱스는 파이썬의 독특한 매력 중 하나예요. 다른 언어에선 마지막 문자를 꺼내려면 s[len(s)-1]처럼 길이를 계산해야 하잖아요. 파이썬은 그냥 s[-1]이면 끝입니다. 깔끔하죠.

원리는 이래요. -1이 마지막 문자, -2가 끝에서 두 번째, 이런 식으로 뒤에서부터 번호가 매겨집니다. s = “Python”이면 s[-1]은 “n”, s[-2]는 “o”, s[-6]은 “P”가 돼요. 양수 인덱스 0과 음수 인덱스 -6이 같은 위치를 가리키는 거죠.

처음에 저를 헷갈리게 했던 게 하나 있어요. 양수는 0부터 시작하는데 음수는 왜 -0이 아니라 -1부터일까? -0은 수학적으로 0이랑 같으니까 시작점이 되어버리거든요. 그래서 뒤에서 첫 번째가 -1인 겁니다. 이걸 깨달으니까 갑자기 머릿속이 정리되더라고요.

슬라이싱에서도 음수가 자유롭게 쓰여요. s[-3:]은 뒤에서 세 글자, s[:-2]는 뒤 두 글자를 빼고 전부입니다. 실무에서 파일 확장자를 떼어내는 filename[:-4] 같은 패턴을 정말 많이 씁니다. 물론 확장자 길이가 항상 같진 않으니 rsplit이나 os.path를 쓰는 게 더 안전하긴 한데, 간단한 경우엔 슬라이싱이 훨씬 빨라요.

💡 꿀팁

음수 인덱스와 양수 인덱스를 섞어 쓸 수도 있어요. s[2:-2]처럼 쓰면 앞 2글자, 뒤 2글자를 동시에 잘라냅니다. 사용자 입력에서 앞뒤 특수문자를 제거할 때 유용한데, 이때 start가 end보다 뒤에 있으면 빈 문자열(“”)이 반환된다는 점만 주의하세요.

step과 [::-1] 뒤집기까지

슬라이싱에는 세 번째 인자가 있어요. s[start:end:step]에서 step이 바로 그것인데, 몇 칸씩 건너뛰며 문자를 가져올지를 결정합니다. 생략하면 기본값 1이고요.

s = “abcdefgh”일 때 s[::2]를 해보면 “aceg”가 나와요. 0번부터 끝까지 2칸 간격으로 문자를 뽑는 거죠. s[1::2]면 “bdfh”가 되고요. 처음 이걸 봤을 때 “이걸 대체 어디에 쓰나” 싶었는데, 데이터 전처리에서 짝수·홀수 번째 요소를 분리할 때 은근히 등장합니다.

진짜 핵심은 step에 음수를 넣을 때예요. step이 -1이면 역방향으로 한 칸씩 이동하면서 문자를 가져옵니다. s[::-1]이 문자열 뒤집기의 대표적인 관용구인 이유가 여기 있어요. start와 end를 생략했으니 전체 범위를, -1 간격으로 역순 탐색하는 겁니다.

근데 주의할 점이 하나 있거든요. step이 음수일 때 start와 end의 방향 감각이 뒤바뀝니다. s[5:1:-1]이면 5번 인덱스부터 2번 인덱스까지 역순으로 가져오는 건데, 이게 처음엔 머리가 안 돌아가요. 저도 한 3번은 직접 쳐보고 나서야 “아 end 쪽이 왼쪽이구나” 하고 받아들였습니다. 헷갈리면 일단 [::-1]로 전체를 뒤집고 나서 양수 슬라이싱으로 필요한 부분만 잘라내는 게 실수가 적어요.

코딩 테스트에서 회문(palindrome) 검사를 한 줄로 끝낼 수 있는 것도 이 문법 덕분이에요. s == s[::-1]이면 앞뒤가 같은 문자열이니 회문인 거죠. 면접에서 이걸 쓰면 면접관이 한 번 더 쳐다봅니다.

초보 시절 저를 울린 실수 모음

첫 번째로 가장 많이 당하는 건 off-by-one 에러예요. s[2:5]라고 쓰면 5번 인덱스가 포함될 거라고 기대하는 거죠. 포함 안 됩니다. end는 “거기 직전까지”예요. 이걸 의식적으로 인지하기까지 저도 최소 열 번은 틀렸어요.

두 번째. 문자열을 직접 수정하려다 터지는 TypeError. s = “Hello”에서 s[0] = “J”를 하면 ‘str’ object does not support item assignment라는 에러가 뜹니다. 파이썬 문자열은 불변이니까요. 수정하려면 슬라이싱을 이용해서 새로 만들어야 해요. s = “J” + s[1:]이라고 쓰면 “Jello”라는 새 문자열이 생성됩니다. 기존 문자열을 바꾸는 게 아니라 새 객체를 만드는 거예요.

⚠️ 주의

인덱싱으로 범위를 벗어나면 IndexError가 터지지만, 슬라이싱으로 범위를 벗어나면 에러 없이 빈 문자열이 돌아옵니다. s = “Hi”일 때 s[10:20]은 “”이에요. 에러가 안 나니까 오히려 버그를 눈치채지 못하는 경우가 있어요. 빈 문자열이 반환되어도 프로그램이 멈추지 않거든요. 디버깅할 때 이걸 꼭 의심해 보세요.

세 번째는 음수 step에서 start와 end를 거꾸로 지정하는 실수예요. s[1:5:-1]을 하면 빈 문자열이 나옵니다. step이 -1인데 start(1)가 end(5)보다 작으니까 이동할 수 있는 방향이 없는 거죠. 제대로 하려면 s[5:1:-1]이어야 해요. step의 부호 방향과 start→end 방향이 일치해야 한다는 원칙을 기억해 두면 됩니다.

네 번째. 한글 문자열에서 인덱싱이 “글자 단위”로 작동한다는 것. s = “안녕하세요”에서 s[0]은 “안”이에요. 파이썬 3에서는 문자열이 유니코드 기반이라 한글 한 글자가 인덱스 하나를 차지합니다. 파이썬 2 시절에는 바이트 기반이라 한글이 깨지는 문제가 있었는데, 이제는 걱정 안 해도 돼요.

돌이켜보면 이 실수들 전부가 “직접 쳐보지 않고 눈으로만 코드를 읽었기 때문”에 생겼어요. 슬라이싱은 진짜 터미널 열어서 하나하나 확인하는 게 최고의 학습법이더라고요. 의심스러우면 print()를 찍어보세요. 그게 제가 드릴 수 있는 가장 현실적인 조언입니다.

자주 묻는 질문

Q. 슬라이싱과 split()은 어떻게 다른가요?

슬라이싱은 위치(인덱스) 기반으로 문자열을 자르고, split()은 특정 구분자를 기준으로 나눠서 리스트를 반환합니다. 예를 들어 “a,b,c”.split(“,”)은 [“a”,”b”,”c”]가 되지만, 슬라이싱은 인덱스 번호로 잘라내는 거라 용도가 다릅니다.

Q. s[::-1] 말고 문자열을 뒤집는 방법이 있나요?

reversed() 함수를 사용한 뒤 “”.join()으로 합치는 방법이 있어요. “”.join(reversed(s)) 형태인데, 슬라이싱보다 가독성은 좋지만 속도는 약간 느립니다. 대부분의 실무 상황에서는 [::-1]이 가장 간결하고 빠릅니다.

Q. 슬라이싱 결과는 새로운 문자열인가요, 원본의 참조인가요?

새로운 문자열 객체가 생성됩니다. 파이썬 문자열은 불변이기 때문에 슬라이싱으로 만든 결과를 아무리 수정해도 원본에는 영향이 없어요. 다만 s[:]처럼 전체를 복사하는 경우, 내부 최적화로 같은 객체를 재활용할 수 있습니다.

Q. 리스트 슬라이싱과 문자열 슬라이싱은 문법이 같은가요?

네, 문법은 동일합니다. [start:end:step] 형태를 그대로 쓸 수 있어요. 차이가 있다면 리스트는 가변(mutable)이라 슬라이싱 결과에 값을 할당할 수도 있고, 결과가 리스트로 돌아온다는 점입니다.

Q. 슬라이싱할 때 step을 0으로 넣으면 어떻게 되나요?

ValueError: slice step cannot be zero 에러가 발생합니다. step이 0이면 한 자리에서 무한히 제자리걸음을 하는 셈이라 파이썬이 이를 허용하지 않아요. 양수든 음수든 0이 아닌 정수만 가능합니다.

본 포스팅은 개인 경험과 공개 자료를 바탕으로 작성되었으며, 전문적인 의료·법률·재무 조언을 대체하지 않습니다. 정확한 정보는 해당 분야 전문가 또는 공식 기관에 확인하시기 바랍니다.

마무리하며

파이썬 문자열 인덱싱과 슬라이싱은 결국 “0부터 시작”, “end 미포함”, “음수는 뒤에서부터” 이 세 가지만 체득하면 나머지는 자연스럽게 따라옵니다. step까지 익히면 문자열 뒤집기나 간격 추출도 한 줄이면 충분하고요.

코딩을 막 시작한 분이라면 오늘 당장 터미널을 열어서 아무 문자열이나 넣고 슬라이싱을 10개만 쳐보세요. 눈으로 백 번 읽는 것보다 손으로 한 번 치는 게 빠릅니다. 이미 기본은 아는데 심화가 궁금한 분이라면 step 음수 조합과 불변 객체의 메모리 동작까지 파보시면 면접에서도 자신감이 붙을 거예요.


도움이 되셨다면 댓글이나 공유 한 번 부탁드려요. 궁금한 점은 댓글로 남겨주시면 아는 선에서 답변 드리겠습니다.

댓글 남기기