첫 파이썬 백엔드 개발자 면접
첫 파이썬 백엔드 개발자 면접
SSAFY 잡페어를 통해 지원한 회사에 면접을 다녀왔습니다!
건축공정관리 솔루션 스타트업으로, Flask/FastAPI가 아닌 Django을 꽤 써본 사람을 찾는 것 같았지만,
프레임워크야 어차피 들어가서 또 회사 입맛에 맞게 배워야 하는 거니
그냥 파이썬 잘한다 어필만 하자는 생각으로 갔습니다!
그리고 생각보다 잘 봤습니다! (진짜로 파이썬만 깊게 물어봄)
인성질문 먼저
당연히 자기소개와 마지막 할 말, 질문은 있었습니다!
인성 질문은 세 분의 면접관 중 프론트 두 분이 끝까지 아무런 질문을 안 할 수 없으니
중간 중간 비어보이는 타임마다 들어왔습니다.
1. 싸피에 코치까지 해놓고 소마까지 간 이유? (특이한 경력이라 하는 걸 보면 아마 소마가 뭔지 아시겠지)
NLP와 AI에 대한 관심으로 개발을 시작해, 싸피에 코치까지 했으나, 취업은 여전히 어느 방향으로 해야할지 고민이 많았다.
소마를 통해 기술적인 역량도 높이고, 진짜로 서비스를 운영하며 뭘 하고 싶은지 찾으려고 가봤다.
2. 개발자로써 본인에게 부족한 점, 개선할 방향
욕심이 있어 하고 싶은 것만 하는 경향이 있다. 그래서 파이썬을 깊게 팠다…
그래도 프로젝트를 위해서는 팀에 협력하는 게 맞고, 욕심을 버리고 하는 편이다.
3. 프로젝트 진행 성과 (기술보단 인성과 찐 성과 위주로 대답했습니다.)
싸피에서 진행한 프로젝트 1, 2, 3마다 어떤 걸 얻었는지 대답했습니다.
첫 번째에선 이런 팀프로젝트가 처음이니, 전공자 팀원들의 도움을 받아 협업과 프로젝트 감각을 쌓았다. 우수상도 수상했다.
두 번째에선 첫 번째 경험을 바탕으로 팀장으로 프로젝트를 진행했다. 그런데 2번의 문제 때문에 혼자만 내 기술에 너무 심취했었다.
아쉬움이 많이 남아서, 세 번째 프로젝트는 정말 협업을 강화하여 팀 다운 팀을 만들고 스크럼 마스터로 이끌어나갔다.
5주만에 프로토타입 개발을 마치고 플라워샵에서 실제 손님들에게 서비스 시연을 했다. 우수상도 받았고.
4. 프로젝트마다 부족했던 점, 발전해나갈 방향을 어떻게 설계하는가?
아쉬운 부분은 항상 회고를 하고, 읽어보면서 다음에는 아쉬움이 없으려고 노력하는 편이다.
두 번째 프로젝트의 아쉬운 점도 다시 언급.
기술 질문
1. 파이썬 3.13 버전을 써봤다고 했는데, 어떻게 썼는가?
주로 Python 백엔드는 AI 모델에 요청을 주고, 결과를 반환하는 방식으로 썼다.
이러한 경우, 요청이 처리되기까지 2~3초가 걸리는데 멀티 프로세싱 방식으로는 동시에 처리 가능한 양이 2~3개 수준이다.
그러나 3.13에서 추가된 멀티 스레딩을 활용하면 동시에 더욱 많은 요청을 처리할 수 있었다.
- 그런데 이건 굳이 멀티스레딩 말고 코루틴으로도 처리 가능한 수준 아니겠는가?
유일하게 말 문이 완전히 막힌 질문이었다.
FastAPI에서 AsyncIO를 활용하긴 했으나, 직접 코루틴을 만들지는 않아서 잘 모르겠다고 답했다.
만약 네트워크 IO가 발생하는(비동기 요청이 가능한 외부 API라면)
멀티스레딩도 필요없이 코루틴 수준에서 훨씬 많은 요청을 처리할 수 있다.
이 부분은 확실히 틀린 답변을 했던 것 같다.
2. 안정화 전까진 안 쓴다고 했는데, 왜인가?
3.13에서 도입된 멀티스레딩은 어디까지나 실험적 기능이다.
공식 docs에서도 현재 버전의 멀티스레딩은 실험적 기능이라 프로덕션 환경에서 사용하면 안 된다고 못을 박아두었다.
그렇기에 개인적으로 신기능을 실험하는 수준에서 활용해본 것이다.
3. GIL에 대해서 알고 있는가?
GIL은 Global Intepreter Lock으로, 파이썬 프로세스를 무조건 싱글 스레드 환경으로 만드는… 제약이다!
(제약보단 안전 장치에 가깝겠죠…)
4. GIL이 왜 생긴 것 같은가?
도입 이유에 대해서는 까먹은 상태였다. 그래서 기능적 특성보단 파이썬의 등장 배경에 대해서 이야기했다.
파이썬 자체가 ABC언어를 계승하여, 배우고 만들기 쉬우며, 생산성있는 언어를 지향했다.
GIL이 없을 경우, 개발자는 메모리 관리에 보다 많은 신경과 관리를 요하기 때문에 생산성이 떨어졌기 때문에
파이썬의 창시자 귀도 반 로썸이 처음부터 만들어 넣은 것 같다.
(면접이 나쁘지 않았다고 생각이 들었던 이유가 여기였습니다.
백엔드 면접관님은 내가 분명 답을 아는데 기억이 안 나는 것이라 생각한 것 같았습니다.)
- 조금 아쉬우니 힌트를 주겠다. 파이썬의 GC를 생각해보아라!
(사실 이 때까지도 잘 기억이 안 나서, 파이썬의 GC부터 혼잣말로 중얼거렸습니다.)
파이썬의 GC(라곤 하지만 메모리 자동 관리 프로세스)는 레퍼런스 카운팅과 GC로 이루어져있다.
- 바로 그겁니다. 레퍼런스 카운팅
(여기서 조금 생각이 났습니다!)
레퍼런스 카운팅은 기본적으로 싱글 스레드 환경을 상정하여 메모리 공간에 대한 카운팅을 진행하기 때문에,
멀티 스레딩 환경에서는 제대로 동작하기 힘들 것이다.
본격적인 GC가 이루어지려면, 레퍼런스 카운팅이 이루어져야 하기 때문에 메모리 누수가 발생할 가능성이 매우 높아진다!
(사실 이 답변도 70점 짜리입니다…)
- 정확히는 말이죠.
파이썬의 객체와 해당 객체에 대한 레퍼런스 카운팅은 힙 영역에 저장됩니다,
멀티 스레딩은 기본적으로 스택을 제외한 코드, 힙, 데이터 영역은 프로세스 수준에서 공유합니다.
멀티 스레딩 환경에서 접근할 경우, 힙 영역에 존재하는 레퍼런스 카운팅에 대한 경쟁 상태(Race Condition)가 생길 수 있습니다.
따라서, 파이썬에서 GIL을 해제한다는 건, OS수준에서의 코어 코드의 변경이 필요하기 때문에
멀티 스레딩 환경이 기본이 된 현재에서도 쉽게 할 수 없었던 작업인 것입니다.
5. 다양한 프레임워크를 써본 것 같은데, 주요 프레임워크에 대해 비교하며 설명 부탁한다.
Flask, FastAPI, Django 수준으로 설명했다.
Flask의 경우, 경량 프레임워크이기 때문에 서버를 구축하는 게 짧은 코드로 가능하다.
특히, AI 요청을 보내고 결과를 반환하는 작업은 100줄 이하의 코드로도 가능할 정도다.
이러한 방식에 대한 사용 경험이 많은 편이다.
FastAPI의 경우, 전체적인 코드는 Flask와 비슷하여 개발 속도가 매우 빠르다.
그리고 비동기 처리와 타입 힌팅을 거의 강제적으로 지원하기에, 현대적인 서버 개발에 잘 맞는 편이다.
Django는 앞선 두 프레임워크보다 등장 시기가 매우 이르며, 기본적으로 MTV(Model-Template-View) 패턴을 사용한다.
템플릿(HTML) 파일 자체를 반환하는 방식으로, 현대의 백엔드 서버의 대표 사양인 JSON 반환은 제대로 지원하지 않기 때문에
Django Rest FrameWork(DRF)가 등장하게 되었다.
또한 Admin 기능이 매우 쉽고 간단하면서 강력하기 때문에,
프로젝트를 진행하며 개발자가 DB에 직접 접근하지 않고 데이터를 수정할 수 있도록
Django를 활용해 어드민 시스템을 개발하여 프론트엔드 팀원들이 쉽게 쓸 수 있도록 만든 경험이 있다.
6. Django ORM과 SQLAlchemy 중 무엇을 더 선호하는가?
(여기선 쓸 데 없이 장고를 잘 안 써봤다는 말을 했습니다. 굳이 할 필요 없었는데!
그리고 쓸 데 없이 말을 길게 했습니다. 당황한 게 티 났을 것 같네요…)
Django에 대한 경험이 많지는 않기 때문에 Django ORM을 제대로 말하긴 힘들 것 같다.
그러나 대체적으로 두 라이브러리 다 비슷하게 돌아가는 걸로 알고 있다.
개인적으로 Django ORM은 SQLAlchemy에 비해 제약이 많다고 생각하여, SQLAlchemy를 선호하고, 많이 사용했었다.
(사실 Flask, FastAPI에서 Django ORM은 끌고와서 쓰기 힘들죠…)
7. 커넥션 풀 문제가 있었다고 했는데, 정확히 어떤 문제고 어떻게 해결했는가?
(이력서에 적힌 내용을 보고 이야기해주셨습니다. 오~ 이런 문제도 겪었구나 하는 표정이셨습니다.)
MySQL의 경우, 기본적으로 커넥션의 지속시간이 6시간이다.
그러나 SQLAlchemy의 경우, 별도의 설정이 없으면 무한정으로 지속된다.
MySQL의 커넥션이 해제된 이후에도 SQLAlchemy에선 확인할 방도가 없어,
이전에 생성된 커넥션을 활용해 데이터를 보내게 되는데, MySQL은 이를 허용하지 않으므로 에러가 발생한다.
그러나 다음 요청부터는 새로운 커넥션을 생성해 요청을 보내므로 정상적으로 동작하는 것처럼 보인다.
이러한 문제는 여러 방법으로 해결할 수 있는데,
모든 쿼리 요청마다 SELECT 1 같은 가벼운 쿼리를 보내 커넥션 상태를 확인하고, 강제로 갱신하는 방법이다.
당연히 아무리 가벼운 요청이어도 요청의 수가 결과적으로 2n이 되기 때문에 오버헤드가 발생할 거라 판단해 쓰지 않았다.
다른 방법으로 engine을 설정할 때, 커넥션의 지속 시간을 설정하여 오래된 커넥션은 해제하는 방식인데,
문제 해결에는 이 방식을 사용했다.
- 두 개의 방법 말고 하나 더 있을 것 같다.
(엥? 여기까지 말했는데 또 말하라고? 뭔가 원하는 답변이 있는 것 같았습니다.)
모든 요청마다 커넥션을 새로 생성하는 방법도 있는데, 이건 앞선 두 방법보다 오버헤드가 훨씬 크기 때문에
아예 사용하지 않는 방법인 걸로 알고 있다.
(더 묻진 않으셨습니다. 정답이거나, 아예 “아 이건 모르나보다 구나” 중 하나겠죠..)
9. Django ORM에는 prefetch, seleted related가 있다. 각각의 차이에 대해 설명해달라.
(꽤 어려운 질문이었습니다… 앞서 말했듯 Django ORM은 경험이 부족한 편이라,
저번 토스 과제 전형 때 썼던 프리패치에 대해서만 설명했습니다.)
prefetch related는 N+1 문제를 해결하기 위한 방법으로 알고 있다.
연관관계로 묶인 데이터를, 여러 번의 쿼리로 가져오는 게 아니라, 한 번에 모두 가져오는 방법으로 알고 있다.
seleted related에 대해서는 잘 모르겠다.
- 둘 다 N+1 문제를 해결하기 위한 것인데, prefetch는 N:M 관계, selected는 1:1 관계에서 쓰는 것이다.
(라고 답변을 정정해주셨습니다!)
10. Github actions, AWS ECR, Docker로 CI/CD를 구축했다고 했는데, 프로세스를 설명해달라.
(대답을 하긴 했지만, 조금 중구난방으로 길게 대답했습니다.)
프로젝트 루트 디렉토리에서 워크 플로우 파일에 프로세스를 작성한 뒤,
develop, main 브랜치에 푸시가 생길 경우, 워크 플로우 프로세스를 실행한다.
github 측에서 일단 docker 이미지를 빌드한 뒤 AWS ECR 프라이빗 레포지토리에 도커 파일을 올린다.
그리고 ssh를 통해 ec2에 접근하여, 환경 변수 파일을 만들고 ecr 레포지토리의 도커 이미지를 다운받아 실행한다.
사용했던 보안 요소인 환경 변수 파일을 삭제한다.
- 또다른 방법이 있지 않을까?
(여기서 조금 벙쪘습니다. 뭘 말해달라는 것이지?! 무중단 배포 같은 걸 원했던 걸지도 모르겠네요…)
jenkins를 쓸 수도 있고, 서버에서 직접 빌드하는 방식도 있다.
그러나 서버에서 직접 빌드할 때, ec2의 성능을 낮은 걸 쓰다보니 jar 파일 같은 걸 직접 빌드하면 서버가 터지는 문제가 있었다.
그래서 github actions를 활용했었다.
- EC2를 쓰셨다고 했는데, 그럼 ppk나 pem키 같은 거 필요한데, 어떻게 했는가?
pem키의 전문을 github 레포지토리의 secrets에 넣어두고,
ssh를 통해 접근할 때, 이를 활용하여 접근하게 만들었다.
아, 물론 사용이 끝난 다음에는 환경 변수 파일과 함께 반드시 삭제했다.
11. AWS의 다양한 서비스는 얼마나, 어떻게 써봤는가?
ec2는 물론이고, VPC와 프라이빗 서브넷, 로드 밸런서, RDS를 활용해
내부 네트워크로 소통하여 보안을 강화한 네트워크 아키텍쳐 정도는 설계할 수 있다.
이외에도 AWS ECR이나 Lambda 사용 경험이 있다.
아, 그리고 이러한 작업들은 모두 IAM에서 권한을 관리하여 안전하게 처리될 수 있도록 만들었다.
(S3나 클라우드 프론트, 나트게이트웨이, DNS에 대해서도 얘기했으면 좋았을 텐데!)
12. 도커 잘 쓰는가?
(또 뭘 말해야할지 벙쪄있던 때에 다시 물어보셨습니다.)
- 아, 그냥 컨테이너 같은 거 올리고…
네.
후기?
자기소개의 첫마디가, “파이썬을 사랑하는 백엔드 개발자”였습니다.
이 답변에 면접관 세 분 모두 웃으셨습니다.. 이상한 말이었을까요!?
그리고 신입은 절대 해선 안 되는, 기술 스택의 수준에 “상” 적기를 했습니다.
그래도 이 정도면 정말로 파이썬을 사랑하고, 기술 수준 “상”급을 쓸만한 개발자로 보이지 않았을까 싶습니다.
요소요소에 파이썬 매니아임을 잘 드러냈던 것 같습니다.
파이썬의 탄생 배경이나 공식 독스를 꾸준히 확인하는 모습(3.13은 아직 나온 지 2달도 안 된 따끈따끈한 버전입니다.)
GIL이나 파이썬 특유의 메모리 관리를 나름 어느정도 대답했기 때문에 스스로도 조금 만족스러운 면접이었습니다.
기술면접에서 “아 나 파이썬 장인인데 내가 알고 있는 거 어떻게 다 보여줌 ㅋㅋ”라는 자만과 오만이 있었는데,
꽤 많은 걸 보여줄 수 있었던 것 같습니다.
특히 가운데 앉아계신 백엔드 실무자 면접관님과 거의 대화하듯 면접을 진행해서,
면접 자체가 굉장히 즐거웠습니다. 그리고 다행히 면접관님도 재밌어하신 것 같았습니다!
사실 이번 후기를 작성하며 답변 자체에 그렇게 깊은 깊이를 보여주진 못한 느낌이라 떨어질 수도 있겠다 싶긴 하지만,
아쉬움은 없는 면접이었기에 굉장히 좋은 경험이었습니다!