refactor boundary

리팩터링의 결과는 두 에러 경로를 main에서 모으는 구조다

인수 파싱 실패와 파일 읽기 실패는 서로 다른 함수에서 생기지만, 사용자 메시지와 종료 코드는 `main`이 한곳에서 결정한다.

인수 파싱 경로

Config::build args 길이를 검사하고 설정 객체를 만든다.
Err(&str) 인수가 부족하면 "not enough arguments"를 반환한다.
unwrap_or_else 사용자 친화 메시지를 출력하고 `process::exit(1)`로 끝낸다.

프로그램 실행 경로

run(config) 파일을 읽고 이후 작업을 수행하는 실행 로직을 맡는다.
? operator I/O 실패를 패닉 대신 호출자에게 전파한다.
if let Err `Application error`를 출력하고 실패 종료 코드로 닫는다.
src/main.rs
env::args 외부 입력을 수집한다.
Config 설정 생성 실패를 메시지로 바꾼다.
run 실행 실패를 검사하고 종료한다.
src/lib.rs

프로그램 로직은 공개 API로 이동한다

`Config`는 검색어와 파일 경로를 소유하고, `run`은 파일 읽기와 이후 검색 동작을 맡는다. 이제 `main`을 직접 테스트하지 않아도 핵심 동작을 `lib.rs`의 함수로 검증할 수 있다.

작은 main 명확한 Config panic 제거
다음 작업

구조가 분리되었으므로 검색 함수처럼 실제 로직을 `lib.rs`에 추가하고, 커맨드 라인 실행 없이 단위 테스트로 결과를 검증할 수 있다.