PHP에서 Go로: 사고방식을 바꾸는 데 가장 오래 걸린 것들
7년 동안 PHP를 작성했습니다. 그중 5년은 Laravel을 사용했습니다. Laravel 모놀리스에서 마이크로서비스로의 전환을 주도하기 위해 Go로 옮겨갔을 때, 저는 튜토리얼을 들고 온 것이 아니었습니다. 저는 10년 동안 몸에 밴 PHP 습관을 들고 왔습니다.
문법을 배우는 것은 쉬웠습니다. Go는 오후 한나절이면 읽을 수 있습니다. 어려운 점은 코드를 생각하는 방식을 버리는 것이었습니다.
제가 마스터하는 데 몇 달이 걸린 사고방식의 변화는 다음과 같습니다:
에러 처리 PHP에서는 try/catch를 사용했습니다. 에러는 종종 전역 핸들러로 보이지 않게 전달되었습니다. Go에서 에러는 값(value)입니다. 함수는 마지막 값으로 에러를 반환합니다. 그 자리에서 즉시 처리해야 합니다. 처음에는 이것이 추가적인 작업처럼 느껴졌습니다. 나중에 저는 이것이 실패를 가시화한다는 것을 깨달았습니다. 서비스가 실패할 때, 에러 메시지는 빵부스러기(breadcrumb) 같은 흔적 역할을 합니다. 거대한 스택 트레이스 없이도 실패가 정확히 어디서 발생했는지 알려줍니다.
메모리와 상태 PHP는 shared-nothing 모델을 사용합니다. 모든 요청은 깨끗한 상태에서 시작됩니다. 프로세스가 요청 후 종료되기 때문에 메모리 누수가 덜 중요합니다. Go는 다릅니다. 프로세스가 수천 개의 요청 동안 살아있습니다. 이는 패키지 수준의 변수가 모든 요청에서 공유된다는 것을 의미합니다. 만약 두 요청이 동시에 맵(map)에 쓰려고 하면 프로그램 전체가 충돌합니다. Go에서는 동시성(concurrency)을 직접 관리해야 합니다. 안전을 유지하기 위해 race detector와 같은 도구를 사용해야 합니다.
Context의 역할 PHP에서는 요청(request)이 경계입니다. 요청이 끝나면 모든 것이 멈춥니다. Go에서는 아무것도 자동으로 멈추지 않습니다. 클라이언트가 연결을 끊어도 goroutine은 계속 실행되어 리소스를 낭비할 수 있습니다. 코드 전체에 취소 신호를 전달하려면
context.Context를 사용해야 합니다. 이는 과부하 상황에서도 서비스를 건강하게 유지해 주는 중심축입니다.상속보다 합성 Laravel은 베이스 클래스를 확장하는 것에 크게 의존합니다. 동작을 상속함으로써 기능을 추가합니다. Go에는 클래스 상속이 없습니다. 암시적으로 충족되는 인터페이스를 사용합니다. 필요한 것을 사용하는 곳에서 정의합니다. 이는 코드를 테스트하고 교체하기 쉽게 만듭니다. 좋은 Go 코드를 작성하기 위해서는 모든 것을 확장하려는 본능을 버려야 했습니다.
영리함보다 명확함 PHP는 매직 메서드(magic methods)와 동적 타이핑을 허용합니다. 영리하고 표현력이 풍부한 코드를 작성할 수 있습니다. Go는 의도적으로 지루합니다. 컴파일러는 표준 포맷팅을 강제하고 사용하지 않는 변수를 방지합니다. 처음에는 이것이 제한적으로 느껴졌습니다. 이제는 그 가치를 압니다. Go는 코드를 작성하는 사람이 아니라 읽는 사람에게 최적화되어 있습니다. 지루한 코드는 장애 발생 시 새벽 2시에도 수정하기 쉽습니다.
새로운 언어를 배우는 것의 어려운 점은 새로운 문법이 아닙니다. 그것은 당신이 가지고 있는 오래된 전제(assumptions)들입니다.
Source: https://dev.to/econ__11/from-php-to-go-what-took-me-longest-to-rewire-2nfn
