로컬에서는 되는데 서버에서는 안 됐던 이유, 개발자를 성장시키는 진짜 경험담

개발을 하다 보면 누구나 한 번쯤 겪게 되는 난감한 상황이 있습니다. 내 컴퓨터에서는 너무 잘 돌아가던 코드가 막상 서버에 올리자마자 동작하지 않는 순간입니다. 이 글에서는 제가 직접 겪었던 시행착오와 함께, 왜 이런 일이 발생하는지, 그리고 어떻게 접근해야 하는지에 대해 편하게 풀어보려고 합니다.

1. 내 컴퓨터는 친절했지만, 서버는 냉정했습니다

처음 그 문제를 마주했을 때를 아직도 잊지 못합니다. 로컬 환경에서는 버튼을 누르면 데이터가 잘 저장되고, 화면도 자연스럽게 바뀌고, 에러 한 줄 없이 완벽하게 돌아갔습니다. 그래서 저는 꽤 자신 있게 배포를 진행했습니다. 그런데 서버에 올리자마자 기능이 멈춰버렸습니다. 로그에는 낯선 에러가 찍혀 있었고, 아무리 다시 시도해도 결과는 같았습니다. 그때 처음으로 ‘로컬에서는 되는데 서버에서는 안 됐던 이유’가 단순한 운이 아니라 구조적인 문제라는 걸 깨닫게 되었습니다.

당시 저는 환경 차이에 대해 깊게 생각해 본 적이 없었습니다. 같은 코드인데 왜 다르게 동작할까, 정말 이해가 되지 않았습니다. 하지만 하나씩 뜯어보니, 로컬과 서버는 생각보다 전혀 다른 세상이었습니다. 운영체제, Node 버전, Python 버전, 패키지 버전, 심지어 파일 경로 방식까지 달랐습니다. 로컬에서는 Windows를 사용하고 있었고, 서버는 Linux였습니다. 대소문자를 구분하지 않는 Windows와 달리, Linux는 파일 이름의 대소문자를 정확히 구분했습니다. 저는 UserService.js를 userservice.js로 import 하고 있었고, 그게 서버에서는 바로 에러로 이어졌습니다.

그때 느꼈습니다. 저는 코드를 짜고 있었지, ‘환경’을 고려한 개발을 하고 있지 않았다는 사실을요.

개인적으로 이 경험 이후로 파일 이름 하나를 지을 때도 더 신중해졌습니다. 사소해 보이지만, 이런 디테일이 서버에서는 치명적으로 작용한다는 걸 몸으로 배웠기 때문입니다.

또 다른 문제는 패키지 버전이었습니다. 로컬에서는 최신 버전을 설치해 사용했지만, 서버에는 예전에 설치된 버전이 그대로 남아 있었습니다. package.json은 같았지만, 실제 설치된 모듈은 달랐던 겁니다. 로컬에서는 정상 동작하던 함수가 서버에서는 존재하지 않는 함수가 되어버렸습니다. 이 역시 ‘로컬에서는 되는데 서버에서는 안 됐던 이유’의 전형적인 사례였습니다.

이 일을 겪고 나서 저는 node_modules를 지우고 다시 설치하는 습관, lock 파일을 관리하는 습관, 그리고 배포 전에 서버 환경을 점검하는 습관을 갖게 되었습니다. 예전에는 이런 과정이 번거롭다고 느꼈는데, 지금은 오히려 이 과정이 없으면 불안합니다.

돌이켜보면, 그날의 삽질 덕분에 저는 단순히 코드를 작성하는 개발자에서, 시스템을 이해하려는 개발자로 한 단계 성장했던 것 같습니다.

2. 경로, 권한, 그리고 보이지 않던 설정들

두 번째로 크게 느꼈던 부분은 ‘경로’와 ‘권한’ 문제였습니다. 로컬에서는 파일 업로드 기능이 너무 잘 되었는데, 서버에서는 파일이 아예 저장되지 않았습니다. 로그를 보니 permission denied 에러가 찍혀 있었습니다. 그제야 서버에는 파일을 쓸 수 있는 권한이 필요하다는 아주 기본적인 사실을 떠올렸습니다.

솔직히 말씀드리면, 그 전까지 저는 파일 권한에 대해 거의 신경 써본 적이 없었습니다. 로컬에서는 관리자 권한으로 모든 게 자유롭게 가능했기 때문입니다. 하지만 서버는 달랐습니다. 지정된 디렉토리에만 접근할 수 있었고, 그 외의 위치에는 접근조차 할 수 없었습니다. 이 또한 ‘로컬에서는 되는데 서버에서는 안 됐던 이유’를 설명해주는 중요한 요소였습니다.

경로 문제도 비슷했습니다. 로컬에서는 상대 경로를 대충 작성해도 잘 찾아갔습니다. 하지만 서버에서는 실행 위치가 달라지면서, 상대 경로가 완전히 다른 위치를 가리키고 있었습니다. 결국 절대 경로로 수정하고 나서야 문제가 해결되었습니다.

이때 느낀 점이 있습니다. 우리는 코드 안에서만 문제를 찾으려고 하지만, 실제 원인은 코드 밖에 있는 경우가 정말 많다는 것입니다.

개인적으로 이 경험 이후로, 저는 서버 구조를 먼저 이해하려고 노력합니다. 디렉토리가 어떻게 구성되어 있는지, 어떤 사용자로 실행되는지, 로그는 어디에 쌓이는지 등을 먼저 확인합니다. 예전에는 이런 과정이 낯설었는데, 이제는 오히려 이걸 확인하지 않으면 배포가 두렵습니다.

환경 변수(.env)도 큰 역할을 했습니다. 로컬에는 API 키가 잘 설정되어 있었지만, 서버에는 해당 값이 비어 있었습니다. 그래서 외부 API 호출이 모두 실패하고 있었던 것입니다. 이 역시 너무 단순하지만, 당시에는 전혀 생각하지 못했던 부분이었습니다.

‘로컬에서는 되는데 서버에서는 안 됐던 이유’를 하나씩 경험하면서, 저는 점점 체크리스트를 만들게 되었습니다. 환경 변수 확인, 권한 확인, 경로 확인, 버전 확인. 이런 기본적인 것들이 쌓이면서 배포 실패가 점점 줄어들었습니다.

지금 생각해보면, 이때의 시행착오가 없었다면 저는 여전히 코드만 바라보는 개발자에 머물러 있었을지도 모르겠습니다.

3. 로그를 읽는 습관이 만든 결정적인 차이

마지막으로 가장 큰 차이를 만든 건 ‘로그를 보는 습관’이었습니다. 예전에는 에러가 나면 당황부터 했습니다. 그런데 서버 문제를 반복해서 겪으면서, 저는 자연스럽게 로그를 먼저 보는 습관이 생겼습니다. 그리고 놀랍게도, 대부분의 답은 로그에 이미 적혀 있었습니다.

처음에는 로그가 너무 복잡하고 어려워 보였습니다. 영어로 된 메시지들이 빼곡했고, 어디를 봐야 할지도 몰랐습니다. 하지만 차분히 읽다 보니, 에러의 원인과 위치가 매우 친절하게 설명되어 있었습니다. 다만 제가 읽을 줄 몰랐을 뿐이었습니다.

한 번은 시간대(Timezone) 문제로 데이터가 다르게 저장되는 일이 있었습니다. 로컬은 한국 시간, 서버는 UTC 시간이었기 때문입니다. 날짜 계산이 전부 어긋나 있었고, 그 결과가 화면에 이상하게 표시되었습니다. 이것도 결국 ‘로컬에서는 되는데 서버에서는 안 됐던 이유’ 중 하나였습니다.

이 경험 이후로, 저는 날짜와 시간 처리를 할 때 항상 서버 기준 시간을 먼저 고려합니다. 그리고 로그에 찍히는 시간을 유심히 봅니다.

개인적으로, 로그를 읽는 능력은 개발자에게 굉장히 중요한 역량이라고 느낍니다. 코드 작성 능력 못지않게, 문제를 해석하는 능력이 필요하다는 걸 깨달았기 때문입니다.

또한, 에러를 두려워하지 않게 되었습니다. 예전에는 에러가 나면 ‘망했다’는 생각이 먼저 들었는데, 지금은 ‘아, 단서를 줬구나’라는 생각이 먼저 듭니다. 이 작은 생각의 차이가 문제 해결 속도를 정말 많이 바꿔주었습니다.

결국, ‘로컬에서는 되는데 서버에서는 안 됐던 이유’는 단순한 실수가 아니라, 개발자가 환경을 얼마나 이해하고 있는지 보여주는 지표 같다는 생각이 들었습니다. 이 과정을 겪으면서 저는 코드뿐 아니라, 시스템 전체를 보는 시야를 갖게 되었습니다.

지금도 배포할 때마다 긴장되지만, 예전처럼 막막하지는 않습니다. 왜냐하면 무엇을 확인해야 하는지, 어디를 봐야 하는지를 이제는 알기 때문입니다. 그리고 그 출발점에는 분명, 그 답답했던 경험들이 있었습니다.

✅함께 보면 좋은 글✅