메뉴
HN
Hacker News • 29일 전

스타트업에서 AWS Cognito를 써봤지만 다시는 안 쓸 것

IMP
6/10
핵심 요약

한 스타트업 개발자가 AWS Cognito로 인증 시스템을 구축하면서 겪은 문제를 상세히 공유했습니다. 문서가 여러 독자층을 동시에 겨냥해 혼란스럽고, Amplify v6로 업데이트하며 인증 로직을 통째로 재작성해야 했으며, 클라우드 기반이라 로컬 개발·테스트가 어렵다는 것이 핵심 불만입니다. 인증 서비스 선택을 고민하는 개발자들에게 실전 교훈이 되는 글입니다.

번역된 본문

스타트업 인증 시스템을 세팅한 지 사흘째 되던 날, 뭔가 잘못됐다는 걸 깨달았다. '세미콜론 하나 빠뜨린' 수준의 잘못이 아니었다. '문서의 모든 단계를 그대로 따랐는데도 비밀번호 재설정 플로우가 여전히 엉뚱한 곳으로 리다이렉트되는' 수준의 잘못이었다. 문서를 열두 개 탭으로 띄워놓고, 코드 샘플을 복사해 붙여넣고, 이 악몽을 정확히 겪어본 것 같은 사람의 튜토리얼까지 봤다.

그런데 이게 중요한 점이다. 나는 인증 구현 경험이 있다. Auth0와 씨름해봤고, Firebase Auth를 길들여봤고, 자랑스럽지는 않지만 작동하는 커스텀 JWT 시스템도 직접 만들어봤다. 그래서 스타트업에 인증이 필요하고 팀이 '이미 AWS 생태계에 있고 월간 활성 사용자 5만 명까지 무료'라는 이유로 Cognito를 선호했을 때, 얼마나 나쁠 수 있겠냐고 생각했다.

모든 걸 후회한다.

문서가 다섯 명의 다른 독자를 동시에 위해 쓰였다

Cognito 문서를 읽는 건, 매뉴얼 세 권을 블렌더에 갈고 거기에 오래된 Stack Overflow 답변을 양념으로 뿌린 느낌이다. AWS는 너무 많은 독자층을 동시에 만족시키려 한다. 기저 기술의 인증 프로토콜을 이해하고 싶은 엔터프라이즈 아키텍트, 로그인 폼만 있으면 되는 프론트엔드 개발자, 네이티브 SDK가 필요한 모바일 개발자. 문서는 모두에게 모든 것이 되려다 정작 아무에게도 쓸모없어진다.

'Cognito 커스텀 속성 검증'을 검색하면, 내가 존재하는지도 몰랐던 다른 네 개 문서를 이미 읽었다고 가정하며 디렉터리 스키마 이야기로 시작하는 페이지가 나온다. 명확한 순차적 경로가 없다. 그저 하이퍼링크와 기도의 그물망일 뿐이다.

그리고 코드 예제. 아, 그 코드 예제들. 절반은 구버전 JavaScript SDK용이다. 일부는 Amplify v1 API를 참조하고, 나머지는 raw AWS SDK를 쓴다. 문서는 어떤 버전을 다루는지 명확히 알려주지 않아서, import 문을 보고 형사놀음을 해야 한다.

Amplify v6가 나를 배신한 날

버전 이야기가 나왔으니, JavaScript 라이브러리 상황을 말해주겠다. 이건 진짜 당황스러웠다. 개발을 시작할 때 Amplify는 버전 5였다. 인증 플로우를 작성하고, 테스트하고, 커밋하고, 다른 기능으로 넘어갔다. 몇 주 후 버그를 고치러 돌아왔더니 콘솔에 지원 중단(deprecation) 경고가 떠 있었다. 문제없지, 최신 버전으로 업데이트하면 되겠거니 했다.

여러분. Amplify v6는 메서드 시그니처 몇 개를 바꾼 수준이 아니었다. Cognito와 상호작용하는 방식을 근본적으로 재설계했다. 내가 UI 플로우 전체를 구축했던 함수들이 사라졌다. 대체됐다. 증발했다. 마이그레이션 가이드는 기술적으로 존재는 했지만, 랜드마크 절반이 빠진 보물지도 같았다.

결국 코드를 다시 작성했다. 리팩토링이 아니라 재작성이다. 프로덕션에서 완벽하게 작동하던 인증 로직이 라이브러리 유지보수자들이 구버전 API를 더 이상 정석으로 보지 않기로 했다는 이유로 재구축되어야 했다. 그건 업그레이드가 아니다. 인질극이다.

로컬 개발은 또 다른 종류의 고통

Cognito에 관한 재미있는 사실 하나: 클라우드 기반이다. 뭐, 놀랍지 않은가. 하지만 실질적으로 의미하는 바는, 로컬 인스턴스를 띄워서 오프라인으로 인증 플로우를 테스트할 수 없다는 것이다. 항상 실제 AWS 엔드포인트를 호출해야 한다.

serverless-offline 플러그인이나 로컬 Cognito 에뮬레이터 같은 도구들이 이 간극을 메우려 하지만, 유지보수 수준과 충실도가 제각각인 커뮤니티 프로젝트들이다. AWS의 공식 입장은 기본적으로 '클라우드 대상으로 테스트하라'인데, 비행기 안에 있거나, 인터넷이 불안정하거나, 네트워크 왕복 대기 없이 빠른 반복 개발 주기를 원한다면 좋은 조언이 못 된다.

나는 실제 환경과 완전히 일치하지 않는 로컬 목업을 세팅하느라 민망할 정도로 많은 시간을 낭비했다. 그 덕분에 버그는 로컬에서는 드러나지 않고 스테이징에서 터졌다. 로컬 개발의 핵심 목적은 문제를 조기에 잡는 건데, Cognito는 그걸 적극적으로 방해한다.

커스터마이징을 원한다면… (이하 생략)

원문 보기
원문 보기 (영어)
I was three days into setting up authentication for our startup when I realized something was wrong. Not “I missed a semicolon” wrong. More like “I followed every step in the documentation and the password reset flow still redirects to the wrong place” wrong. I had the docs open in twelve tabs. I had copy-pasted the code samples. I had even watched a tutorial from someone who sounded like they’d been through this exact nightmare before. Here’s the thing. I’ve implemented authentication before. I’ve wrestled with Auth0, tamed Firebase Auth, and even rawdogged a custom JWT system that I’m not proud of but it worked. So when our startup needed auth and the team leaned toward Cognito because “it’s already in the AWS ecosystem and the first 50,000 monthly active users are free,” I thought, how bad could it be? I regret everything. The Documentation Was Written for Five Different People at Once Reading Cognito docs feels like someone took three separate manuals, threw them in a blender, and then sprinkled in some outdated Stack Overflow answers for flavor. AWS is trying to serve too many audiences simultaneously. You’ve got the enterprise architect who wants to understand the underlying identity protocols. You’ve got the frontend developer who just wants a login form. You’ve got the mobile developer who needs native SDKs. And the docs try to be everything to everyone, which means they end up being useful to exactly nobody. I’d search for “Cognito custom attribute validation” and land on a page that starts with a paragraph about directory schemas that assumes I’ve already read four other pages I didn’t know existed. There’s no clear linear path. It’s just a web of hyperlinks and prayers. And the code examples. Oh, the code examples. Half of them are for the old JavaScript SDK. Some reference the Amplify v1 API. Others use the raw AWS SDK. The docs don’t always clearly tell you which version they’re talking about, so you’re left playing detective with import statements. The Day Amplify v6 Betrayed Me Speaking of versions. Let me tell you about the JavaScript library situation, because this one genuinely caught me off guard. When we started building, Amplify was on version 5. I wrote our auth flow, tested it, committed it, moved on to other features. A few weeks later, I came back to fix a bug and noticed some deprecation warnings in the console. No problem, I thought. I’ll just update to the latest version. Friends. Amplify v6 didn’t just change a few method signatures. It fundamentally rearchitected how you interact with Cognito. Functions I had built entire UI flows around were gone. Replaced. Vanished. The migration guide existed, technically, but it felt more like a treasure map with half the landmarks missing. I rewrote the code. Not refactored. Rewrote. Authentication logic that was working perfectly fine in production had to be rebuilt because the library maintainers decided the old API was no longer the blessed path. That’s not an upgrade. That’s a hostage situation. Local Development is a Special Kind of Pain Here’s a fun fact about Cognito: it’s cloud-based. I know, shocking. But what that means practically is that you can’t just spin up a local instance and test your auth flows offline. You’re always hitting actual AWS endpoints. Now, there are tools like the serverless-offline plugin and local Cognito emulators that try to bridge this gap. But they’re community projects with varying levels of maintenance and fidelity. The official story from AWS is basically “test against the cloud,” which is great advice unless you’re on a plane, or your internet is spotty, or you just want fast iteration cycles without waiting for network round trips. I spent an embarrassing amount of time setting up a local mock that didn’t quite match the real thing, which meant bugs would slip through locally and show up in staging. The whole point of local development is catching issues early, and Cognito actively works against that. You Want Customization? Best I Can Do is a Logo This one stung. The hosted UI that Cognito provides is functional. It’s there. It works, mostly. But if you want it to look like your brand and not like an AWS service wearing a costume, you’re going to have a bad time. You can change the logo. You can tweak some CSS via the console. But the layout, the structure, the overall feel? That’s AWS’s house, and you’re just renting a room. If you need anything beyond basic customization, the advice from the community is usually “build your own UI using the SDK.” Which, fine, I get it. But at that point, what exactly is the hosted UI saving me? The Email-Only Configuration That Broke My Spirit Let me tell you about the moment I almost threw my laptop out a window. Our app only needed email authentication. No usernames. Users sign up with an email, verify it, set a password, done. Simple concept, right? So I went into the Cognito user pool settings and configured it to use email addresses as the sign-in identifier. I set up the attribute mappings. I created the sign-up flow. Everything seemed fine until I realized that Cognito treats “email” differently depending on whether it’s a core attribute, an alias, or a custom attribute, and the configuration options are spread across multiple screens in the console with interdependencies that are never fully explained. I made a mistake in the initial setup. A small one. I had configured something as a custom attribute that should have been a standard one. No problem, I thought. I’ll just change it. You cannot change it. Once a user pool attribute is created as custom, it’s custom forever. And if your authentication scheme depends on the relationship between certain attributes, and you get that relationship wrong, your options are roughly: delete the entire user pool and start over, or build an elaborate migration process that moves users to a new pool with the correct configuration. For a production app with active users, “just delete it” is not really an option. So now you’re scripting user migrations, handling password resets in the new pool, and apologizing to your users for the inconvenience. All because a dropdown in a console was a little too ambiguous. What I Actually Learned I don’t want to just complain. That’s easy. But I do want to be honest about what this experience taught me, because I think there’s something useful here beyond “Cognito bad.” Authentication is not the place to cut corners. The “it’s already in the ecosystem” argument is seductive, but ecosystem proximity doesn’t matter if the tool makes you miserable every time you touch it. The free tier pricing is attractive until you calculate the engineering hours spent fighting the documentation and rewriting code for breaking API changes. Next time, I’m picking a tool based on developer experience first, not AWS service integration convenience. The time we lost debugging Cognito issues could have paid for several years of a paid auth provider. And we would have shipped faster, with less cold pizza consumed at midnight. If you’re reading this because you’re currently evaluating Cognito for your project, I’m not going to tell you what to do. But I will say this: build a small proof of concept first. Something nontrivial. Something with custom attributes and email verification and a password reset flow. See how it feels. Time yourself. Count the documentation tabs you have open by the end of it. If that number is over twenty, maybe reconsider. I’m still using Cognito on this project, by the way. We’re too far in to rip it out now. But every time I open the AWS console and see that user pool sitting there, I feel a small, quiet resentment. Like an old roommate who never does the dishes and keeps “borrowing” your stuff. You know the feeling. Need a Developer Who Gets It Done? If this post helped solve your problem, imagine what we could build together! I'm a full-stack developer with expertise in Python, Django, Typescript, and modern web technolo