diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt b/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt
index 7c8a24e..6423bda 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/configs/SecurityConfig.kt
@@ -67,6 +67,7 @@ class SecurityConfig(
             .antMatchers("/member/check/email").permitAll()
             .antMatchers("/member/check/nickname").permitAll()
             .antMatchers("/member/signup").permitAll()
+            .antMatchers("/member/signup/v2").permitAll()
             .antMatchers("/member/login").permitAll()
             .antMatchers("/creator-admin/member/login").permitAll()
             .antMatchers("/member/forgot-password").permitAll()
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt
index 61000c0..886c48a 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberController.kt
@@ -9,6 +9,7 @@ import kr.co.vividnext.sodalive.member.following.CreatorFollowRequest
 import kr.co.vividnext.sodalive.member.login.LoginRequest
 import kr.co.vividnext.sodalive.member.login.LoginResponse
 import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
+import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2
 import org.springframework.data.domain.Pageable
 import org.springframework.security.core.annotation.AuthenticationPrincipal
 import org.springframework.security.core.userdetails.User
@@ -42,6 +43,21 @@ class MemberController(
         @AuthenticationPrincipal user: User
     ) = ApiResponse.ok(service.updateNickname(profileUpdateRequest, user))
 
+    @PostMapping("/signup/v2")
+    fun signupV2(@RequestBody request: SignUpRequestV2): ApiResponse<LoginResponse> {
+        val response = service.signUpV2(request)
+
+        if (!response.marketingPid.isNullOrBlank()) {
+            trackingService.saveTrackingHistory(
+                pid = response.marketingPid,
+                type = AdTrackingHistoryType.SIGNUP,
+                memberId = response.memberId
+            )
+        }
+
+        return ApiResponse.ok(message = "회원가입을 축하드립니다.", data = response.loginResponse)
+    }
+
     @PostMapping("/signup")
     fun signUp(
         @RequestPart("profileImage", required = false) profileImage: MultipartFile? = null,
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt
index 9103990..e67a033 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberRepository.kt
@@ -59,6 +59,10 @@ interface MemberQueryRepository {
     fun getAuditionNoticeRecipientPushTokens(isAuth: Boolean): Map<String, List<List<String>>>
 
     fun getMemberProfile(memberId: Long, myMemberId: Long): GetMemberProfileResponse
+
+    fun existsByEmail(email: String): Boolean
+    fun existsByNickname(nickname: String): Boolean
+    fun findNicknamesWithPrefix(prefix: String): List<String>
 }
 
 @Repository
@@ -479,4 +483,34 @@ class MemberQueryRepositoryImpl(
             .where(member.id.eq(memberId))
             .fetchFirst()
     }
+
+    override fun existsByEmail(email: String): Boolean {
+        return queryFactory
+            .selectOne()
+            .from(member)
+            .where(member.email.eq(email))
+            .fetchFirst() != null
+    }
+
+    override fun existsByNickname(nickname: String): Boolean {
+        return queryFactory
+            .selectOne()
+            .from(member)
+            .where(
+                member.nickname.eq(nickname),
+                member.isActive.isTrue
+            )
+            .fetchFirst() != null
+    }
+
+    override fun findNicknamesWithPrefix(prefix: String): List<String> {
+        return queryFactory
+            .select(member.nickname)
+            .from(member)
+            .where(
+                member.nickname.startsWith(prefix),
+                member.isActive.isTrue
+            )
+            .fetch()
+    }
 }
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt
index 24628fd..2c54085 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/MemberService.kt
@@ -25,9 +25,11 @@ import kr.co.vividnext.sodalive.member.login.LoginResponse
 import kr.co.vividnext.sodalive.member.myPage.MyPageResponse
 import kr.co.vividnext.sodalive.member.nickname.NicknameChangeLog
 import kr.co.vividnext.sodalive.member.nickname.NicknameChangeLogRepository
+import kr.co.vividnext.sodalive.member.nickname.NicknameGenerateService
 import kr.co.vividnext.sodalive.member.notification.MemberNotificationService
 import kr.co.vividnext.sodalive.member.notification.UpdateNotificationSettingRequest
 import kr.co.vividnext.sodalive.member.signUp.SignUpRequest
+import kr.co.vividnext.sodalive.member.signUp.SignUpRequestV2
 import kr.co.vividnext.sodalive.member.signUp.SignUpResponse
 import kr.co.vividnext.sodalive.member.signUp.SignUpValidator
 import kr.co.vividnext.sodalive.member.stipulation.Stipulation
@@ -77,6 +79,7 @@ class MemberService(
     private val orderService: OrderService,
     private val emailService: SendEmailService,
     private val canPaymentService: CanPaymentService,
+    private val nicknameGenerateService: NicknameGenerateService,
     private val memberNotificationService: MemberNotificationService,
 
     private val s3Uploader: S3Uploader,
@@ -96,6 +99,46 @@ class MemberService(
 
     private val tokenLocks: MutableMap<Long, ReentrantReadWriteLock> = mutableMapOf()
 
+    @Transactional
+    fun signUpV2(request: SignUpRequestV2): SignUpResponse {
+        val stipulationTermsOfService = stipulationRepository.findByIdOrNull(StipulationIds.TERMS_OF_SERVICE_ID)
+            ?: throw SodaException("잘못된 요청입니다\n앱 종료 후 다시 시도해 주세요.")
+
+        val stipulationPrivacyPolicy = stipulationRepository.findByIdOrNull(StipulationIds.PRIVACY_POLICY_ID)
+            ?: throw SodaException("잘못된 요청입니다\n앱 종료 후 다시 시도해 주세요.")
+
+        if (!request.isAgreePrivacyPolicy || !request.isAgreeTermsOfService) {
+            throw SodaException("약관에 동의하셔야 회원가입이 가능합니다.")
+        }
+
+        duplicateCheckEmail(request.email)
+        validatePassword(request.password)
+
+        val nickname = nicknameGenerateService.generateUniqueNickname()
+        val member = Member(
+            email = request.email,
+            password = passwordEncoder.encode(request.password),
+            nickname = nickname,
+            profileImage = "profile/default-profile.png",
+            gender = Gender.NONE,
+            container = request.container
+        )
+
+        if (!request.marketingPid.isNullOrBlank()) {
+            member.activePid = request.marketingPid
+            member.partnerExpirationDatetime = LocalDateTime.now().plusYears(1)
+        }
+
+        repository.save(member)
+        agreeTermsOfServiceAndPrivacyPolicy(member, stipulationTermsOfService, stipulationPrivacyPolicy)
+
+        return SignUpResponse(
+            memberId = member.id!!,
+            marketingPid = request.marketingPid,
+            loginResponse = login(request.email, request.password)
+        )
+    }
+
     @Transactional
     fun signUp(
         profileImage: MultipartFile?,
@@ -334,7 +377,11 @@ class MemberService(
 
     fun duplicateCheckEmail(email: String): ApiResponse<Any> {
         validateEmail(email)
-        repository.findByEmail(email)?.let { throw SodaException("이미 사용중인 이메일 입니다.", "email") }
+
+        if (repository.existsByEmail(email)) {
+            throw SodaException("이미 사용중인 이메일 입니다.", "email")
+        }
+
         return ApiResponse.ok(message = "사용 가능한 이메일 입니다.")
     }
 
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/nickname/NicknameGenerateService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/nickname/NicknameGenerateService.kt
new file mode 100644
index 0000000..ab4c230
--- /dev/null
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/nickname/NicknameGenerateService.kt
@@ -0,0 +1,65 @@
+package kr.co.vividnext.sodalive.member.nickname
+
+import kr.co.vividnext.sodalive.common.SodaException
+import kr.co.vividnext.sodalive.member.MemberRepository
+import org.springframework.stereotype.Service
+import kotlin.random.Random
+
+@Service
+class NicknameGenerateService(private val repository: MemberRepository) {
+    private val adjectives = listOf(
+        "감성적인", "몽환적인", "깊이있는", "따뜻한", "서정적인", "소울풀한", "잔잔한",
+        "선율의", "리드미컬한", "감미로운", "은은한", "잔향의", "울려퍼지는", "하모닉한",
+        "레트로한", "복고풍의", "아날로그적인", "빈티지한", "90년대감성", "옛날느낌의",
+        "시간을넘는", "과거에서온", "시간여행자의", "미래를보는", "초월적인", "운명적인",
+        "신비로운", "마법같은", "전설속의", "별빛의", "달빛의"
+    )
+
+    private val nouns = listOf(
+        "소리", "울림", "속삭임", "청취자", "메아리", "목소리", "공명", "음색", "감성",
+        "멜로디", "선율", "리듬", "하모니", "사운드트랙", "나이트클럽", "라디오스타",
+        "레코드판", "카세트테이프", "LP음악", "복고댄스", "클래식기타", "빈티지마이크",
+        "시간여행", "타임머신", "평행세계", "운명의선택", "마법진", "신비한음색",
+        "달빛의향연", "별빛의꿈", "마법사의속삭임", "초월적인선율"
+    )
+
+    private val numberRange = 1000..9999
+
+    private fun generateRandomNickname(): String {
+        val formatType = Random.nextInt(5)
+        return when (formatType) {
+            0 -> "${adjectives.random()}${nouns.random()}${numberRange.random()}"
+            1 -> "${nouns.random()}의${nouns.random()}${numberRange.random()}"
+            2 -> "${adjectives.random()}${nouns.random()}"
+            3 -> "${nouns.random()}의${nouns.random()}"
+            else -> "${adjectives.random()}${nouns.random()}의${nouns.random()}${numberRange.random()}"
+        }
+    }
+
+    private fun generateNonConflictingNickname(usedNicknames: Set<String>): String {
+        val usedNicknameSet = HashSet(usedNicknames) // 해시셋으로 변환 (O(1) 조회 가능)
+        val availableNumbers = (1000..9999).shuffled()
+
+        for (num in availableNumbers) { // 숫자를 먼저 결정 (무작위)
+            for (adj in adjectives.shuffled()) { // 형용사 순서 랜덤화
+                for (noun in nouns.shuffled()) { // 명사 순서 랜덤화
+                    val candidate = "$adj$noun$num"
+                    if (!usedNicknameSet.contains(candidate)) {
+                        return candidate
+                    }
+                }
+            }
+        }
+        throw SodaException("회원가입을 하지 못했습니다.\n다시 시도해 주세요.")
+    }
+
+    fun generateUniqueNickname(): String {
+        repeat(5) {
+            val candidates = (1..10).map { generateRandomNickname() }
+            val available = candidates.firstOrNull { !repository.existsByNickname(it) }
+            if (available != null) return available
+        }
+
+        return generateNonConflictingNickname(repository.findNicknamesWithPrefix("").toSet())
+    }
+}
diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/member/signUp/SignUpRequest.kt b/src/main/kotlin/kr/co/vividnext/sodalive/member/signUp/SignUpRequest.kt
index 42c7350..de4a6fa 100644
--- a/src/main/kotlin/kr/co/vividnext/sodalive/member/signUp/SignUpRequest.kt
+++ b/src/main/kotlin/kr/co/vividnext/sodalive/member/signUp/SignUpRequest.kt
@@ -12,3 +12,12 @@ data class SignUpRequest(
     val isAgreePrivacyPolicy: Boolean,
     val container: String = "api"
 )
+
+data class SignUpRequestV2(
+    val email: String,
+    val password: String,
+    val marketingPid: String? = null,
+    val isAgreeTermsOfService: Boolean,
+    val isAgreePrivacyPolicy: Boolean,
+    val container: String = "api"
+)