Hacker News 의견
  • The Valid method takes a context (which is optional but has been useful for me in the past) and returns a map. If there is a problem with a field, its name is used as the key, and a human-readable explanation of the issue is set as the value.

    • 유효성 검사 방법: 선택적인 컨텍스트를 받아 문제가 있는 필드를 키로 하고 문제 설명을 값으로 하는 맵을 반환함. 이 방식은 과거에 유용했음을 언급함.
  • I used to do this, but ever since reading Lexi Lambda's "Parse, Don't Validate," I've found validators to be much more error-prone than leveraging Go's built-in type checker.

    • 유효성 검사 대신 파싱: Lexi Lambda의 "Parse, Don't Validate"를 읽은 후, Go의 내장 타입 검사기를 활용하는 것이 유효성 검사보다 오류 가능성이 낮다고 느낌.
  • For example, imagine you wanted to defend against the user picking an illegal username. Like you want to make sure the user can't ever specify a username with angle brackets in it.

    • 사용자 이름 유효성 검사 예시: 사용자가 꺾쇠 괄호가 포함된 불법적인 사용자 이름을 선택하지 못하도록 방어하는 상황을 상상함.
  • With the Validator approach, you have to remember to call the validator on 100% of code paths where the username value comes from an untrusted source.

    • 유효성 검사기 접근법의 문제점: 불신할 수 있는 출처에서 온 사용자 이름 값에 대해 모든 코드 경로에서 유효성 검사기를 호출해야 하는 부담이 있음.
  • Instead of using a validator, you can do this:

    • 유효성 검사 대안 제시: 유효성 검사기를 사용하는 대신, 다른 방법을 제안함.
  • That guarantees that you can never forget to validate the username through any codepath. If you have a Username object, you know that it was validated because there was no other way to create the object.

    • 객체 생성을 통한 유효성 보장: Username 객체를 생성하는 과정에서 유효성 검사가 이루어지므로, 어떤 코드 경로를 통해서도 유효성 검사를 잊을 수 없게 됨.
  • I really like Mat Ryer's work, and I've applied most of the ideas in the 2018 version of this article to all of my Go projects since then.

    • Mat Ryer의 작업 선호: Mat Ryer의 작업을 매우 좋아하며, 2018년 버전의 기사에 나온 대부분의 아이디어를 자신의 Go 프로젝트에 적용함.
  • The one weak spot for me is this aspect:

    • 약점 지적: 문제가 되는 부분에 대해 언급함.
  • This has always felt wrong to me, but I've never been able to figure out a better solution.

    • 문제에 대한 해결책 부재: 잘못된 것 같지만, 더 나은 해결책을 찾지 못함을 표현함.
  • It means that a huge chunk of your code has a huge amount of unnecessary shared state.

    • 공유 상태의 문제: 코드의 큰 부분이 불필요한 공유 상태를 가지고 있음을 지적함.
  • I often end up writing HTTP handlers that only need access to a tiny amount of the shared state.

    • HTTP 핸들러와 공유 상태: HTTP 핸들러가 매우 적은 양의 공유 상태에만 접근해야 하는 경우가 많음을 언급함.
  • Nothing against Mat Ryer, as his pattern is the best I've found, but I still feel like there's some better solution out there.

    • Mat Ryer의 패턴에 대한 존중: Mat Ryer의 패턴이 지금까지 찾은 것 중 최고라고 하면서도, 여전히 더 나은 해결책이 있을 것 같다는 느낌을 표현함.
  • one of my biggest pet peeves is when people take a Config object, which represents the configuration of an entire system, and pass it around mutably.

    • Config 객체 사용에 대한 불만: 전체 시스템의 설정을 나타내는 Config 객체를 변경 가능하게 전달하는 것에 대한 큰 불만을 표현함.
  • When you do that, you're coupling everything together through the config object.

    • Config 객체를 통한 결합 문제: Config 객체를 통해 모든 것을 결합시키는 문제점을 지적함.
  • I've worked on systems where you had to configure the parts in a specific order in order for things to work, because someone decided to write back to the config object when it was passed to them.

    • Config 객체의 순서 의존성 문제: Config 객체를 전달받은 사람이 그것에 다시 쓰기를 결정함으로써, 부품을 특정 순서로 구성해야만 시스템이 작동하는 경우에 대해 경험을 공유함.
  • Or another case was where I've seen it such that you couldn't disable a portion of the system because it wrote data into the config object that was read by some other subsystem later.

    • Config 객체와 시스템 부분의 비활성화 문제: Config 객체에 데이터를 쓰고, 그것이 나중에 다른 하위 시스템에 의해 읽혀져서 시스템의 일부를 비활성화할 수 없는 경우를 목격함.
  • The pattern of "your configuration is one big value, which is mutable" is one of the more annoying patterns that I've seen before, both in Go and in other languages.

    • 변경 가능한 단일 대형 설정 패턴에 대한 비판: Go와 다른 언어 모두에서 본 "설정이 하나의 크고 변경 가능한 값"이라는 패턴에 대해 불편함을 표현함.
  • I agree with a lot of this, I'll add my own opinions:

    • 의견 동의 및 추가: 많은 부분에 동의하며 자신의 의견을 추가함.
  • I would pass a waitgroup with the app context to service structs.

    • Waitgroup과 앱 컨텍스트 전달 제안: 서비스 구조체에 앱 컨텍스트와 함께 waitgroup을 전달하는 것을 제안함.
  • This way the interrupt can trigger the app shutdown via the context and the main goroutine can wait on the waitgroup before actually killing the app.

    • 앱 종료를 위한 인터럽트와 waitgroup 활용: 인터럽트가 컨텍스트를 통해 앱 종료를 트리거할 수 있고, 메인 고루틴이 앱을 실제로 종료하기 전에 waitgroup에서 대기할 수 있음을 설명함.
  • If writing a CLI program, then testing stdout, stdin, stderr, args, env, etc. is useful.

    • CLI 프로그램 테스트의 유용성: CLI 프로그램을 작성할 때 stdout, stdin, stderr, args, env 등을 테스트하는 것이 유용함을 언급함.
  • But for an http server, this is less true.

    • HTTP 서버에 대한 다른 접근: HTTP 서버의 경우 위의 테스트가 덜 유용함을 지적함.
  • I would pass structured config to the run function to let those tests be more focused.

    • 구조화된 설정 전달을 통한 테스트 집중: 더 집중된 테스트를 위해 구조화된 설정을 run 함수에 전달할 것을 제안함.
  • I disagree with parsing templates using sync.Once in a handler because I don't think handlers should do template parsing at all.

    • 핸들러에서의 템플릿 파싱에 대한 반대: 핸들러가 템플릿 파싱을 전혀 하지 않아야 한다고 생각하기 때문에 sync.Once를 사용한 템플릿 파싱에 동의하지 않음.
  • I would do this when the app starts: if the template cannot be parsed, the app should not become ready to receive any requests and should rather exit with a non-zero exit code.

    • 앱 시작 시 템플릿 파싱 제안: 앱이 시작될 때 템플릿 파싱을 수행하고, 파싱할 수 없다면 앱이 요청을 받을 준비가 되지 않아야 하며, 0이 아닌 종료 코드로 종료해야 함을 제안함.
  • I found fx to be a super simple yet versatile tool to design my application around.

    • fx 도구의 간단함과 다재다능함: fx를 매우 간단하면서도 다재다능한 도구로 찾아 애플리케이션 설계에 활용함.
  • All the advice in the article is still helpful, but it takes the "how do I make sure X is initialized when Y needs it" part completely out of the equation and reduces it from an N*M problem to an N problem.

    • 기사의 조언과 fx의 이점: 기사의 모든 조언이 여전히 도움이 되지만, fx는 "Y가 필요할 때 X가 초기화되었는지 어떻게 확실히 할 것인가"라는 문제를 완전히 제거하고 N*M 문제를 N 문제로 줄임.
  • I've used quite a few dependency injection libraries in various languages over the years (and implemented a couple myself) and the simplicity and versatility of fx makes it my favorite so far.

    • fx의 선호도: 여러 언어에서 다양한 의존성 주입 라이브러리를 사용해왔고 몇 가지를 직접 구현하기도 했지만, fx의 단순성과 다재다능함이 지금까지 가장 좋음.
  • I've recently been playing with ogen:

    • ogen 사용 경험: 최근에 ogen을 사용해봄.
  • Write openapi definition, it'll do routing, definition of structs, validation of JSON schemas, etc.

    • openapi 정의와 ogen의 기능: openapi 정의를 작성하면 ogen이 라우팅, 구조체 정의, JSON 스키마 유효성 검사 등을 수행함.
  • All I need to do is implement the service.

    • 서비스 구현의 단순화: 서비스를 구현하는 것만 필요함을 언급함.
  • Validating an integer range for a querystring parameter is just too boring. And too easy to mistype when writing it manually.

    • 쿼리스트링 파라미터의 정수 범위 유효성 검사의 단점: 쿼리스트링 파라미터에 대한 정수 범위 유효성 검사가 지루하고, 수동으로 작성할 때 오타가 나기 쉬움을 지적함.
  • Anyways, so far only been playing, so haven't found the bad parts yet.

    • ogen에 대한 초기 평가: 아직까지는 ogen을 실험적으로 사용하고 있으며, 나쁜 점을 발견하지 못함.
  • Great article with lots of interesting ideas. Can't believe I didn't know about signal.NotifyContext. Finally I'll be able to actually rememeber how to respond to signals instead of copy-pasting that between projects.

    • 기사와 signal.NotifyContext에 대한 긍정적 평가: 많은 흥미로운 아이디어가 담긴 훌륭한 기사라고 평가하며, signal.NotifyContext에 대해 알지 못했던 것에 놀라움을 표현함. 프로젝트 간에 복사-붙여넣기를 하지 않고 신호에 어떻게 반응해야 하는지 기억할 수 있게 됨.
  • I like a lot of what they've done here. My testing looks a bit different however.

    • 기사의 접근 방식에 대한 호감과 테스트 방식의 차이: 기사에서 한 많은 것들을 좋아하지만, 자신의 테스트 방식은 조금 다름을 언급함.
  • srv, err := newTestServer()

    • 테스트 서버 생성 코드 예시: 새로운 테스트 서버를 생성하는 코드 예시를 제시함.
  • require.NoError(t, err)

    • 에러 검사 코드 예시: 에러가 없는지 검사하는 코드 예시를 제시함.
  • defer srv.Close()

    • 서버 종료 코드 예시: 테스트가 끝난 후 서버를 닫는 코드 예시를 제시함.
  • resp, err := http.Post(fmt.Sprintf("http://localhost:%d/signup/json";, srv.Port()), "application/json", strings.NewReader({ "email": "[email protected]", "password": "p@55Word", "password_copy": "p@55Word" }))

    • HTTP POST 요청 코드 예시: HTTP POST 요청을 보내는 코드 예시를 제시함.
  • In my newTestServer, I spin up a server with fakes for my dependencies.

    • 의존성을 위한 가짜 서버 생성: 의존성을 위한 가짜 서버를 생성하는 방식을 사용함.
  • If I want to test a dependency error, I replace that property with a fake that will return an error.

    • 의존성 에러 테스트 방법: 의존성 에러를 테스트하고 싶을 때, 에러를 반환할 가짜로 해당 속성을 교체함.
  • I can validate my error paths. I can validate my log entries. I can validate my metric emission. I can validate timeouts and graceful shutdowns.

    • 다양한 검증 가능성: 에러 경로, 로그 항목, 메트릭 발생, 타임아웃, 그리고 우아한 종료 등을 검증할 수 있음.
  • After the server starts, I inspect to determine which port it is running on (default is :0 so I have to wait to see what it got bound to).

    • 서버 시작 후 포트 검사: 서버가 시작된 후 어떤 포트에서 실행되고 있는지 검사함 (기본값은 :0이므로 어떤 포트에 바인딩되었는지 확인하기 위해 대기해야 함).
  • My "unit" tests can test at the handler level or the http level, making sure that I can fully test the code as the users of my system will see it, exercising all middleware or none.

    • 단위 테스트의 범위: "단위" 테스트는 핸들러 수준이나 HTTP 수준에서 수행할 수 있으며, 시스템 사용자가 보게 될 코드를 완전히 테스트할 수 있도록 모든 미들웨어를 사용하거나 사용하지 않음.
  • I can spin up N instances and run my tests in parallel.

    • 병렬 테스트 실행: N개의 인스턴스를 생성하고 테스트를 병렬로 실행할 수 있음.
  • I don't write go, but I like these patterns. Feels fairly universal for testable code.

    • Go 작성 경험 부재와 패턴 선호: Go를 작성하지 않지만, 이러한 패턴을 좋아하며, 테스트 가능한