회사에서 DB 지식을 좀 쌓기 위해서 그림으로 공부하는 오라클 구조라는 책을 읽는 중이다. 아직 12장 중 4장까지만 읽었고 정독보다는 속독을 하는 중인데, 읽다보니 새삼 내가 DB에 대해서 제대로 아는 게 없다는 사실을 많이 느꼈다. 그래서 포스팅을 통해 현재까지의 내가 뭘 모르고 뭘 아는지를 정리해보려고 한다. 

 

✅ 내용 정리

우리가 많이 들어본 Oracle, MySQL, MariaDB, PostgreSQL과 같은 데이터베이스들은 모두 DBMS(database management system)의 여러 종류들이다. DBMS는 데이터를 저장하고 꺼내올 수 있는 디스크나 메모리같은 저장 장치만을 의미하는 것이 아니라, 넓은 의미로는 DB의 4원칙이라 불리는 ACID를 보장할 수 있도록 관리해주는 시스템이라고 이해했다. 

 

내가 이해한 ACID는 다음과 같다. 

  • Atomicity: commit은 원자적이다. 하나의 commit은 전체가 모두 반영되거나 전체가 모두 반영되지 않는다. 
  • Consistency: DB의 데이터는 일관성 있게 관리되어야 한다. 
  • Isolation: 트랜잭션이 다른 트랜잭션의 간섭을 받지 않고 독립적으로 실행되는 것을 보장한다. 여기서 '독립적'이라는 말은 해석의 여지가 있다. 이는 DB의 isolation level에 따라서 다르게 해석될 수 있다. 
  • Durability: commit한 데이터는 어떤 일이 있어도 반드시 DB에 기록되어야 한다. 

Durability와 Atomicity를 동시에 보장하는 일은 어렵다고 한다. 특히 Durability를 준수하려면 commit한 데이터는 어떤 일이 있어도 반드시 DB에 기록되어야 한다는 말은 commit 후 DB에 저장하지 않은 상태에서 DB failure가 발생하는 경우를 대비해야 한다. 

 

그러기 위해서 매번 commit 할 때마다 DB에 저장을 하면 되지 않나? 라고 할 수 있지만, 그럴 경우 commit이 빈번하게 되면 DB I/O가 빈번하게 발생하여 성능 저하로 이어진다. 즉 이 ACID를 만족시키면서 동시에 높은 성능을 제공하는 것이 어렵다고 할 수 있다. DBMS는 이 Durability를 지키기 위해서 DB에 데이터를 저장하는 것과 별도로 로그를 기록하는 저장소를 따로 두고 있다고 한다. 

 

Isolation의 경우, DB를 동시에 사용하고 있는 여러 사용자가 있고 그들이 동시에 데이터를 조회하거나 commit을 날릴 경우 어떻게 대응할지에 따라 4단계로 나뉜다. 아래로 갈수록 트랜잭션(transaction)들은 서로 강하게 분리되지만, 그만큼 처리에서 시간이 오래 걸릴 가능성은 높아진다. 

  • Read Uncommited: 어떤 트랜잭션의 변경 내용이 commit과 rollback과 상관없이 다른 트랜잭션에서 보여진다. 예를 들면 A라는 트랜잭션에서 CUD(create/update/delete)하고 commit하지 않은 내용을 다른 트랜잭션에서 조회할 수 있다. 이 경우 Dirty Read 문제가 발생할 수 있다. 
  • Read Committed: 한 트랜잭션이 commit한 내용만 다른 트랜잭션에서 볼 수 있다. 한 트랜잭션에서 commit하지 않고 CUD한 내용들은 Undo 영역에 저장된다고 한다. 그러나 이 경우에도 다른 트랜잭션에서 CUD를 하고 commit을 해 버리면 그 다음부터는 다른 트랜잭션에서 변경된 내역을 바로 볼 수 있기 때문에, Non-Repeatable Read 문제가 발생할 수 있다. 
  • Repeatable Read: 한 트랜잭션이 시작되기 전에 commit된 내용에 대해서만 볼 수 있다. 즉 트랜잭션 여러 개가 진행 중인 상황에서 한 트랜잭션이 commit을 해도 다른 트랜잭션들은 자신이 시작된 시점에 commit 되어있던 내용에 대해서만 볼 수 있다. 이 경우 Non-Repeatable Read는 발생하지 않으나, Insert 문에 대해서는 이야기가 다르다. 다른 트랜잭션에서 Insert 쿼리가 실행되었을 경우 Phantom Read 문제가 생길 수 있다. 
  • Serializable: 하나의 트랜잭션이 실행 중일 때 다른 트랜잭션은 실행되지 않는다. 트랜잭션 간의 실행을 완벽히 분리할 수 있고 Dirty Read, Non-Repeatable Read, Phantom Read 등이 발생하지 않는다는 장점이 있지만, 트랜잭션을 순차적으로 실행하면서 여러 트랜잭션의 처리 시간이 길어지는 단점도 있다. 

그리고 Serializable 단계를 제외한 나머지 세 단계에서 나타나는 현상들은 다음과 같다.

  • Dirty Read: 한 트랜잭션에서 commit 없이 변경한 내용을 다른 트랜잭션에서 읽어들일 수 있다. 만약 이 데이터가 정상적으로 commit되지 않고 rollback 되어도 이미 그 데이터를 읽어들인 다른 트랜잭션에서는 이를 알 길이 없다. 즉 트랜잭션의 입장에서는 지금 자신이 읽어들인 데이터가 정상적으로 commit된 것인지 아닌지도 알 수 없다. 
  • Non-Repeatable Read: 한 트랜잭션에서 데이터 변경 없이 여러 번 조회 쿼리를 날렸을 때 그 결과가 바뀔 수 있다.
  • Phantom Read: 한 트랜잭션에서 데이터 변경 없이 여러 번 조회 쿼리를 날렸을 때, 기존에 있던 데이터가 변경되지는 않지만 새로운 데이터가 생성된 결과가 나올 수 있다. 

표로 나타내면 다음과 같다. 

  Dirty Read Non-Repeatable Read Phantom Read
Read Uncommitted Yes Yes Yes
Read Committed No Yes Yes
Repeatable Read No No Yes
Serializable No No No

 

그리고 SQL을 파싱(parsing)할 때도 DBMS가 관여하는 부분이 있다. SQL은 어떤 데이터를 읽을지(what)를 기술하는 언어이지 어떻게(how) 읽을지를 알려주지 않는다. SELECT FROM, WHERE, GROUP BY, ORDER BY 등으로 어떤 데이터를 읽어올지만 기술한다. 그렇다면 그 데이터를 '어떻게' 읽을지는 DBMS에서 판단하여야 한다. 

 

어떻게 읽는다는 말이 무슨 의미일까? 그냥 읽으면 되는 게 아닐까?

 

DBMS에서는 SQL 쿼리를 실행할 때 어떻게 하면 해당 쿼리를 효율적으로 실행할지를 고민한다. (사실 전공에서 배운 기억은 있는데 이 부분은 잘 모른다...) 이를 위해서 SQL 파싱 단계에서 만든 parse tree를 사용하기도 하며, 각 DB table에 대한 통계 자료를 사용하기도 한다. 

 

물론 옵션으로 통계 자료를 수집할지 말지, 수집한다면 어느 시점에 수집할지 등을 정할 수 있다. 예를 들면 DBMS는 특정 column의 average, sum, min, max 등의 값을 수집하고 이 값들을 쿼리 최적화(query optimization) 및 쿼리가 효율적인지 평가(query evaluation)하는 데 사용한다고 알고 있다. 

 

✅ 궁금한 점

  • Oracle, Mysql, Mariadb와 같은 DBMS들은 어떻게 사용자의 정보를 저장할까?
  • 왜 Durability와 Atomicity를 동시에 보장하는 것이 어려울까?
  • Durability를 준수하기 위해서 로그 저장소를 따로 두고 I/O를 하면 DB I/O를 하는 것에 비해서 어떤 장점이 있을까? 결국 I/O는 똑같아 보이는데 어떤 이유로 이 방법을 택한 것일까?
  • 나는 DB의 구조를 일단은 다음과 같이 이해했는데, 더 구체적인 그림을 그려보고 싶다.

 

✅ References

 

'server-side > server' 카테고리의 다른 글

웹 어플리케이션 서버(WAS)  (0) 2024.08.05
Mac 환경설정  (0) 2024.07.15
Software Release Life Cycle  (0) 2023.07.15
OAuth 2.0 기본원리  (0) 2022.09.26
인증(Authentication)  (0) 2022.07.14

오후에 섬뜩한 문자를 받았다. 

 

슬슬 12월의 AWS 요금이 결제될 것이라는 것은 알고 있었는데 5만원이라니. 뭔가 이상하다 싶어 AWS billing console에 들어가봤다. 사실 0 하나가 더 안 붙은게 어디인가 싶긴 한데, AWS lambda로 돌아가고 있는 서비스라 아무리 생각해봐도 이 금액이 나올 게 아니었다. 

 

원인을 찾아보니 RDS 서비스에서만 약 25달러가 결제되고 있었다. 

현재 RDS는 세 개의 개발 환경을 그대로 반영해서 prod, dev, test 총 3개의 인스턴스를 띄우고 있었다. 그래서 요금이 세 배로 나온 것으로 추측했다. 

 

하지만 이런 식이면 요금을 유지할 수 없었기에... 일단 RDS를 지우기로 했다. 아직 사용 중인 서비스가 아니라서 괜찮다는 판단을 내렸다. 

 

그리고 멘토님이 예전에 조언을 해 주셨던 구글 드라이브 동기화 방식이나 Firebase 등의 DB를 사용하는 방식으로 바꿔 보기로 했다. 

 

바로 RDS에서 세 개의 인스턴스를 지워주었다. 

 

이제 이에 맞춰서 DB를 사용하는 코드를 전부 Google Drive/iCloud를 사용하도록 바꿔 주어야 했다. 새삼 예전에 Java를 찍먹하면서 배웠던 설계 원칙 중 추상화가 덜 되었다는 생각이 들었다. 원칙대로라면 DB가 바뀌어도 구현 클래스를 추가로 만들면 view(controller) 단에서는 코드가 바뀌지 않아야 한다. 문득 Django에서도 개인이 코드를 작성하여 이런 DB 계층의 추상화를 할 수 있을지 궁금해졌다. 다음에 코드를 짜면서 알아보자. 

 

이전 포스팅을 통해서 개발 서버의 도메인을 잘 살려냈다. 이제 남은 과정은 다음과 같다. 

  1. 프론트 앱을 개발 버전에서 실행시켜서 모든 작업들이 다 되는지 확인하기
  2. 개발 버전이 아닌 프로덕션 버전에서도 api가 잘 동작하도록 하기
  3. 현재는 수동으로 aws lambda에 직접 배포를 해야 하는 상황인데, main이나 develop 브랜치에 코드를 올리면 자동으로 zappa 명령어를 통해 변경 내용이 lambda에 반영되도록 하기

1번부터 실행해 보았다. 개발 환경으로 앱을 띄우는 명령어를 입력하니 초기 화면까지는 잘 나왔다. 그런데 그 다음부터가 되지 않았다. 'Apple로 로그인' 버튼을 누르고 이메일과 비밀번호를 입력해 주었더니 아무런 반응이 없다. 

 

일단 원인으로 추측되는 부분은, 서버와 google developer console 등의 설정 문제로 ios에서 받아온 ios client id가 유효하지 않을 수 있다는 것이었다. 다행히 sentry를 활성화시켜둔 덕분에 에러 리포팅을 받아볼 수 있었다. 

추측상 앱에서 api를 통해 ios clinet id를 받아오는 작업까지는 잘 진행된 것으로 보이고, 이후 해당 ios client id를 통한 애플 로그인까지도 잘 진행된 것 같다. 왜냐하면 앱 자체에서 애플 로그인이 잘 진행된 다음에 오류가 난 해당 api를 호출하기 때문이다. 

 

그런데 쓰다보니 벌써 늦은 밤이다. 멀쩡한 월요일을 위해 오늘은 여기까지 해 보고, 다음에 InvalidAudienceError의 원인을 파악해 보자. 

 

✅ 오늘 배운 것

드디어 api gateway를 porkbun 도메인과 연결하는 데 성공했다!!

 

이제 다음 스텝으로 넘어갈 수 있어서 뿌듯하기도 하고, 그동안 모호한 상황에서 나름의 우여곡절을 겪었기에 이를 기록해서 정리해 보려고 한다. 

 

연결하는 과정에서 필요한 서비스들은 다음과 같다. 내가 개발했던 과정에서는 이 외의 다른 서비스와 상호작용하지는 않았었다. 

  1. aws lambda
  2. aws api gateway
  3. aws certificate manager
  4. porkbun

맨 처음으로는 api lambda가 퍼블릭 엔드포인트에서 잘 동작하는지를 확인해 주어야 하겠다. 그래야 api gateway를 통해 연결했을 때에도 잘 동작할 것이니 말이다. 

 

그 다음으로는 aws certificate manager의 issued(발급 완료)된 인증서가 필요하다. 나는 이 문제로 헤매기 전에 이미 발급받은 인증서가 있는 상태였어서 어떻게 내가 이걸 발급했었는지 잘 기억이 나지 않았다. 그래서 다른 블로그의 글을 가져와봤다. 여기서 '도메인 SSL/TLS 인증서 추가하기' 부분에 해당 과정이 잘 설명되어 있어서 복습하는 데 도움이 많이 되었다. 

 

그 다음으로는 api gateway로 이동해서 custom domain을 생성해야 한다. api gateway 서비스로 이동하면 좌측 메뉴에 '사용자 지정 도메인 이름'이라는 메뉴가 있다. (영어로는 아마 'custom domain'이 포함된 메뉴일 것이다.) 여기로 들어오면 나의 경우는 이미 연결해 둔 도메인이 있어서 하나의 레코드가 나오고, 없으면 추가하면 된다. '도메인 이름 추가' 버튼을 누르면 된다. 

 

그러면 추가 페이지가 나오는데, 나는 '도메인 이름'과 'ACM 인증서'를 할당해주는 것 빼고는 설정을 바꾸지는 않았었다. 이런 식으로 할당했다. 

 

도메인 이름을 입력해주고, 특정 VPC 내부에서만이 아닌 일반 URL 엔드포인트로 접근이 가능하게 하는 것이 목적이므로 '퍼블릭'으로 할당해줬다.

 

'API 엔드포인트 유형'의 경우 사실 잘 모르는 부분이었다. 그래도 REST API만 지원하도록 했다가 나중에 일부 기능이나 API가 동작하지 않는 경우가 있을 수도 있다고 생각해서 '리전별(권장)'으로 입력했었다. 

 

최소 TLS 버전과 상호 TLS 인증 역시 기본값으로 두었다. 마지막의 ACM 인증서의 경우는 드롭다운 메뉴를 클릭해서 맞는 인증서를 할당해주면 된다. 나의 경우는 앞에 dev라는 서브도메인을 할당하려고 했기 때문에 *(와일드카드)가 붙은 인증서를 선택해 주었다.

 

이 부분은 처음 Certificate Manager에서 인증서를 발급받을 때 결정해야 한다. 그냥 도메인(stepby.one)과 와일드카드가 붙은 도메인(*.stepby.one) 총 두 개에 대해 인증서를 발급하면 편했다. 

그리고 '도메인 이름 추가'를 눌러주자. 그 다음에는 이렇게 만든 custom domain 설정을 기존에 잘 동작하던 api gateway와 연결해주면 된다. api gateway 서비스로 다시 들어가보면 방금 생성된 '사용자 지정 도메인 이름(custom domain)'이 생겼을 텐데, 이 도메인 이름을 눌러서 들어가보자.

 

그러면 하단에 'API 매핑' 섹션이 보이고 아직은 아무것도 없을 것이다. 여기서 'API 매핑 구성'을 눌러서 매핑을 추가해주자. 나의 경우는 미리 할당해 둔 상태라서 이렇게 'backend-dev'라는 api gateway가 custom domain에 연결되어 있다. 

 

그러면 이렇게 현재 활성화된 api gateway들 중 어떤 것을 해당 custom domain에 연결할지를 선택할 수 있다. 원하는 api gateway를 선택해 주고 저장 버튼을 누르자. 

이제는 porkbun 사이트로 다시 들어간 다음 구매한 도메인에 대해서 cname 레코드를 추가해 주어야 한다. porkbun 사이트에서 로그인을 하고 우상단 메뉴의 'account' 메뉴를 클릭하면 드롭다운으로 하위 메뉴들이 나오는데, 여기서 'Domain Management'를 클릭해주자. 그러면 본인이 구매한 도메인 레코드들을 볼 수 있다. 

 

여기서 본인이 구매한 도메인 이름에 마우스를 올리면 'DNS | NS' 라는 레코드가 나오고 클릭할 수 있다. 우리는 이미 연결된 도메인에 대해서 서브도메인을 추가로 설정하는 것이니 NS 부분은 건드릴 필요가 없고, DNS를 클릭해주자. 

 

그러면 이런 화면이 나오면서 레코드를 추가할 수 있다. 우리는 서브도메인을 추가할 것이므로 CNAME 타입으로 설정하고, Host 부분의 이름은 설정하려는 서브도메인의 값을 입력해준다. 

 

여기서 Answer / Value 부분이 중요한데, 이 값은 api gateway의 custom domain 상세보기 페이지로 들어가면 얻을 수 있다. api gateway의 '사용자 지정 도메인 이름' 메뉴로 들어가서 아까 추가한 레코드를 클릭해보자. 그러면 이런 화면이 나오는데, 여기의 'API Gateway 도메인 이름' 값을 입력해주면 된다. 

 

그러면 이런 cname 타입 레코드가 생긴다. 

 

해당 도메인의 레코드가 DNS 서버에 전파되어 접속이 가능하게 되려면 시간이 필요하다고 알고 있다. 정확한 시간은 없지만, TTL이 600초라서 나는 10분 내외를 예상했었다. 실제로는 약 1시간 정도의 시간이 걸렸던 것 같다(40분 이후에 시도해봤는데도 되지 않았기 때문에 그렇게 추측했다). 

 

✅ 궁금한 점

  1. CNAME 레코드는 보통 subdomain에 대해 매핑을 추가할 때 할당하는 레코드라고만 알고 있었다. 정확한 CNAME 레코드의 정의가 무엇일지 궁금하다. 정확히는 CNAME 타입이 무엇이길래 서브도메인을 추가하려면 CNAME 타입의 레코드를 추가해야 하는 것인지가 궁금하다. 
  2. 전체 구조가 어떻게 되는 것인지 대강 말로는 설명할 수 있지만 그림이 그려지지는 않는다. 그림을 한번 그려보자. 

 

문득 코딩웨일이라는 개발자 유튜브를 보다가 '일 잘 하는 개발자가 되려면 어떻게 해야 하는가'에 대해 생각해보게 되었다. 크게 두 가지의 인사이트를 얻었다. 하나는 내가 무의식적으로 생각하고 있던 부분이었고, 다른 하나는 아마 나를 비롯한 많은 신입 개발자들에게 있을 '임포스터 증후군'에 대한 위로이자 통찰이었다. 

  1. 회사에서 원하는 개발자는 개발만 잘 하는 개발자가 아니라, 개발로 문제를 해결하는 개발자이다. 
  2. 재능의 영역도 물론 있다. 하지만 소위 말하는 '잘 하는 개발자'가 되고 싶다는 거라면 이 부분은 잘 설정된 노력과 학습으로도 어느 정도 가능하다. 

✅ '나 자신'과 '회사' 모두에 대해 이해하는 개발자가 되자

이런 종류의 영상을 보면서 항상 느끼는 점이 있는데, 개발자도 결국 하나의 직업이며 이 직업의 수요나 채용은 사회와의 관계(수요와 공급) 속에서 결정된다는 거였다. 예전에 소마에서 우리 엑스퍼트님이 해주신 말씀과도 맥락이 통한다. 그때 당시에는 취업 관련 조언으로 이 말을 해 주셨는데, 지금 생각해 보면 이 인사이트는 커리어를 쌓아 나가는 과정에서도 계속 유효하다고 생각한다. (정확히는 기억나지 않지만 이런 맥락이었다.)

채용은 '나'와 '회사' 사이의 핏을 맞춰 나가는 과정이다. 그렇기에 이력서를 쓰거나 면접을 볼 때에도 내가 생각하는 '나 자신'이 있고, 내가 생각하는 '회사'가 무엇인지를 말해 주고, 이 둘이 어떻게 핏을 맞춰 나갈 수 있을지를 드러내야 한다. 왜냐하면 회사에서는 회사에서 성과를 낼 개발자를 채용하려는 것이므로, '이 개발자는 어떤 사람인지'와 '그래서 우리 회사에 맞을지'가 궁금한 것이겠다. 이 두 가지를 이력서나 면접에서 풀어내려면 내가 현재 갖고 있는 '개발자로서의 나 자신'에 대한 생각과, '내가 지원하려는 회사'에 대한 생각을 정리해 봐야 하겠다. 

 

그러니까 단순히 '나는 A라는 능력이 있다' 라는 개발자가 아니라, '나는 A라는 능력이 있고, 내가 이해하기로는 회사에서 B라는 업무를 하는데 여기서는 A라는 능력이 필요하다고 알고 있다. 그러므로 나는 회사에 적합한 인재이다' 라는 식으로 풀어나가는 것이 조금 더 맞다는 생각이었다. 

 

✅ 업무 처리 능력 != 개발 실력

그리고 잠시나마 실무를 찍먹해 본 입장에서도 위의 인사이트에 공감했다. '개발을 잘 한다'고 하면 보통 코드를 간결하거나 빠르게 만들거나, 코드를 가독성 있게 짜거나, 전공지식이 탄탄한 경우를 생각하곤 했다. 그런데 그게 항상 업무를 잘 하는 걸로 이어지지는 않는다. (물론 대체로 이런 사람들이 실무를 더 잘 하기는 하는데, 인과관계는 아니라는 뜻이다.)

 

1년차 미만 개발자인 내가 보기에 실무를 잘 하는 주니어 개발자의 특징을 정리해 보았다. (시니어 개발자의 영역은 아직은 내가 알 수 없는 영역이라 제외했다.)

  1. 요구사항이 무엇인지를 잘 파악한다. 
  2. 마감 기한을 잘 지킨다. 
  3. 커뮤니케이션을 잘 한다. 가령 여러 문제로 마감 기한이 늦어질 위기에 처하는 경우가 있을 수 있다. 하지만 이 경우 자신의 문제 상황을 잘 공유하고 피드백을 구해서 잘 적용한다. 

사실 이 정도가 생각난다. 그리고 생각보다 주니어 개발자를 평가할 때 순수한 코딩 실력으로만 이를 평가하지는 않을 것이다. 이전의 업무 경험에서는 나는 이런 피드백을 받았었다. 

  1. (두 사수분에게 모두 받았던 피드백) 모르는 것이나 어려움이 있을 때 꽁꽁 숨기지 말고, 시도해 본 다음에 안 되면 바로 질문해 줬으면 좋겠다. 그게 효율적이다. 
  2. (코드 리뷰 때 받은 피드백) 가독성이 좋게 코드를 짜는 것은 매우 중요하다. 내가 짠 코드를 후에 다른 개발자가 맡아서 작업할 수도 있기 때문이다. 
  3. (회식 때 받은 피드백) 문서화를 잘 하셔서 일이 어디까지 진행되고 있는지 알아보기가 편했다. 
  4. (마감 데드라인이 밀렸을 때 / 다른 분들이 예상하신 것보다 더 시간이 걸렸을 때) 일을 하면서 겪은 다른 어려움이 있는지 궁금하다. 작업을 방해한 다른 요소가 있는지 궁금하다. -> 책임을 물으시려는 의도가 아니었고 원인을 알아내서 같이 제거해 주려는 목적으로 여쭤보셨다. 

이러한 것들이 생각난다. 여기서 느낀 점은, 생각보다 주니어에게 대단한 무언가를 기대하지는 않는다는 거였다. 네 개의 피드백 모두 어떻게 보면 커뮤니케이션 영역과 관련이 깊었다. 입사 후 바로 조직에서 성과를 낼 수 있는 주니어면 정말 좋겠지만, 내가 생각하기에 나는 그런 '슈퍼 신입'은 아니었다. 그걸 인정하고 다시 피드백을 보니, 최소한 조직이 돌아가는 방식이나 협업 프로세스를 빨리 파악하고 여기에 적응하는 주니어를 선호하는 것은 분명해 보였다. 

 

그래서 나는 '슈퍼 신입'이 되려는 대신 전략을 바꿨다. 

 

✅ 임포스터 증후군 극복하기

많은 신입들이 가면 증후군이 있다고 한다. 가령 '나는 회사의 기대를 충족할 만큼 잘 하고 실력 있는 사람이 아닌데, 근데 그걸 어떻게 잘 숨겨서 뽑힌 것이다. 내 실제 실력을 알면 실망할 것이다'와 비슷한 생각이다. 나도 이 가면 증후군이 있었고, 여전히 있다. 

 

내가 실력이 좋아서 뽑힌 것은 아니라고 생각한다. 그저 괜찮아 보이는 몇 가지의 조건들이 충족되어서 서류를 통과했고, 면접관 입장에서는 크게 부정적인 방향으로 눈에 띄는 사람은 아니었기에 면접을 통과한 것이라고 생각한다. 절대 내가 잘 해서 뽑힌 게 아니라고 생각하고, 살면서 나는 이런 면에서 꽤 객관적이었던 만큼 실제로도 그럴 것이라고 생각한다. 

 

그래서 불안하냐고 하면 그건 맞는데, 그래도 앞으로 어떻게 할지가 더 중요하다는 답을 내렸다. 그 전에 '나는 어떤 개발자가 되고 싶은가'에 대한 답을 내려야겠다. 

  1. 문제를 기한 안에 해결하는 개발자
  2. 소통이 잘 되는 개발자

나는 1번 영역에 대해서 더 자신이 없다. 예상했던 것보다 일을 늦게 처리한 경험이 몇 번 있었기에, 오히려 1번 영역이 나의 콤플렉스에 가깝다. 그리고 지금까지 나는 문제를 기한 안에 해결하는 것 자체가 코딩을 잘 한다는 것이고, 나에게는 없는 재능이며, 순수한 재능의 영역이라고만 생각했었다. 

 

그런데 발전시킬 수도 있지 않을까?

 

앞서 언급한 코딩웨일 유튜브를 보고 그런 생각이 들었다. 모두가 천부적인 재능으로 개발자를 하는 게 아니라면 나도 가능하지 않을까? 

 

다만 깃털 같은 희망만을 품어서 될 일은 아니었다. 어떤 노력을 해서 이 능력을 좀 끌어올릴 수 있을지를 생각해 봤다. 내가 생각하기에는 나의 부족함을 빨리 맞닥뜨리는 연습이 필요한 것 같다. 가령 안 풀리는 부분이 있으면 빨리 공유해서 이에 대한 피드백을 받고, 새로운 방법을 모색하는 것이겠다. 

 

그동안은 도움을 요청한다는 것 자체가 내가 혼자 해결해야 할 일인데 남에게 도움을 요청한다는, 어찌 보면 의존적이라는 생각이 들어서 잘 요청하지 못했었다. 그런데 아이러니하게도 주니어 개발자의 경우, 혼자 시도한 다음에 풀리지 않는 일이라면 피드백을 요청하고 그 피드백을 잘 수용하려고 노력하는 과정을 통해 더 빨리 발전할 수 있겠다는 생각이 들었다. 

 

그러니까 이를 위해서는 나의 완벽주의를 좀 버려야 하겠다. 잘 하는 것처럼 보이고 싶고, 혼자 일을 완벽하게 해내고 싶은 마음을 잘 눌러야겠다. 열심히 시도해 보다가 모르면 현재의 나는 이걸 잘 모른다는 것을 겸허히 인정한 뒤 내가 할 수 있는 다른 방법, 피드백을 요청하는 것을 기꺼이 해야겠다. 

 

회사 입장에서 중요한 것은 '내가 문제를 느리더라도 처음부터 끝까지 혼자 해결하는 것'이 아니라 '내가 효율적으로 빠르게 문제를 해결하는 것'일 테니 말이다. 일하면서 나 자신뿐만 아니라 '동료'와 '회사'가 나와 같이 일하고 있다는 것을 잃지 말자. 

 

그리고 그렇게 나의 부족함을 계속해서 발견하고, 부끄럽고 민망하겠지만 이에 대한 조언이나 피드백을 구하고, 그걸 적용하려는 연습을 하다보면 분명 혼자 꽁꽁 싸매던 예전의 나보다는 더 빨리 발전할 수 있을 것이라는 확신이 든다. 

 

+ Recent posts