효율적인 조직 관리: Polar.sh와 BetterAuth의 완벽한 통합 방법
2025-04-16 10:16:42Polar.sh와 BetterAuth의 통합 - 배경
Polar.sh와 BetterAuth을 조직 기반의 구독 관리에 통합 시키는 것은 많은 SaaS 개발자들에게 매우 유용한 작업입니다. Polar.sh는 고객 이메일이 고유해야 하며, 사용자가 여러 조직을 관리 할 경우 각 조직을 고객으로 등록하는데 있어서 이메일 주소를 다르게 설정할 수 없습니다. 이는 앱 내 여러 조직을 관리하는 사용자가 동일한 이메일 주소를 사용해야 한다는 것을 의미합니다. BetterAuth의 경우, Polar에서 이 문제에 대한 해결책이 아직 없었습니다. 이번 블로그에서는 이를 해결하기 위한 최선의 방법을 다루고자 합니다.
문제점: 이메일 주소 고유성
Polar.sh는 고객 이메일이 고유해야 하며, 동일한 이메일로 여러 조직을 구독 등록하는 것은 불가능합니다. 사용자 입장에서는 각 조직마다 다른 이메일을 관리해야 하는 불편함이 있고, 이는 SaaS 환경에서의 조직 관리에 많은 제약을 줍니다. 특히, BetterAuth와의 통합 과정에서 이러한 문제가 발생하여 개발자들은 새로운 해결책을 모색해야 합니다.
해결책: 사용자 지정 구독 관리 플로우
SaaS Idea Validation 앱인 Venturate를 개발하면서 발견한 방법 중 하나는 사용자 지정 구독 관리 플로우를 구현하는 것입니다. 이를 위해 BetterAuth 및 Polar.sh와의 통합을 철저히 계획하고 각각의 역할을 명확히 하는 것이 필요합니다.
필수 준비 사항
- BetterAuth 플러그인을 설치합니다:
yarn add @polar-sh/better-auth - Polar SDK를 설치합니다:
yarn add @polar-sh/sdk - 앱 코드 내에서 BetterAuth와 Polar를 설정합니다.
BetterAuth + Polar + Orgs 설정 방법
import { betterAuth } from "better-auth";
import { prismaAdapter } from "better-auth/adapters/prisma";
import { organization } from "better-auth/plugins";
import { nextCookies } from "better-auth/next-js";
import { prisma } from "@/prisma/prisma";
import { Polar } from "@polar-sh/sdk";
import { polar } from "@polar-sh/better-auth";
export const polarClient = new Polar({
accessToken: process.env.POLAR_ACCESS_TOKEN!,
server: "sandbox",
});
export const auth = betterAuth({
database: prismaAdapter(prisma, {
provider: "postgresql",
}),
plugins: [
polar({
client: polarClient,
createCustomerOnSignUp: true,
enableCustomerPortal: false,
checkout: {
enabled: false,
products: [], // 비워두지만 반드시 설정
},
webhooks: {
secret: process.env.POLAR_WEBHOOK_SECRET!,
onPayload: async ({ data, type }) => {
if (
["subscription.created", "subscription.active", "subscription.canceled",
"subscription.revoked", "subscription.uncanceled", "subscription.updated"].includes(type)
) {
const org = await prisma.organization.findUnique({
where: { id: data.metadata.org as string },
});
if (!org) throw new Error("Error, something happened");
await prisma.subscription.upsert({
create: {
status: data.status,
organisation_id: org?.id,
subscription_id: data.id,
product_id: data.productId,
},
update: {
status: data.status,
organisation_id: org?.id,
subscription_id: data.id,
product_id: data.productId,
},
where: {
organisation_id: org.id,
},
});
}
},
},
}),
organization(),
nextCookies(),
],
});
웹훅 및 고객 포털 설정
Polar에 웹훅을 활성화하고, 각 조직을 위한 맞춤형 고객 포털을 통해 구독을 관리할 수 있습니다. 관리자뿐 아니라 조직의 구성원들이 구독을 관리할 수 있는 환경을 구축해야 합니다.
세션 기반 사용자 및 조직 정보 가져오기
아래의 코드를 통해 세션 기반으로 사용자와 현재 조직의 세부 정보를 가져올 수 있습니다.
export async function getSession() {
const headersList = await headers();
const sessionData = await auth.api.getSession({ headers: headersList });
if (!sessionData?.session) {
redirect("/auth/sign-in");
}
const { session, user } = sessionData;
const [member, activeOrg] = await Promise.all([
auth.api.getActiveMember({ headers: headersList }),
session.activeOrganizationId
? prisma.organization.findFirst({
where: {
id: session.activeOrganizationId,
},
})
: Promise.resolve(null),
]);
if (!session.activeOrganizationId || !activeOrg || !member) {
redirect("/switch-org");
}
return {
userId: user.id,
org: session.activeOrganizationId!,
email: user.email,
name: user.name,
image: user.image,
role: member.role,
orgName: activeOrg.name,
orgDomain: activeOrg.domain,
};
}
한걸음 더 나아가기: 사용자 지정 고객 포털 URL 생성
이제 조직 구성원들이 편리하게 구독 설정을 관리할 수 있도록 사용자 지정 고객 포털 URL을 생성하는 방법을 배워보겠습니다.
export async function generateCustomerURL() {
const { org } = await getSession();
const subscription = await prisma.subscription.findFirst({
where: {
organisation_id: org,
},
});
if (!subscription) return null;
const polarSubscription = await polarClient.subscriptions.get({
id: subscription.subscription_id!,
});
if (!polarSubscription) return null;
// 더 많은 설정 필요시 이곳에 추가
}
결론
Polar.sh와 BetterAuth의 강력한 통합은 조직 기반 구독 관리에 필수적입니다. 사용자 지정 관리 기능을 통해 각 조직의 요구에 맞는 구성을 적용하고 사용자 경험을 향상시키세요. 이 블로그가 더 나은 SaaS 애플리케이션 구축에 도움이 되길 바랍니다.
더 읽어볼 만한 글
더 많은 정보와 지원을 받으려면, 관련 링크를 꼭 방문해보세요.