파이썬 문자열은 한 번 만들어지면 내부의 글자를 바꿀 수 없는 불변(immutable) 자료형이에요. 메서드를 쓰면 원본이 바뀌는 게 아니라 새 문자열이 나오니까 반드시 변수에 다시 저장해야 해요.
split()으로 문자열을 쪼개서 리스트로 만들고, join()으로 리스트 요소들을 다시 하나의 문자열로 쉽게 합칠 수 있어요.
문자열 안에 변수나 계산식을 집어넣고 서식을 맞출 때는 직관적인 f-string을 사용하는 것이 제일 편하고 좋아요.
실무에서는 데이터에 빈 값(None)이나 숫자가 섞여 들어올 수 있으니, try-except 예외 처리로 런타임 에러를 방지하는 방어 로직을 꼭 짜야 해요.
목차
- 먼저 알아야 할 것: 문자열은 수정이 안 돼요 (불변성)
- 1. 쪼개고 합치기: split()과 join()
- 2. 데이터 정제와 변환: strip, replace, upper/lower
- 3. 문자열 포매팅의 정답: f-string
- 4. 문자열 검색과 검증: find() vs index(), startswith
- 5. 실무 필수 팁: 예기치 못한 비정상 데이터 방어하기
- 6. 초보자가 자주 하는 실수 요약
- 자주 묻는 질문
먼저 알아야 할 것: 문자열은 수정이 안 돼요 (불변성)
파이썬 코딩을 시작하고 텍스트 데이터를 다루다 보면, 가장 먼저 당황하게 되는 순간이 있어요. 바로 문자열의 특정 글자를 콕 집어서 바꾸려고 할 때 발생하는 에러예요. 인덱스로 접근해서 그 부분만 딱 바꾸면 되는 거 아니냐고 생각해보셨나요? 저도 처음에 그렇게 생각했거든요. 하지만 파이썬에서 문자열은 불변(Immutable) 객체예요. 한 번 메모리에 만들어지면, 그 안의 내용물은 절대 바꿀 수 없도록 꽉 잠겨버리는 거죠.
불변성이라는 특성은 메모리 관리나 보안 측면에서는 아주 효율적이고 좋지만, 텍스트를 조금 수정해야 하는 우리 입장에서는 꽤 번거롭게 느껴질 수 있어요. 원본의 글자를 직접 뜯어고칠 수 없기 때문에, 무조건 기존 것을 복사하거나 잘라서 새로운 문자열을 만든 뒤 변수에 덮어쓰는 방식을 사용해야만 해요.
이처럼 원본은 절대로 훼손되지 않아요. 어떤 화려한 메서드를 사용해서 텍스트를 다루더라도, 원본 문자열은 처음 만들어진 그 모습 그대로 유지돼요. 새로 가공된 결과물은 허공에 둥둥 떠 있는 상태가 되기 때문에, 우리가 사용할 변수에 꼭 다시 담아줘야 해요.
❗ 중요
문자열을 변형하는 어떤 함수나 메서드를 쓰더라도 원본은 절대 바뀌지 않습니다. 변경된 값을 사용하려면 반드시 기존 변수에 재할당하거나 새로운 변수에 저장해야만 동작해요.
1. 쪼개고 합치기: split()과 join()
데이터 분석을 하거나 웹 크롤링을 해보셨나요? 외부에서 가져온 텍스트 데이터는 우리가 코딩하기 편하게 예쁘게 잘려있지 않아요. 엑셀에서 뽑아낸 CSV 파일만 봐도 모든 데이터가 쉼표 하나에 의지해서 쭈르륵 붙어있죠. 이 거대한 텍스트 덩어리를 우리가 다루기 쉬운 형태로 요리하려면 어떻게 해야 할까요? 바로 여기서 쪼개고 합치는 마법의 메서드 두 가지가 등장해요.
split() 메서드는 말 그대로 문자열을 특정 기준에 따라 쪼개서 리스트라는 바구니에 차곡차곡 담아줘요. 괄호 안에 특정 기호를 넣으면 그 기호를 칼날 삼아 문자열을 토막 내죠. 반대로 join() 메서드는 흩어져 있는 리스트의 요소들을 하나의 문자열로 쫙 이어 붙여주는 풀 역할을 해요.
재미있는 점은 split()은 문자열을 리스트로 만들고, join()은 리스트를 문자열로 만든다는 거예요. 이 둘은 데이터를 분해하고 다시 조립하는 과정에서 항상 짝꿍처럼 같이 다니니까 무조건 세트로 묶어서 외워두는 게 좋아요.
💡 Tip
split() 괄호 안에 아무런 기호도 넣지 않고 그냥 실행하면 스페이스바, 탭, 엔터 같은 모든 공백 문자들을 알아서 무시하고 아주 깔끔하게 단어 단위로 쪼개줍니다. 문장 분석할 때 최고의 방법이에요.
2. 데이터 정제와 변환: strip, replace, upper/lower
사용자가 직접 입력한 데이터를 그대로 믿고 코드를 짜시나요? 절대 그러시면 안 돼요. 회원가입 폼을 만들다 보면 아이디 뒤에 무의식적으로 스페이스바를 꾹 눌러서 공백을 넣는 분들도 있고, 영문 대소문자를 자기 마음대로 섞어 쓰는 분들도 정말 많아요. 이런 지저분한 데이터를 그대로 데이터베이스에 넣거나 조건문으로 비교하려고 하면 백발백중 버그가 터집니다. 그래서 본격적인 작업에 들어가기 전에 텍스트를 깨끗하게 씻겨주는 정제 과정이 필수예요.
가장 먼저 써야 할 메서드는 strip()이에요. 이 녀석은 문자열의 맨 앞과 맨 뒤에 지저분하게 묻어있는 띄어쓰기나 줄바꿈 문자를 싹 지워줘요. 그리고 대소문자가 뒤죽박죽 섞여 있다면 lower()를 써서 전부 소문자로 통일하거나, upper()로 대문자로 쫙 맞춰주세요. 이렇게 기준을 하나로 맞춰야 파이썬이 “Yes”와 “yes”를 다르다고 인식하는 억울한 상황을 막을 수 있어요. 만약 단어를 통째로 교체해야 한다면 replace()를 쓰면 되고요.
이 세 가지 메서드만 순서대로 잘 조합해도 실무에서 마주치는 지저분한 텍스트 데이터의 90% 이상은 아주 깔끔하게 다듬을 수 있어요. 데이터를 비교하거나 저장하기 전에는 습관처럼 이 메서드들을 한 번씩 거치도록 코드를 작성하는 게 좋아요.
3. 문자열 포매팅의 정답: f-string
문자열 중간중간에 변수 값을 끼워 넣어야 할 때 보통 어떻게 하시나요? 혹시 아직도 더하기(+) 기호로 텍스트 조각과 변수를 주렁주렁 엮어서 긴 기차를 만들고 계시지는 않죠? 파이썬 3.6부터 도입된 f-string을 한 번 써보시면, 예전 방식으로 절대 돌아가고 싶지 않으실 거예요. 그만큼 직관적이고 강력하거든요.
사용법은 정말 눈물 날 정도로 간단해요. 문자열을 감싸는 따옴표 바로 앞에 소문자 ‘f’를 하나 톡 붙여주세요. 그리고 변수나 계산식이 들어가야 할 자리에 중괄호 {}를 열고 그 안에 이름을 바로 적어주기만 하면 끝이에요. 예전에 .format()을 쓰거나 % 기호 위치를 일일이 세어가며 맞추던 시절의 복잡함은 이제 완전히 잊으셔도 좋아요.
특히 돈을 표기할 때 천 단위마다 콤마를 찍거나, 소수점 자릿수를 딱 맞춰야 할 때 f-string의 서식 지정 기능은 엄청난 빛을 발해요. 코드를 처음 보는 사람도 문맥을 한눈에 파악할 수 있으니, 텍스트를 조립해야 하는 상황이라면 무조건 이 방식을 최우선으로 쓰세요.
📌 Note
f-string은 코드를 쓰기 편하고 예쁘게 만들어주는 것뿐만 아니라, 파이썬에 존재하는 다른 문자열 포매팅 방식들보다 실행 속도도 가장 빠르다는 엄청난 장점이 있어요. 성능 면에서도 압도적이에요.
4. 문자열 검색과 검증: find() vs index(), startswith
수십, 수백 줄의 긴 텍스트 안에서 내가 원하는 단어가 어디 있는지 콕 집어 찾거나, 다운로드한 파일 이름이 정확히 ‘.pdf’로 끝나는지 확인해야 할 때가 있어요. 이때 굳이 for문을 돌리면서 복잡하게 로직을 짤 필요 없이 파이썬이 기본으로 제공하는 메서드들을 쓰면 단 한 줄로 순식간에 해결돼요.
먼저 문자열의 시작과 끝을 검증할 때 쓰는 startswith()와 endswith()가 있어요. 이름 그대로 우리가 원하는 문자로 시작하는지, 끝나는지를 True나 False로 친절하게 알려주죠. 웹 크롤링할 때 URL이 ‘https’로 시작하는지 체크할 때 아주 찰떡처럼 쓰이는 메서드예요.
그럼 특정 단어가 중간 어디쯤 숨어있는지 찾을 때는 어떨까요? 이때는 find()와 index() 두 가지를 쓸 수 있는데, 이 둘의 차이점을 정확히 아는 게 핵심 중의 핵심이에요. 둘 다 단어가 있는 인덱스 번호를 반환해 주는 건 똑같아요. 그런데 만약 찾는 단어가 텍스트 안에 아예 없을 때의 행동이 완전히 달라져요.
find()는 찾는 단어가 없으면 ‘-1’을 던져주니까, 값이 없는 상황이 자연스러운 조건문 분기 중 하나라면 이 메서드를 쓰시면 돼요. 반면에 index()는 그 단어가 무조건 존재해야만 하는 필수 조건인데 누락되었을 때 씁니다. 바로 에러를 터뜨려야 시스템의 더 큰 오작동을 막을 수 있으니까요.
⚠️ Warning
웹에서 긁어온 정제되지 않은 데이터에서 index()를 무턱대고 쓰면, 예상치 못한 텍스트 누락으로 인해 전체 프로그램이 뻗어버릴 수 있으니 상황에 맞게 주의해서 사용해야 해요.
5. 실무 필수 팁: 예기치 못한 비정상 데이터 방어하기
지금까지 배운 문자열 메서드들, 참 유용하고 편리하죠? 그런데 우리가 실무에서 데이터베이스나 엑셀 파일, 혹은 외부 API에서 데이터를 왕창 끌어올 때는 책에서 보던 것처럼 예쁘고 완벽한 문자열만 들어오지 않아요. 중간에 뜬금없이 숫자가 섞여 있기도 하고, 아예 값이 텅 비어있는 ‘None’이 떡하니 자리 잡고 있을 수도 있어요.
이런 비정상적인 데이터에 대고 무작정 .split()이나 .upper() 같은 문자열 전용 메서드를 날리면 어떻게 될까요? 파이썬은 “어? 숫자나 None에는 그런 기능 없는데?” 하면서 가차 없이 AttributeError나 TypeError를 띄우고 전체 시스템을 멈춰버려요. 그래서 실무에서는 반드시 이런 예기치 못한 폭탄 데이터가 들어올 상황을 방어하는 예외 처리 로직을 깔아둬야 마음 편히 잘 수 있어요.
위 코드처럼 try-except 블록으로 문자열 메서드가 실행되는 위험한 구역을 감싸주면, 이상한 데이터가 튀어나와도 프로그램이 죽지 않고 부드럽게 다음 데이터로 넘어가게 할 수 있어요. 실무에서 뻗지 않는 튼튼한 코드를 만들고 싶다면 이 방어 로직은 선택이 아니라 무조건 필수예요!
6. 초보자가 자주 하는 실수 요약
문자열을 다루다 보면 이제 막 코딩을 시작한 초보자분들, 심지어 가끔은 경력자들도 피곤하면 무심코 저지르는 자잘한 실수들이 있어요. 그중에서 가장 대표적이고 사람을 화나게 만드는 두 가지 상황을 짚어 드릴게요. 문자열을 가공할 때 에러 없이 안전하게 작업하려면, 아래의 단계별 올바른 작업 순서를 항상 머릿속에 기억해 두고 코드를 짜야 해요.
내가 다루려는 변수가 정말 순수한 문자열이 맞는지부터 확인하세요. 리스트나 정수, None이 들어있다면 아무리 좋은 문자열 메서드도 먹히지 않고 바로 에러를 뱉어냅니다.
리스트의 요소들을 합칠 때 무심코 리스트.join()이라고 쓰는 분들이 정말 많아요. 합치는 데 쓸 접착제 역할인 문자열 기호가 주어라는 점을 절대 잊지 마세요.
문자열의 불변성 규칙에 따라, 메서드 실행 결과로 튀어나온 ‘새로운 문자열’은 기존 변수나 아예 새로운 변수에 반드시 다시 할당해줘야 허공으로 날아가지 않아요.
이 세 가지 스텝만 잘 지켜도 어이없는 실수는 99% 막을 수 있어요. 자주 하는 실수 코드를 직접 보면서, 내 코드에 이런 부분이 없는지 한 번 점검해 보세요.
방금 고친 코드처럼 메서드 호출 후에는 변수에 꼭 덮어쓰고, join을 쓸 때는 리스트가 아니라 문자열 기호가 주인공이라는 사실, 이제 절대 안 까먹으시겠죠?
자주 묻는 질문
Q. 크롤링이나 데이터 수집 중 값이 비어있거나 None일 때 문자열 메서드를 쓰면 에러가 납니다. 어떻게 해결하나요?
데이터가 정말 순수한 문자열인지 먼저 확인하는 절차가 필요해요. isinstance(데이터, str) 코드를 사용해서 데이터가 문자열일 때만 메서드가 동작하게 if문으로 분기를 짜주세요. 아니면 본문에서 설명해 드린 것처럼 try-except 블록을 사용해서 AttributeError나 TypeError가 날 때 프로그램이 멈추지 않고 빈 문자열(“”)을 반환하도록 예외 처리를 해주면 아주 깔끔하게 해결됩니다.
Q. 특정 문자를 찾을 때 find()와 index() 중 어떤 것을 써야 할까요?
찾는 문자가 없을 때 여러분의 프로그램이 어떻게 행동해야 하는지에 따라 선택이 달라져요. 문자가 없으면 그냥 건너뛰고 다른 작업을 하도록 부드럽게 넘어가야 한다면 -1을 돌려주는 find()를 쓰시는 게 맞아요. 반대로, 그 문자가 없는 상황 자체가 프로그램에 치명적인 문제라서 당장 실행을 멈추고 에러 로그를 남겨야 한다면 자비 없이 예외를 뱉어내는 index()를 사용하는 게 올바른 대처법이에요.
Q. 문자열의 공백을 제거하려고 text.strip()을 작성했는데, 다시 출력해보면 공백이 안 지워지고 그대로 있습니다. 이유가 뭔가요?
파이썬의 문자열은 절대 변경할 수 없는 불변(immutable) 객체라서 그래요. strip() 같은 메서드는 원본 문자열의 공백을 직접 지우는 게 아니라, 공백이 깔끔하게 지워진 ‘새로운 문자열’을 만들어서 결과로 던져주는 역할만 해요. 그래서 text = text.strip() 처럼 그 새롭게 만들어진 문자열을 변수에 다시 담아주지 않으면 그냥 허공으로 날아가 버리고 원본만 남게 되는 거예요.
Q. 리스트 요소들을 합치려고 words.join(‘-‘)을 썼더니 AttributeError가 발생해요. 도대체 무엇이 문제인가요?
join()은 리스트가 가지고 있는 기능이 아니라 문자열 객체가 단독으로 가지고 있는 기능이에요. 그래서 리스트 변수에다 점을 찍고 부르면 당연히 에러가 나죠. 합칠 때 접착제로 사용할 연결 문자열(여기서는 하이픈 “-“)을 먼저 쓰고, 그 뒤에 점을 찍어 "-".join(words) 형태로 써야만 정상적으로 동작합니다. 주어와 목적어의 위치가 바뀌었다고 생각하시면 편해요.