addToFile function에서 path를 사용해 새로운 파일을 생성
let previousContent = "";
const addToFile = async (path, content) => {
if (previousContent === content) return; // 중복 실행 방지를 위한 거름망
if(!(await fileExist(path))) return; // file이 존재하는지 않하는 지 체크
try {
await appendFile(path, content);
previousContent = content;
console.log(`✅ ${content} is successfully appended to ${path}`);
} catch (error) {
if (error.code === "ENOENT") {
console.log(`⚠️ ${path} does not exist`);
}
console.error(`❌ 에러 발생: ${error.message}`);
}
};catch error 부분에서 에러 코드로 ENOENT를 사용해서 path가 존재하지 않는 경우를 잡아내는 코드를 작성했지만, 실제로 실행했을 때 appendFile 자체가 이미 새로운 파일을 생성해내는데 성공하였기 때문에 error로 연결되지 않았습니다.
중복 콘텐츠 방지를 위한 if 밑에 또 다른 if로 fileExist를 사용해서 early return을 하는 이런 방식으로 처리를 하는 게 맞을까요? 아니면 제가 놓친 다른 catch error 가 있는 걸까요?
Câu trả lời 1
0
안녕하세요 Minju Kim님! 질문해 주셔서 감사합니다!
먼저 제가 강의에서 제공해 드렸던 기본 코드를 다시 한번 살펴보겠습니다.JavaScript
let previousContent = ''; // 중복 실행(이벤트 바운스) 방지용 상태 변수
const addToFile = async (path, content) => {
if (previousContent === content) return; // 동일한 내용이 연속으로 오면 무시
try {
await appendFile(path, content);
previousContent = content;
console.log(`📝 내용이 '${path}'에 성공적으로 추가되었습니다.`);
} catch (e) {
console.error(`❌ 파일에 내용 추가 중 오류 발생: ${e.message}`);
}
};
결론부터 말씀드리면, 이 기본 코드에 Minju님이 추가로 작성하신 fileExist를 활용한 Early Return 방식이 현재 요구사항을 완벽하게 해결하는 가장 알맞은 처리 방식입니다. 왜 ENOENT 에러가 발생하지 않았는지 궁금하셨을 텐데, Minju님이 정확히 짚어내신 것처럼 그 원인은 appendFile의 기본 성질에 있습니다.
Node.js의 appendFile 함수는 내부적으로 파일 시스템의 'a' (append) 플래그를 기본값으로 사용합니다. 이 플래그의 OS 레벨 기본 동작 방식은 파일을 추가 모드로 열고 만약 파일이 존재하지 않으면 새로운 파일을 자동으로 생성하는 특징을 가지고 있습니다. 따라서 타겟 파일이 없더라도 에러를 던지는 대신 새로운 파일을 만들어버리며 성공 처리해버리기 때문에, catch 블록의 ENOENT(Error NO ENTry) 에러로 넘어갈 상황 자체가 발생하지 않은 것입니다.
이러한 상황에서 Minju님이 추가하신 다음 코드는 매우 훌륭한 해결책이 됩니다.rp
if(!(await fileExist(path))) return;작성해주신 이 방어 로직은 단순한 임시방편이 아니라, 시스템의 예측 가능성을 높이는 매우 견고한 아키텍처 설계입니다. 프레임워크나 내장 함수가 제공하는 알아서 만들어주는 암묵적인 편의성이 반드시 존재하는 파일에만 추가해야 한다는 우리가 의도한 비즈니스 로직과 충돌할 때가 종종 발생합니다. 이때는 지금처럼 명시적인 검증 단계인 Validation을 함수 도입부에 배치하여 입구에서 튕겨내는 것이 올바른 구조입니다. 깊은 곳에서 에러가 터지길 기다리는 것보다 서버 I/O 리소스 낭비도 막고 코드의 가독성도 훨씬 높여주기 때문입니다.
그렇다면 파일이 존재하지 않는 경우를 잡아내는 목적으로 놓치신 에러가 있는지 궁금하실 수 있는데, 결론적으로 놓치신 부분은 없습니다. 이미 appendFile의 기본 동작이 그 에러를 덮어버리기 때문입니다. 다만, 현재 만들어두신 catch 블록 자체는 지우지 말고 그대로 두시는 것이 맞습니다. 그 이유는 파일에 접근할 권한이 부족한 EACCES 에러나 디스크 용량이 꽉 차는 ENOSPC 에러 등 OS 레벨에서 예기치 않게 발생하는 다른 치명적인 I/O 에러들을 훌륭하게 방어하는 최후의 보루 역할을 든든히 수행하고 있기 때문입니다.
따라서 질문과 함께 제공해주신 코드를 기준으로 어떤 부분을 빼고 어떤 부분을 추가해야 하는지 명확히 짚어드리겠습니다. 가장 먼저 코드에서 빼야 할 부분은 catch 블록 내부에 작성하신 if (error.code === "ENOENT") 조건문입니다.
if (error.code === "ENOENT") {
console.log(`⚠️ ${path} does not exist`);
}이미 도입부에서 fileExist로 튕겨내고 있으며, appendFile 자체가 에러 대신 파일을 생성해 버리므로 이 부분은 절대 도달할 수 없는 코드가 되었습니다. 따라서 이 부분은 과감히 삭제하시는 것이 좋습니다. 반대로 코드에 새롭게 추가해야 할 부분은 fileExist 로직 안쪽의 안내 메시지입니다.
if (!(await fileExist(path))) {
console.log(`⚠️ ${path} does not exist`);
return;
}기존 코드는 파일이 없을 때 아무런 피드백 없이 return으로 조용히 종료되지만, 위와 같이 console.log로 경고 메시지를 남겨두면 사용자와 시스템 모두 왜 명령이 실행되지 않았는지 투명하게 추적할 수 있어 훨씬 견고한 로직이 완성됩니다.
이러한 모든 맥락과 Minju님의 훌륭한 접근을 종합하여, 실무 서버에서도 완벽하게 동작할 최종 보완 코드를 작성해 보았습니다.
let previousContent = ''; // 중복 실행(이벤트 바운스) 방지용 상태 변수
const addToFile = async (path, content) => {
// 1차 방어: 동일한 내용이 연속으로 오면 무시 (이벤트 디바운싱 효과)
if (previousContent === content) return;
// 2차 방어: 의도치 않은 새 파일 생성을 원천 차단 (Early Return)
if (!(await fileExist(path))) {
console.log(`⚠️ 경고: '${path}' 파일이 존재하지 않아 내용을 추가할 수 없습니다.`);
return;
}
try {
await appendFile(path, content);
previousContent = content;
console.log(`📝 내용이 '${path}'에 성공적으로 추가되었습니다.`);
} catch (e) {
// fileExist로 거르지 못한 OS 레벨의 치명적 예외 상황 처리
console.error(`❌ 파일에 내용 추가 중 치명적 오류 발생: ${e.message}`);
}
};이 코드가 최종적인 형태인 이유는 우리가 설계한 두 겹의 방어막이 완벽한 시너지를 내기 때문입니다. 첫 번째 조건문은 불필요한 중복 I/O 요청을 막아 메모리를 보호하고, Minju님이 제안하신 두 번째 조건문은 appendFile의 암묵적 파일 생성 기능을 억제하여 비즈니스 로직의 엄격함을 유지합니다. 동시에 try-catch 블록은 파일 권한 부족과 같은 진짜 예기치 못한 시스템 에러만을 순수하게 포착하도록 역할이 명확히 분리되었습니다.
실무적인 관점에서 보았을 때, 이렇게 로우레벨 모듈이 내부적으로 어떻게 동작하는지 의심하고 스스로 검증해내는 과정은 탄탄한 시스템 아키텍트로 성장하는 가장 확실한 길입니다. 커맨드 센터 로직이 아주 흠잡을 데 없이 완성되었으니, 앞으로도 이 방식 그대로 밀고 나가시면 좋겠습니다. 추가로, 현재 적용된 할인율보다 훨씬 더 높은 할인이 적용된 강의 쿠폰이 필요하시다면 언제든 jeony0535@naver.com 으로 이메일 남겨주시기 바랍니다. 확인하는 대로 바로 전달해 드리겠습니다. 계속해서 파이팅입니다! 감사합니다!
컴퓨터구조론에 관해서
0
10
1
메모리 동적할당시 메모리창 빨간 글씨
0
15
2
[46강] EventEmitter를 활용한 10가지 패턴 중 플러그인 아키텍처
0
20
2
강의가 누락된것 같습니다.
0
36
2
섹션3에 대한 문의사항
0
50
2
쿼터스 스케메틱에 대한 질문
0
28
2
examtopics와 krdumps 차이가 나는데요 ㅠ
0
45
1
추가 강의 있으면 좋겠어요.
0
49
2
용어 발음법이 계속 바뀌는 것 같은데 이런 부분들 개선이 가능할까요...?
0
44
1
vscode 다루는법을 모르겠습니다
0
24
1
counter01.html은 어디있을까요?
1
16
1
리눅스로 진행해도 될까요?
0
34
2
존재하지 않는 일기 url입력 시 alert이 두 번 떠요
0
38
1
useState 직접 구현 부분에서 질문이 있습니다.
1
43
1
FIFO 질문
0
25
2
학습을 하고 블로그에 정리를 해도 괜찮을까요?
1
41
1
Design a Toast Notification System 미션 관련 질문드립니다.
0
68
1
교재(3쇄)와 강의 내용 문의
0
36
2
call stack 표현이 잘못표현된것이 아닌가요?
0
81
2
혹시 다음 강의 제작 예정된 것들이 있을까요?
0
95
1
1강 질문
0
74
2
ai가 만든 강의인가요?
0
160
1
3강 질문
0
84
2
2강 nodejs 3단계 설명 질문
0
96
1

