blog

미국 약혼자 (K-1) 비자 신청 과정

호주에서 미국으로 이사오게 되었다. 그 과정에서 지난한 비자 신청을 또 했다!

한국에서 결혼식은 했지만 짧은 체류 기간으로 국내서 법적 절차는 밟지 못했다. 그래서 배우자 비자 대신 약혼자 비자를 신청해야 하는 상황이었고 결혼식 직후에 서류를 준비해서 제출했다.

호주 비자는 온라인으로 모든 서류를 제출하고 현황을 확인할 수 있었던 것에 반해 미국의 경우는 우편으로 제출하는 부분이 많아서 그런지 처리 기간이 상당히 걸렸다. 변호사 없이 모든 서류와 절차를 아내와 함께 준비해서 접수했다.

모든 정보는 travel.state.gov, uscis.gov, usembassy.govvisajourney에서 확인하고 진행했다. 특히 visajourney는 인터뷰라든지, 메디컬 체크라든지 궁금하던 부분을 해소해주는 좋은 글이 많았다. 네이버에서도 검색해보면 많이 나오긴 했지만 나는 멜버른에 있었고 시드니에서 인터뷰를 봐서 visajourney에 더 맞는 상황의 글이 많았다.

영사관에 제출하는 서류에 어떤 한국 공문서를 제출하면 되는지 확인하려면 Reciprocity and Civil documents: South Korea를 참고하면 된다. 영문으로 뽑을 수 있는 서류는 영문으로 뽑았고 영문 서류가 없는 경우에는 번역했고 멜버른 영사관에서 영사 공증을 받았다. 아포스티유는 받지 않았다. 호주 비자 신청 당시 필요했던 서류와 크게 다르지 않아서 준비에 별다른 문제는 없었다.

  • 2017년 6월 초 – I-129F 청원 접수
  • 2017년 6월 7일 – NOA1
  • 2017년 12월 – 추가 요청 서류 제출 (Beneficiary’s Statement)
  • 2018년 1월 26일 – NOA2
  • 2018년 4월 3일 – NVC
  • 2018년 4월 9일 – 시드니 미 영사관에 case 이관, DS-160 제출
  • 2018년 4월 12일 – 영사관 인터뷰 접수 및 안내
  • 2018년 4월 말 – Toorak Village medical centre에서 Medical Assessment 받음 (검사랑 예방 접종)
  • 2018년 5월 29일 – 시드니 영사관 인터뷰
    • I-129F 청원 만기일이 5일 가량 지나서 Revalidation letter을 제출
  • 2018년 6월 4일 – 인터뷰에 제출한 여권 택배로 수령 (비자 스티커 붙어 있고 입국 시 가져가는 밀봉 서류 받음)
  • 2018년 6월 30일 – LAX로 입국, POE 통과
  • 2018년 7월 – 코트 방문, 혼인 신고

인터뷰는 시드니까지 가서 봐야 했던 터라 긴장을 많이 했었다. 인터넷에 나온 예상 질문 보고 답하는 연습 해본 것이 버벅이지 않고 대답하는데 많은 도움이 되었다. 예상 질문 내에서 다 질문했다. 다행인지 아내가 멜버른에 오는 기간에 인터뷰가 겹쳐서 여행 일정은 좀 줄긴 했지만 시드니를 같이 다녀와서 마음은 좀 편했다.

미국에 오자마자 Marriage certificate을 신청했다. 나머지 SSN, AOS, EAD, 운전 면허 등 신청해야 할 것이 줄줄이 남아 있는데 순차적으로 처리되어야 하는 부분이라 시간을 두고 기다리고 있다.

출발하기 전에 보낸 이삿짐은 아직 오지 않았는데 8월 쯤에 온다고 한다. 모두 별 일 없이 도착했으면 좋겠다.

비자는 할 때마다 정신적으로 많이 피곤하지만 문제 없이 잘 처리되는 것에 얼마나 다행인지 생각한다. 아내와 멀리 떨어져서 준비했던 기간을 생각하면 남은 부분은 함께 처리할 수 있으니 참 감사하다. 긴 프로세스 동안 함께 준비하고 고생한 아내에게 너무 고맙다.

6년 여 지냈던 멜버른을 떠나서 새 터전에 자리를 잡게 되었다. 처음 호주에 갔을 때는 아무 준비도 없었고 연고도 없었지만 이번은 사랑하는 사람이 곁에 있고 적응할 걱정은 좀 덜하다. 그래도 마음은 잔뜩 긴장하고 첫 달을 보내고 있긴 하다. 별 문제 없이 잘 정착하도록 노력해야겠다.

오픈소스 지속가능성 체계적으로 생각해보기

C. Titus Brown의 글 A framework for thinking about Open Source Sustainability?을 번역했다. 공유지의 비극과 그 해결책을 오픈소스 프로젝트에 적용해보는 글인데 오픈소스 거버넌스에서 기성 연구를 적용하는 글이라 더 흥미롭다.

오픈소스 지속가능성 체계적으로 생각해보기

공유자원 문제를 온라인 오픈 프로젝트에 적용할 수 있을까?

Nadia Eghbal의 아름다운 글인 “공유지의 비극”을 다시 읽었습니다. Elinor Ostrom의 공유자원 연구에 기반한 대안적 결과를 읽으며 여러 맥락에서 다양한 생각이 들었고 그 생각을 공유하려고 합니다.

Nadia는 오픈소스의 지속가능성 문제에 대해 탐구하고 있습니다. 중요한 오픈소스 소프트웨어가 상대적으로 적은 인원으로 관리되고 있으며 금전적 보장 방법이 많지 않은 상황이라 중대한 문제로 볼 수 있습니다. 이 문제의 규모나 범위를 따지면 누구와 대화하고 있냐에 따라 달라집니다. Python의 과학적 컴퓨팅 환경에 관한 충격적인 그림을 보면 numpy는 겨우 6명의 메인테이너가 유지하고 있는 점을 확인할 수 있습니다. Python에서 과학적 컴퓨팅 환경을 생각해보면 numpy에 상당히 의존적이기 때문에 메인테이너의 수가 적다는 이야기는 쉽지 않은 도전처럼 들립니다. 소프트웨어 개발에 관한 일반적인 도전 과제를 심층적으로 살펴보고 싶다면 “The Astropy problem”, Muna et al., 2016를 보도록 합니다.

(이후 논의에서는 과학적 소프트웨어에 치중되어 있지만 더 넓은 범위에도 적용할 수 있다고 생각합니다.)

저는 생물정보학(bioinformatics) 분야에서 일하고 있습니다. 이 분야는 다양한 조합의 소프트웨어 패키지를 사용하며 이런 패키지도 대학원생이나 포스트닥터, 학부에 계신 분이나 직원 등 다양한 사람이 관리하고 있습니다. 제 랩에서도 소프트웨어를 개발하고 있습니다. (주로 khmersourmash를 개발하며 그 외에도 여럿 있습니다.) 그리고 지난 해에는 지속적으로 소프트웨어를 유지하기 위한 방법도 개발했는데 주로 테스트와 지속적 통합을 중심으로 동작합니다. 하지만 항상 무언가 제대로 동작하지 않는 부분이 있습니다. 자동화된 관리에서 정말 사소한 상수인데도 그렇습니다. 운이 좋다고 해야할지 Jupyter와 같은 프로젝트와는 다르게 저희 소프트웨어를 사용하는 사람은 그리 많지 않아서 버그 리포트와 관리 문제가 주체 못할 정도로 쏟아지진 않습니다.

이미 언급했듯 오픈소스 소프트웨어를 관리하는 상수는 꽤 노력이 필요합니다. 매주 소프트웨어의 어떤 부분이든 작업하다보면 버그와 관련되어 있지 않는 경우가 드뭅니다. 아니면 새로운 기능을 추가하기 위해 뒤집어 엎어야 하는 부분이 많은 경우도 있습니다. 물론 랩에서 저나 다른 사람이 갑자기 연구나 코딩에 영감이 온다면 한동안 그런 문제를 마주할 일이 없긴 할겁니다.

학습에 있어서도 동일하게 노력이 필요합니다. 매년 2주짜리 과정분석 워크샵을 진행해 새로운 접근법, 소프트웨어, 자료 타입 등 발전에 필요한 학습을 합니다. 2010년에 배운 지식도 여전히 동작하긴 하지만 대부분 지독하게 썩었을 것이라 예상합니다.

다년간 여러 패키지를 관찰해본 제 경험에서는 활발하게 관리되지 않는 오픈 온라인 프로젝트(소프트웨어와 학습 자료를 포함)는 빠르게 부식한다는 확고한 결론에 도달했습니다. 또한 사람들이 많이 사용하는 프로젝트는 고쳐야 할 많은 버그와 문제를 항상 찾게 됩니다. 이 관리된다는 말에는 다른 사람들이 당신의 온라인 프로젝트를 향상하는데 실제로 도움을 주고 싶어서 Github에 리뷰 받아 머지되거나 거절되야 할 풀 리퀘스트를 제출하는 것을 포함하지 않았습니다. 또는 (정말 성공적이라면) 어떤 회사에서 프로젝트에 참여해 그들의 코드를 넣고 싶어할지도 모르겠지만 그런 회사도 포함하지 않았습니다.

프로젝트가 활발하게 관리되려면 지속적인 관심이 필요합니다. 이 관심에는 멋진 과학적 소프트웨어 패키지의 제멋대로 자란 생태계, 실제 메인테이너로 구성되어 있지만 상대적으로 작은 커뮤니티도 포함됩니다. 이 모든 것이 하나로 섞이면 과학계에서 마주하는 오픈소스 지속 가능성 문제로 이어집니다. 영웅적인 노력 없이는 이 모든 프로젝트를 유지할 수 있는 인력이 없습니다. 과학계에서의 소프트웨어 유지라는 명확한 커리어 패스가 존재하지 않는다면 오픈소스 유지보수를 위해 더 많은 사람을 찾는 일은 도덕적이지도, 지속 가능하지도 않다는 점이 명확합니다.

최근에 동료와 다른 오픈소스 프로젝트에 대해 브레인스토밍을 한 적이 있습니다. (뒤에 더 설명합니다.) 이 과정에서 이 문제를 공유자원 문제라는 틀 안에서 생각해보려고 했습니다. 프로젝트의 성공이란 지속가능성 문제와 맡닿아 있으며 공유 자원 프레임워크를 사용하면 그 지속가능성에 대해 판단할 수 있을 거라 생각하고 이 틀을 찾기로 했습니다.

공유 자원, 공유지의 비극, 지속가능성을 위한 디자인 원리

제가 알고 있는 공유자원 프레임워크는 Elinor Ostrom의 책, 공유지의 비극을 넘어 (원제: Governing the Commons)에서 왔습니다. 이 책에서는 아주 일반적인 공유자원 문제를 설명하고 공동체가 이런 문제를 어떤 방식으로 해결했는지 논의하고 있습니다.

개괄적으로, 60, 70년대 Elinor Ostrom과 동료는 “공유지의 비극”이라는 유명한 개념을 설명했습니다. 공유지의 비극은 공유자원이 이기적인 이유로 과도하게 이용되는 상황을 의미합니다. 이 문제는 피할 수 있습니다. 꼭 정부의 규제나 기업화만 이런 문제를 관리하는 방법이 아닙니다. 실제로 공동체 대다수는 공유자원을 지역적으로 관리하는 방식을 통해 문제를 해결했습니다. Ostrom과 다른 사람의 사례 연구에서 Ostrom은 공유 자원의 지속 가능성을 위한 8가지 “디자인 원칙”을 추출했습니다.

Nadia의 블로그 포스트에서 잘 설명하고 있고, 또한 읽기 좋게 정리되어 있는 위키피디아에 있는 8가지 디자인 원칙 링크를 남겨둡니다.

Ostrom은 이 연구에 대한 업적으로 2009년 노벨상을 수상했습니다.

오픈 온라인 프로젝트로 돌아가기

저와 동료들은 이 프레임워크를 디지털 자원인 오픈 온라인 프로젝트에 어떤 방식으로 적용할 수 있을까 고민했습니다. 디지털 자원은 물리적 자원과 달리 소비할 수 없고 누가 프로젝트의 소스 코드를 소비한다고 해서 다른 사람이 사용하지 못하는 것이 아니기 때문입니다.

대화 속에서 답을 찾았고 그 답은 노력(effort)이었습니다. 오픈 온라인 프로젝트의 공유 자원은 노력입니다.

기여자가 프로젝트에 새로운 기능을 추가하려면 무슨 일을 하게 되나요? 노력을 들입니다. 기여자가 버그를 보고할 때는? 역시 노력을 들입니다. 좋은 버그 리포트를 남길 때는? 노력을 들입니다. 문서를 작성할 때는? 기능을 테스트할 때는? 새 기능을 추천할 때는? 모든 과정에서 노력이 필요합니다.

하지만 이보다 더 깊은 주제가 있습니다. 새로운 기여자를 프로젝트로 끌어들이면 노력의 크기를 성장시킬 수 있습니다. 오픈 소스 프로젝트에 금전적 지원을 줄 새 투자자와 만나게 될 때, 프로젝트에 얼마나 많은 헌신적 노력이 있는가에 따라 그 지원의 규모가 증가하기도 합니다.

물론 전에 썼던 것과 같이 모든 기여가 노력으로 가치 있는 것은 아닙니다. 어떤 기여는 그 기여가 주는 가치보다 프로젝트에 더 많은 비용 부담을 주기도 합니다. 예를 들면 새로운 기능 제안, 나쁜 버그 리포트가 있습니다. 기여가 없는 커다란 기능 추가는 단순히 리뷰하고 거절하는 일에서도 핵심 프로젝트 메인테이너에게 엄청난 비용적 부담을 줄 수 있습니다. 이런 일은 유지보수 필요성이 낮은 일인데 유지보수가 프로젝트의 노력을 죄다 끌어가야만 하는 상황으로 뒤바뀔 수도 있습니다.

Fernando Perez가 #GCCBOSC에서 비슷한 점을 언급한 적이 있습니다. 바로 오픈소스 프로젝트에서 사람을 채용해가는 방식에 대한 지적입니다. 많은 회사가 오픈소스 커뮤니티에서 사람을 채용합니다. 단순히 생각해봐도 오픈소스 커뮤니티에서 이들을 교육하는데 들인 노력은 안중에 없이 발굴해가는 것은 문제입니다.

공유 자원의 지속가능성을 위한 8가지 디자인 원칙을 보고 “노력”을 공유 자원으로 정의한다면 오픈소스 프로젝트에 다음처럼 적용할 수 있습니다.

  1. 오픈소스 프로젝트에 누가 기여자인지 명확하게 정의합니다.
  2. 오픈 온라인 프로젝트에서의 노력은 프로젝트의 필요에 따라 지역적으로 적용됩니다.
  3. 오픈 소스 프로젝트는 기여하는 사람이 디자인 결정에 참여한다는 규칙을 따릅니다.
  4. 크게 기여하는 사람을 공식적으로 프로젝트에 참여하도록 해서 결정에 더 큰 역할을 맡을 수 있도록 합니다.
  5. 커뮤니티의 규칙을 위반한 기여자는 제재할 수 있는 범위를 둡니다.
  6. 충돌 대부분은 법률적으로 해결하기보다 프로젝트 내부적으로 해결합니다.
  7. 충돌 대부분은 가벼운 방법과 논의로 다룹니다.
  8. 오픈소스 기여자 대부분은 여러 프로젝트에 기여합니다. 예를 들면 Python 생태계에서는 같은 사람이 많은 프로젝트에 참여하고 있습니다. 이런 맥락에서 Python 생태계를 큰 규모의 공유 자원으로 여기고 많은 지역적 공유 자원으로 구성되어 있다는 점을 고려해야 합니다. 예를 들어 “핵심 CPython 개발”, “수치 연산/numpy 라이브러리” 등의 지역적 공유 자원이 존재합니다.

제 생각에는 많은 종류의 열린 공동체에 일반적으로 적용할 수 있는 항목이라고 생각합니다.

그렇다면 이게 무슨 의미일까요?

저와 동료가 이런 방식으로 생각하기 시작한 후로 이 관점에서 오픈소스 프로젝트와 온라인 공동체 자료를 보기 시작했습니다. 이 틀은 오픈소스의 지속 가능성을 생각하는데 아주 간단하고 좋은 프레임워크가 될 수 있습니다. “얼마나 열리면 지나치게 열린 것인가” 포스트는 정확히 이 생각에서 온 글입니다. 또한 당신의 프로젝트에 사람들이 더 모집되는 것을 긍적적으로 봐야하는지 설명합니다. 프로젝트에 노력을 쓸 수 있는 양이 늘어난다면 프로젝트 필요에 더 많은 노력을 사용할 수 있습니다. 이렇게 참여를 늘린다는 점에서 행동 강령과 기여자 가이드라인이 더 중요해집니다. 장기적으로 참여할 사람을 찾고 노력할 사람을 유지하는게 가능하게 됩니다.

이 관점 자체로는 어떤 문제도 해결하지 않습니다. 하지만 이 원칙은 정말 좋은 사례 연구와 함께 묶여 있으며 공유 자원에 대한 연구로 어떻게 공동체 자원을 지속 가능하게 관리하는지 심도있게 다루고 있습니다.

좀 더 세부적으로 다루자면 일반적인 오픈 온라인 프로젝트를 한다는 맥락에서 몇 가지 고려해야 할 점을 제안하고 있습니다.

먼저 오픈소스 프로젝트에 사용할 노력이 잠식되지 않도록 지켜내야 합니다. 프로젝트가 성공하려면 기여 잠재력이 가용 노력에 얼마나 영향을 주는지 평가해야 합니다. 이런 평가가 기술적 기여에는 이미 포함되어 있겠지만 (“기술적인 빚”이란 관점에서), 버그 리포트와 기술 제안에서도 고려되어야 합니다. (물론 프로젝트 대다수는 이런 점을 이미 고려하고 있습니다.)

둘째, 지속적으로 유지보수 할 필요가 있는 부분(코드, 문서, 설치 등)에 들어가는 비용도 노력이 들어가는 부분으로 계산해야 합니다. 새 기능을 기여하면서 이런 유지보수가 필요한 부분을 간과하는 경우가 있으므로 세심히 살펴야 합니다. 새 기여자가 계속 도움을 주려고 하나요? 유지보수하기 위한 노력을 들여 헌신하려고 하나요? 그렇지 않다면 이런 유지보수에 노력을 더하게 되는 기여는 파트너십 등을 통해서 미뤄야 합니다.

셋째로, 새 기여자를 교육하고 육성하는 방식은 장기적인 관점에서 가용 노력을 늘린다는 점을 염두해야 합니다. 하지만 기여자의 심리는 까다롭고 교육하고 육성한다고 해서 계속 이 프로젝트에 남아 있으리라는 예측은 그렇게 간단하지 않습니다. Python 코어 멘토 프로그램처럼 어떤 프로젝트는 뛰어난 인큐베이터를 갖고 있습니다. 이런 곳은 자신들의 노력을 새로운 기여자를 찾는 일에 사용하는데 관심있는 사람들이 운영합니다. 제가 생각하기에는 친근한 환경을 만들고 기여하고 싶은 사람들에게 갖는 기대감이 어떤 방향인지 잘 알려줄 수 있다면 새로운 기여자에게 도움이 될거라고 봅니다. 우리 유지보수 노력에 기여하고 싶은 사람에게 어떻게 하면 새로운 기능도 추가하고 버그도 개선할 수 있는지 기쁘게 알려줄 수 있다는 그런 마음가짐 말이죠. 장기적으로 보면 건강한 공동체가 즉, 건강한 프로젝트라고 할 수 있습니다.

넷째로, 모든 또는 대다수의 자원 제공자가 의사 결정에 참여하도록 허용하는 흥미로운 구조의 영향을 받습니다. 이 부분은 좀 더 세세하게 살펴봐야 하긴 합니다. 하지만 대략적으로 설명하면 프로젝트에서 어느 정도 수준의 투자와 기여가 어떤 실효적 수준에서 정책이나 원칙 수립 단계의 보상을 받게 되는지 정할 필요가 있습니다.

다섯째로, 자금 제공자의 기대치를 설정하고 투자를 얻는 과정에서 프로젝트의 성숙도를 측정하는 기준을 정의하는 일이 도움이 될 수 있습니다. 제 경험에 따르면 대부분의 자금 제공자는 프로젝트 지속 가능성를 도식화 하는 일을 가장 우선시 합니다. 위에서 얘기한 디자인 원칙(그리고 공유 자원에서 나온 사례 연구)을 프로젝트 성숙도의 기반으로 삼는다면 지속 가능성을 판단할 수 있게 됩니다. 프로젝트의 자금 지원 제안을 작성한다고 가정하면 어느 디자인 원칙과 연계된 부분을 향상하려고 하며 어떻게 지속 가능 프레임워크와 연결되는지 적용할 수 있습니다. 예를 들어 “지금 당장 새로운 기여자가 참여하는데 있어 우리 역량을 걱정하고 있습니다. 또한 회사로부터 큰 규모의 기여를 하겠다는 제안을 받고 있습니다. 저희는 프로젝트 관리 방식을 구축하고 기여자를 위한 안내를 향상해 새 기여자와 투자자에게 어떤 수준의 투자와 기여를 기대하고 있는지 명확하게 설명하려고 합니다.” 식으로 설명한다면 자금 제공자는 이런 설명에 만족할겁니다.

“노력”이라는 공유 자원 프레임워크가 오픈소스 프로젝트와 오픈 온라인 프로젝트에 일반적으로 정말 잘 맞나요?

좋은 질문입니다. 저는 공유 자원에 대해 해박하지 않고 앞으로도 읽어야 할 것이 정말 많습니다. 공유 자원 프레임워크와 부합하지 않는 부분도 보여서 좀 더 다듬어야 하는게 사실입니다. 하지만 오픈소스 프로젝트가 동작하는 방식과 잘 맞아 떨어진다는 게 제 직감입니다. 공유 자원과 같은 개념적인 틀은 제 관점을 다시 생각하게 하고 더 나은 그림에 맞춰볼 수 있게 하며 문제를 해결하는데 다른 결론에 닿게 할 지도 모르겠습니다. 이 예제는 앞서 언급했던 “얼마나 열리면 지나치게 열린 것인가” 포스트에서 찾아볼 수 있습니다.

제가 정말로 시도하고 싶은 일은 오픈 소스 프로젝트의 사례 연구에 참여하여 오픈소스 프로젝트가 실제 삶에서 어떻게 작동하는지 연구하며 이 프레임워크에 부합하는지, 혹은 부합하지 않는지 확인하는 일입니다. 몇 년 내로 안식년을 가지게 되는데 그 기회가 될지 모르겠습니다.

이 프레임워크에서 가장 좋아하는 점 하나는 오픈소스 프로젝트에서 자유 오픈소스 소프트웨어에서 큰 가치로 여겼던, 흐릿해진 목표와 분리해서 생각할 수 있게 되었다는 점입니다. “우리는 행복한 대가족이고 모든 부분이 함께 동작합니다!” 라는 구호는 메인테이너의 삶이 열린 기여에 의해 망가지는 상황을 마주하면서 희미해졌습니다. 오픈소스 프로젝트는 오늘날 세계를 구성하는 커다란 부분을 실제로 운영하고 있으며 지속 가능성을 포함한 어떤 관점에서도 공식적이지 않은 방식으로 운영했던 과거의 접근 방식으로는 더 이상 지속할 수 없다고 한 Fernado Perez의 이야기와 맥락이 닿습니다. 우리는 지속 가능한 오픈 프로젝트를 목표로 더 책임감을 갖고 더 현실적이고 냉철한 프레임워크를 만든다면 돈이 있는 투자자(그 도구를 사용하는 기술 회사나 학계 공동체)가 지속 가능성을 만드는 일을 도울 수 있을 겁니다. 이런 지속성 문제를 어떻게 해결할지 고민하는 것은 (예를 들어) 구글이 해야 할 일이 아니라 우리가 고민해서 그들에게 어떻게 우리를 도와야 하는지 이야기하고 그들이 우리와 함께 할 때 일을 해쳐나가는 것이 우리가 해야 할 일입니다. 그러나 지금 당장 중요한 프로젝트 대부분은 이런 접근이 어렵습니다. 그리고 어떤 경우도 간단하게 해결할 수 있는 문제가 아닙니다. 하지만 공유 자원이 이런 문제를 해결할 수 있는 접근법이 될 수 있습니다. 함께 생각해봅시다!

개인적으로 제가 참여했던 여러 오픈소스 프로젝트에서 어떤 노력을 했는지 다시 살펴보게 되어 흥미로웠습니다. 그 노력 중 하나도 지속적이지도, 지속되지도 않았습니다. 🙂 또한 그렇게 참여했던 프로젝트에서 Ostrom의 디자인 원칙에 맞지 않은 부분도 볼 수 있었습니다. 이 이야기는 다른 포스트에서 이어가도록 하겠습니다.

— 타이투스

특별히 Cameron Neylon과 Michael Nielsen에게 감사합니다. 이들은 Elinor Ostrom의 업적을 몇년 전에 알려줬습니다. Nadia Eghbal의 설명에도 감사를 전합니다. 주제에 대한 설명이 이 글의 재료가 되었고 앞으로도 같이 고민하며 전진했으면 합니다.

이 글을 쓰며 많은 이름을 언급했는데 Luiz Irber, Katy Huff, Katie Mack, Cory Doctorow, Jake VanderPlas, Tracy Teal, Fernando Perez, Michael Crusoe와 Matthew Turk에게 감사를 전합니다. #scifoo18과 #gccbosc에서도 같은 주제로 대화를 할 수 있었기에 SciFoo와 BOSC에도 감사합니다.

알고리즘 학습에 대한 조언

Buck Shlegeris의 My advice on studying algorithms를 번역했다.


알고리즘 학습에 대한 조언

소프트웨어공학 면접에서는 화이트보드 알고리즘 질문을 종종 냅니다. 이런 질문을 어떻게 공부해야 하는지 조언을 하려고 합니다. (저는 구글과 애플을 포함한 수많은 화이트보드 면접을 통과했습니다. 그리고 프로그래머가 이런 알고리즘 면접을 준비하도록 돕는 일이 제 직업의 일부입니다. 게다가 다양한 분야의 개발자를 대상으로 200회 이상의 기술 면접을 치뤘습니다.)

이 글은 Triplebyte이 아닌 제 자신으로서 쓰는 글입니다.

알고리즘 외에도 면접에 관한 여러 주제가 있습니다. 이런 주제는 Triplebyte의 포스트에서 잘 다루고 있습니다. 이 글에서 중요하게 다루려고 하는 내용은 Triplebyte의 포스트에서 2번 항목에 해당합니다.

배경: 왜 회사는 알고리즘 문제를 낼까요?

실생활에서 프로그래머가 이진트리 검색이나 그래프 탐색 알고리즘을 구현하는 시간은 거의 존재하지 않습니다. 그런데 왜 회사는 알고리즘에 대해 많은 질문을 낼까요?

이 질문을 존 왓슨과 코난 도일의 관점으로 해석할 수 있습니다. “회사가 알고리즘 문제를 내는 것이 왜 유용한가?”, 그리고 “어떤 회사가 알고리즘 질문을 하는 실제 일반적 원리가 무엇인가?”가 그 관점입니다.

먼저 알고리즘을 물어보는 이유를 설명하려고 합니다. 그리고 더 나아가 이 유행에 대한 냉소적인 입장에서 설명합니다.

먼저 직업 프로그래머 대다수가 아주 기초적인 일을 수행하지 못합니다. 예를 들어 고객 객체 목록이 있고 각 고객 객체에 구입 객체 배열이 존재합니다. 지난 주에 가장 많이 구입한 고객 다섯 명의 이름을 찾으려고 합니다. 제 예상에는 직업 프로그래머의 50%가 이 문제를 30분 이내에 풀지 못합니다. 이런 사람들을 실수로라도 채용하고 싶지 않을겁니다.

조금 덜 비관적으로 가정해봅시다. 프로그래밍 일을 위해 누군가 면접을 볼 때 어렵고 혼란스러운 문제를 잘 풀어낼 수 있는지 알아내려고 할겁니다. 모든 세세한 내용을 머리에 담고 있어야 풀 수 있는 것을 말이죠. 실생활에서 혼란스럽고 복잡한 문제가 존재하는 이유는 그 프로젝트를 몇 주 동안 봐야 할 만큼 큰 규모고 소프트웨어의 여러 부분을 동시에 고려해야 하기 때문입니다. 하지만 면접은 일반적으로 그렇게 깊은 프로그래밍 문제를 다룰 만큼 시간이 넉넉하지 않습니다. 그래서 규모가 크기 때문에 복잡한 문제를 물어보는 것보다 짧고 복잡한 질문을 물어보는 것입니다.

그럼 어떻게 복잡하지만 쉽게 설명할 수 있는 짧은 코딩 문제를 낼 수 있을까요? 그런 관점으로 생각해보면 제 생각에 여기서는 알고리즘이 좋은 선택입니다. 알고리즘은 컴퓨터 과학에서 대부분의 소프트웨어 엔지니어가 알고 있는 복잡한 분야며 쉽게 설명할 수 있고 구현하기 힘든 문제가 많이 존재합니다.

여기 조금 냉소적인 설명이 따라옵니다.

면접 프로세스는 이상할 정도로 끈적합니다. 엔지니어링팀은 팀의 기술 면접을 통과한 사람으로만 구성되어 있습니다. 그래서 모두가 면접이 옳은 방식이라고 믿게 되고 면접 과정이 소프트웨어 엔지니어링 능력을 측정하는데 매우 정확하다고 생각하게 됩니다. 그래서 회사에 알고리즘 면접 문화가 생기고 나면 그 이후로 바꾸기가 어려워집니다.

또한 모두가 알듯 구글은 10년 전에 놀라운 팀이 있었습니다. (지금은 그 당시보다 적습니다.) 그 당시에 구글은 알고리즘 면접 질문을 했습니다. 대부분의 회사가 자신들이 구글이 아니라는 점에 조금 불안했는지 (알다시피 최고의 지원자는 구글에 다 잃었으니까요), 이 회사도 구글 면접 과정을 따라하기 시작했습니다.

최악의 경우로 보면 알고리즘 면접은 기괴하고 못살게 구는 절차로 바뀌어 버립니다. 가끔 회사에서 무작위 난제를 내는 것이 위대한 지원자를 찾는 비밀 병기라고 단단히 착각해버려서 그런 생각을 바꾸는 일이 불가능한 경우가 있습니다.

종합해서 말하자면, 저는 이런 전통적이고 어려운 알고리즘 문제를 면접에서 안냈으면 합니다. 최악으로는 알고리즘 문제가 극단적으로 나쁜 면접 질문이 될겁니다. 제가 특히 싫어하는 질문은 이런 상황을 위해 따로 적어뒀습니다. 알고리즘 질문은 난제나 여러 통찰을 요구하는 경우에 특히 나쁜 질문입니다. (만약 알고리즘 면접 과정을 만들고 싶다면 언제든지 이메일을 보내시기 바랍니다. 이런 문제가 없는 질문을 하는 방법에 대해 더 자세한 의견을 드릴 수 있습니다.)

어떻게 공부하나요?

추가: Haseeb Qureshi의 블로그 포스트를 읽었는데 이 글에 동의합니다. 그리고 이 글이 좀 더 상세하다고 생각합니다. “일반 학습 전략”과 “프로그래밍 면접 공부 가이드” 부분을 읽으세요.

저는 알고리즘 문제에 답하려면 두 가지 다른 기술이 필요로 하다고 생각합니다. 첫째로 모든 대표적 알고리즘과 자료 구조 문제를 알아야 합니다. 둘째로는 부담되는 상황에서 알고리즘 논리를 화이트보드에 빠르게 풀어나갈 수 있어야 합니다. 이 두 주제를 나눠서 얘기해보려고 합니다.

표준 알고리즘 자료

회사의 시험을 준비하는데 있어 습득해야 하는 거의 필수적인 핵심 알고리즘 모음이 있습니다. 회사에서는 이런 목록에 들어있지 않은 질문은 하지 않으려고 합니다. 좋은 프로그래머 다수가 이 목록에 없는 질문에 대해서는 답을 모르기 때문이며 그래서 목록 외 질문을 냈다가 회사는 좋은 사람을 뽑는데 실패하게 됩니다.

알아야 할 자료구조는 다음과 같습니다.

  • list 구조: 배열, 동적 배열, 링크드 리스트(linked list)
  • set과 map 구조: 해시맵, 이진 검색 트리, 힙

여기서 언급한 자료구조는 필수 메소드가 어떻게 구현되어 있는지, 런타임은 어떻게 동작하는지 알아야 합니다. (list의 필수 메소드는 set, get, pushAtEnd, popAtEnd, insertByIndex, removeByIndex, set의 필수 메소드는 insert, remove, contains? 입니다.) 자료구조 구현을 어떻게 사용하는지 알아야 합니다. 예를 들면 getNearestElementTo(x) 메소드를 구현할 수 있어야 합니다. 이 메소드 즉, x와 가장 가까운 값을 찾는 구현을 하려면 이진 검색트리를 알아야 합니다.

이 문제를 해결하는데 이런 내용을 알아야 합니다.

  • 이진 검색트리 구현에 균형을 맞추는 코드가 필요하다는 점을 알아야 하지만 세부 내용은 몰라도 괜찮습니다. (선택 자료: 자기 균형 BST을 어떻게 구현하는지 빠르게 배우고 싶다면 이 트립을 참조하세요. 어떻게 레드블랙 트리가 동작하는지 이해하고 싶다면 좌편향 레드블랙 트리 또는 2-3-4 트리를 배우세요.)
  • 큐를 스택 두 개로 구현할 수 있다는 점을 알아야 합니다.

다음 알고리즘은 어떻게 구현하는지 알아야 합니다.

  • 그래프 알고리즘: 너비 우선 탐색(breadth first search), 깊이 우선 탐색(depth first search), 다익스트라 알고리즘 (dikstra’s algorithm)
  • 빠른 정렬 알고리즘 하나. 병합 정렬(mergesort) 또는 퀵 정렬(quicksort)
  • 배열에서 수행하는 이진 검색. 이 알고리즘은 제대로 작성하기 매우 까다롭고 대략적으로 알고리즘을 이해하고 있더라도 코드로 작성해볼 가치가 있습니다.

그리고 Big O 표기법도 대충이라도 편하게 사용할 수 있어야 합니다.

이 모든 내용을 어떻게 배워야 하나요? 제가 가장 좋아하는 자료는 Skiena의 Algorithm Design Manual입니다. 위에서 언급한 모든 내용을 챕터 2~6에서 다룹니다. 이 책을 좋아하는 이유는 저술 방식이 참여를 유도하고 각 부분에서 중요한 자료에 잘 초점을 맞추고 다루는데 이런 방식은 중요하다고 생각합니다. 이 책은 인터넷에서 무료로 찾을 수 있습니다. 이 책의 단점은 예제가 C로 작성되었다는 점인데 C를 읽지 못하는 개발자라면 접근성이 좋지 않습니다. 저는 챕터 1~6, 12는 꼭 읽어야 한다고 생각합니다. 이 부분은 인터뷰에서 나올 가능성이 극히 낮지만 필요 없다고 생각하는 부분이 진정 핵심적인 부분을 잘 보강한다고 생각하기 때문입니다.

이런 부분에 대략적인 설명을 보고 싶다면 Craking the Coding InterviewInterviewCake.com의 설명이 좋습니다.

저는 Skiena의 책이 극단적일 정도로 건조하고 딱딱한 유명 CLRS 교재보다 낫다고 생각합니다.

그래프 알고리즘에 대한 글을 쓴 적이 있는데 참고가 되었으면 좋겠습니다.

표준 알고리즘 기술

여기까지 인터뷰에 핵심적으로 필요한 부분을 확인했습니다. 이제 다른 종류의 프로그래밍 기술로 무엇을 테스트하는지 확인하고 제가 선호하는 학습 자료도 함께 확인합니다.

이런 기술에 있어서는 Cracking the Coding Interview(이하 CtCI) 책이 가장 유용합니다. 이 책에 대해서 작성한 글입니다.

알고리즘 면접 문제 중 가장 일반적이고 중점적으로 다뤄지는 요소는 다음과 같습니다.

  • 동적 프로그래밍: Skiena 책의 챕터 8 또는 CtCI에서 이 주제의 챕터에서 학습합니다.
  • 재귀: CtCI에 이 주제에 대한 멋진 챕터가 있습니다.
  • 유명 자료 구조를 반복(iterating)하는 문제: CtCI에서 각각의 자료 구조를 다룰 때 이 문제도 함께 다룹니다. 예를 들어 BST에서는 CtCI 트리 챕터를 참고할 수 있습니다.
  • 문제 해결을 위해 빠른 자료 구조를 조합하기: 이런 문제에 대한 예제는 이 글에서 확인할 수 있습니다.

CtCI에서 살펴볼 수 있는 많은 문제를 살펴보는 방법이 제가 드리는 가장 주요한 조언입니다. 이 문제에서 가장 중요하다고 생각하는 부분은 위 목록과 같습니다.

이런 부류의 문제를 어떻게 학습하는지에 대해 일반적인 생각은 이렇습니다. 제 생각엔 답안을 “훔쳐보는” 일은 그래도 괜찮다고 생각합니다. 면접 문제 푸는 일을 내던지고 아예 포기하는 것보다는 문제 풀다가 막히면 해결책을 보는 방법이 차라리 나은 접근이기 때문입니다.

알고리즘 면접에서 성공하기 위한 비기술적 측면

이런 질문은 실제로 부담되는 환경에서 답하는 연습을 해야 합니다. 진짜 사람이 질문하는 상황에서 말이죠. 이 부분에 대해서는 Triplebyte의 블로그 포스트에서 다루고 있고 2, 3, 7번을 읽어보기 바랍니다.

알고리즘과 자료구조에 대해 더 배우기

취업 목적 학습을 넘어서 본인을 위해 즐겁게 알고리즘과 자료구조를 배우고 싶다고 가정해봅시다. 어떻게 더 배워야 할까요?

가장 쉬운 방법은 위에서 필수로 배워야 한다고 한 핵심 자료 구조에 포함되지 않는 자료 구조 중 상대적으로 간단한 자료 구조를 학습하는 방법입니다. 트립, 스킵 목록, 증강 이진검색트리, 서로소 집합 자료구조가 그 예로 모두 쉽게 이해할 수 있는 편이며 모두 멋진 알고리즘입니다.

자료구조 주제 중 이해하기 어렵지만 노력해서 이해하면 좋은 주제도 있습니다. 예를 들어 이 슬라이드에서는 이진트리와 2-3-4 트리를 설명합니다.

흥미로운 자료 구조를 배울 수 있는, 제가 좋아하는 자료는 다음과 같습니다.

  • Skiena의 챕터 12와 이후 챕터
  • 스탠포드의 멋진 강의인 CS166. 이 강의의 슬라이드는 멋지고 읽기 좋은 편입니다. 저는 여기서 다룬 문제가 즐거웠습니다. 자료구조와 더 놀고 싶다면 이 프로젝트 아이디어 핸드아웃을 추천합니다.
  • 저는 이런 작업처럼 그다지 어렵지 않은 자료 구조 문제를 아마추어 활동으로 재미삼아 한다는 점이 자랑스럽습니다. 이 문제를 풀기 위한 해결책으로 고급 자료구조에서 얻은 몇 아이디어를 적용했다는 점이 멋지지 않나 생각합니다.

자료