면접 전날 리눅스 개발 환경을 복제해 본 포트폴리오 후기
기술 면접을 하루 앞두고 포트폴리오의 오래된 프로젝트를 다시 실행했는데, 첫 명령부터 오류가 쏟아졌습니다. 제 노트북에서는 분명 작동하던 PHP API와 자바스크립트 화면이 새 리눅스 환경에서는 연결되지 않았고, 설치 과정도 README와 달랐습니다. 그 순간 프로젝트의 완성도보다 더 불안했던 것은 면접관이 저장소를 내려받았을 때 같은 문제를 겪을 수 있다는 사실이었습니다.
그래서 빈 Ubuntu 가상 머신을 만들고, 처음 보는 사람처럼 제 개발자 포트폴리오를 복제해 봤습니다. 예상보다 손이 많이 갔지만 결과적으로 README, 실행 스크립트, 환경 변수 예시, 데모 데이터까지 한꺼번에 개선할 수 있었습니다. 아래 내용은 그날 실제로 막혔던 지점과 고친 방법, 그리고 다시 해보며 느낀 장단점을 기록한 사용 후기입니다.
새 Ubuntu에서 저장소를 처음 열었을 때 드러난 문제
내 컴퓨터의 익숙함이 문서를 대신하고 있었습니다
테스트에는 평소 쓰던 장비 대신 메모리 4GB, CPU 2코어의 Ubuntu 가상 머신을 사용했습니다. Git과 브라우저 정도만 설치된 상태에서 저장소를 복제한 뒤 README의 명령을 위에서부터 그대로 입력했습니다. 여기서 가장 먼저 발견한 문제는 PHP 확장 모듈 누락이었고, 다음은 Node.js 버전 차이, 마지막은 로컬에서만 존재하던 데이터베이스 계정이었습니다. 개발자인 저는 무의식적으로 해결할 수 있었지만, 방문자는 오류 메시지를 해석할 이유가 없습니다.
특히 README에 적어 둔 ‘의존성을 설치하고 서버를 실행한다’는 문장이 너무 추상적이었습니다. 어떤 PHP 버전이 필요한지, npm과 pnpm 중 무엇을 쓰는지, 데이터베이스 초기화 순서는 무엇인지 빠져 있었습니다. 포트폴리오의 용어적 의미처럼 결과물을 한데 모으는 데서 그치지 않고, 소프트웨어 포트폴리오는 다른 사람이 결과를 확인할 수 있는 경로까지 포함해야 한다고 느꼈습니다.
처음에는 새 환경을 준비하는 시간이 낭비처럼 보였습니다. 그러나 한 시간 동안 나온 오류 목록이 곧 문서 개선 순서가 됐습니다. 잘 꾸민 프로젝트 소개보다 실제 설치 실패 한 건이 신뢰를 더 크게 떨어뜨릴 수 있다는 사실도 체감했습니다.
- 재현된 문제: PHP 확장 모듈, Node.js 버전, 데이터베이스 권한이 문서에서 누락됐습니다.
- 좋았던 점: 기존 노트북의 캐시와 전역 패키지에 가려진 의존성을 빠르게 찾았습니다.
- 아쉬운 점: 가상 머신 이미지 다운로드와 초기 업데이트 때문에 첫 준비에 약 30분이 추가됐습니다.
- 사용 팁: 오류를 즉시 고치기보다 명령, 메시지, 해결 시간을 먼저 기록하면 README의 문제 순서를 잡기 쉽습니다.
포트폴리오를 처음 보는 사람은 작성자의 기억을 설치할 수 없습니다. 저장소 안의 문서와 자동화 파일만으로 실행돼야 합니다.
설치 명령을 줄이자 프로젝트 설명이 더 선명해졌습니다
한 줄 실행보다 실패 원인을 보여주는 자동화가 유용했습니다
처음에는 모든 작업을 하나의 셸 스크립트에 넣어 한 줄로 실행되게 만들었습니다. 사용하기는 편했지만 중간 단계가 실패하면 원인을 찾기 어려웠습니다. 결국 환경 검사, 의존성 설치, 데이터베이스 준비, 애플리케이션 실행을 각각 분리했습니다. 사용자는 전체 명령을 순서대로 실행할 수 있고, 문제가 생기면 어느 단계에서 멈췄는지 바로 알 수 있었습니다.
환경 검사 스크립트에는 PHP와 Node.js의 최소 버전, 필요한 포트의 사용 여부, 필수 확장 모듈을 확인하는 기능만 넣었습니다. 운영체제에 패키지를 강제로 설치하거나 관리자 권한을 요구하지 않도록 한 점이 중요했습니다. 자동화가 지나치게 공격적이면 사용자의 기존 환경을 바꿀 수 있기 때문입니다. 대신 부족한 항목과 권장 설치 명령을 출력하게 했더니 안전성과 친절함을 함께 확보할 수 있었습니다.
직접 써보니 가장 큰 장점은 면접 중 설명이 간결해진다는 점이었습니다. “제 컴퓨터에서는 됩니다”가 아니라 “검사 명령이 실행 조건을 확인하고, 네 단계로 재현됩니다”라고 말할 수 있었습니다. 반면 Windows와 macOS까지 모두 지원하려 하면 스크립트가 복잡해졌습니다. 제 프로젝트의 기준 환경은 Linux라고 명확히 쓰고, 다른 운영체제에서는 Docker 사용을 권장하는 방식이 현실적이었습니다.
- check-env에서 런타임 버전과 포트 충돌을 검사했습니다.
- install에서는 잠금 파일을 기준으로 PHP와 JavaScript 의존성을 설치했습니다.
- seed는 개인 정보가 없는 샘플 데이터를 생성하도록 구성했습니다.
- start는 API와 프런트엔드의 로그를 분리해 출력하게 만들었습니다.
- 각 단계가 끝나면 다음에 입력할 명령과 예상 소요 시간을 표시했습니다.
Docker를 붙여 보니 편리함과 무거움이 동시에 보였습니다
로컬 설치와 컨테이너 실행을 모두 남긴 이유
두 번째 실험에서는 Docker Compose로 PHP, 웹 서버, 데이터베이스를 묶었습니다. 깨끗한 Ubuntu에서 Docker만 설치한 뒤 실행하니 로컬 패키지 버전 충돌은 거의 사라졌고, 약 7분 만에 샘플 화면을 확인할 수 있었습니다. 특히 오래된 PHP 프로젝트처럼 최신 배포판의 기본 패키지와 맞지 않는 작업을 보여줄 때는 컨테이너가 큰 도움이 됐습니다.
그렇다고 Docker만 제공하는 것이 항상 최선은 아니었습니다. 최초 이미지 다운로드 용량이 컸고, 메모리가 작은 가상 머신에서는 데이터베이스와 프런트엔드 빌드를 동시에 올릴 때 반응이 느렸습니다. 컨테이너 내부를 잘 모르는 방문자는 단순한 파일 권한 오류에도 당황할 수 있었습니다. 그래서 저는 빠른 체험용 Docker 경로와 구조를 살펴보기 좋은 로컬 실행 경로를 함께 남겼습니다.
비용 면에서는 Ubuntu, Git, Docker의 기본 사용료가 없어 별도 SaaS 지출은 없었습니다. 다만 클라우드 가상 머신으로 같은 검증을 반복한다면 시간당 과금과 스토리지 비용이 생길 수 있습니다. 짧은 테스트라면 로컬 가상 머신으로 충분했고, 외부 네트워크나 실제 배포 조건까지 확인할 때만 소형 클라우드 인스턴스를 잠깐 사용하는 편이 효율적이었습니다. 독자 여러분의 프로젝트가 단일 정적 페이지라면 Docker가 오히려 과한 장식은 아닌지도 먼저 물어볼 필요가 있습니다.
- Docker가 잘 맞는 경우: PHP 확장, 데이터베이스, 캐시 서버처럼 여러 실행 조건이 얽힌 프로젝트입니다.
- 로컬 실행이 나은 경우: 의존성이 적은 바닐라 JavaScript 도구나 정적 포트폴리오입니다.
- 실사용 장점: 새 장비에서도 같은 런타임과 샘플 데이터를 비교적 빠르게 재현했습니다.
- 실사용 단점: 이미지 용량, 낮은 사양에서의 속도, 파일 권한 설명이 추가로 필요했습니다.
컨테이너는 프로젝트를 돋보이게 하는 훈장이 아니라 실행 조건을 고정하는 도구입니다. 복잡성을 실제로 줄일 때만 넣는 편이 좋습니다.
README를 면접관의 10분 동선에 맞춰 다시 써봤습니다
설치법보다 먼저 보여줘야 했던 것은 프로젝트의 이유였습니다
재현에 성공한 뒤에는 README를 처음부터 다시 읽었습니다. 기존 문서는 기술 스택과 설치 명령으로 바로 시작했지만, 면접관이 궁금해할 ‘무슨 문제를 해결했는가’와 ‘내가 맡은 부분은 무엇인가’가 뒤쪽에 숨어 있었습니다. 상단을 프로젝트 한 문장 소개, 핵심 성과, 데모 또는 실행 경로, 담당 범위 순서로 바꾸자 짧게 읽어도 맥락이 전달됐습니다.
저는 README를 약 10분짜리 동선으로 나눴습니다. 첫 1분에는 결과와 역할을 파악하고, 다음 3분에는 구조와 중요한 의사결정을 읽으며, 남은 시간에는 직접 실행하거나 테스트 로그를 살펴보게 했습니다. 단순히 작업물을 모아 놓는 관점과 달리 개발자 포트폴리오는 선택의 근거까지 보여줘야 합니다. 서로 다른 분야에서 쓰이는 포트폴리오 정의와 활용 맥락을 참고하되, 소프트웨어 프로젝트에는 재현 절차와 기술적 판단을 더하는 것이 자연스러웠습니다.
실제 면접에서는 모든 코드를 읽어 달라고 요구하기보다 특정 파일 세 곳을 안내했습니다. 예를 들어 인증 흐름, 데이터 접근 계층, 실패를 검증하는 테스트 파일에 링크를 걸었습니다. 그 결과 설명이 저장소 여기저기로 흩어지지 않았습니다. 다만 성과 수치를 강조하려다 근거 없는 백분율을 쓰는 실수는 피했습니다. 측정 환경과 전후 조건을 제시할 수 없는 숫자라면, 처리 시간이나 테스트 범위처럼 다시 확인 가능한 사실로 바꾸는 편이 낫습니다.
- 첫 화면에서 프로젝트 목적, 담당 역할, 현재 상태를 세 문장 안에 표시했습니다.
- 빠른 실행에는 복사 가능한 명령과 예상 소요 시간, 정상 화면의 기준을 적었습니다.
- 설계 선택에는 채택한 방법뿐 아니라 포기한 대안과 이유를 짧게 덧붙였습니다.
- 테스트 항목에는 실행 명령, 통과 개수, 일부 실패 시 확인할 로그 위치를 연결했습니다.
- 마지막에는 알려진 제한과 다음 개선 과제를 공개해 과장된 인상을 줄였습니다.
복제 테스트에서 반복해서 걸린 세 가지 함정
비밀값, 샘플 데이터, 종료 절차를 빼먹지 않아야 했습니다
가장 위험했던 실수는 실제 환경 변수 파일을 편의상 저장소에 넣으려 한 것입니다. API 키와 비밀번호는 당연히 제외했지만, 예제 파일까지 비워 두면 사용자는 어떤 값을 넣어야 할지 알 수 없습니다. 그래서 .env.example에는 안전한 가짜 값과 필드별 설명을 넣고, 시작 스크립트가 필수 값의 누락만 검사하게 했습니다. Git 기록에 과거 비밀값이 남아 있지 않은지도 별도로 확인했습니다.
두 번째 실수는 샘플 데이터가 제 로컬 데이터에 의존한 점이었습니다. 테이블은 생성되는데 첫 화면이 비어 있어 프로젝트가 고장 난 것처럼 보였습니다. 실제 사용자 정보가 섞이지 않은 작은 데이터 세트를 만들고, 같은 명령을 여러 번 실행해도 중복되지 않도록 수정했습니다. 세 번째는 종료 방법의 누락이었습니다. 테스트 후 서버와 컨테이너가 계속 실행되면 포트를 차지하고 메모리를 사용하므로, README에 중지와 초기화 명령을 설치 절차만큼 눈에 띄게 배치했습니다.
마지막으로 모든 것을 자동화했다는 이유로 수동 검증을 생략하면 안 됩니다. 저는 브라우저에서 핵심 화면 세 개를 열고, 신규 사용자 흐름과 오류 응답을 직접 확인한 뒤 로그에 개인 경로가 노출되지 않는지 살폈습니다. 포트폴리오 방문자가 실행에 실패했을 때 연락할 방법과 이슈 양식도 마련했습니다. 실행 성공만큼 실패했을 때의 안내가 프로젝트의 관리 수준을 보여준다는 것이 이번 사용 경험에서 가장 오래 남은 교훈이었습니다.
- 비밀값을 예제에 복사하는 실수: 형식만 유지한 가짜 값으로 대체하고 저장소 기록까지 검사합니다.
- 빈 화면을 정상으로 착각하는 실수: 최소 샘플 데이터와 확인 가능한 사용자 시나리오를 제공합니다.
- 시작 명령만 문서화하는 실수: 중지, 데이터 초기화, 볼륨 제거의 차이를 함께 설명합니다.
- 최신 환경에서만 확인하는 실수: 지원할 최소 런타임 버전에서도 설치와 테스트를 한 번 실행합니다.
- 오류를 숨기는 실수: 알려진 제한, 재현 조건, 로그 위치를 공개해 방문자가 다음 행동을 선택하게 합니다.

- 다음글프로젝트가 늘어 개발자 포트폴리오 구조가 고민이라면 26.08.19
등록된 댓글이 없습니다.
