카카오 로그인
Updated:
다음은 카카오 로그인을 위한 문서이다.
https://developers.kakao.com/docs/latest/ko/kakaologin/common
다음은 카카오 로그인 과정이다.
- 인가 코드 받기
- 서비스 서버가 카카오 인증 서버로 인가 코드 받기를 요청한다.
- 카카오 인증 서버가 사용자에서 인증을 요청한다.
- 사용자가 카카오 계정으로 로그인한다.
- 카카오 인증 서버가 사용자에게 동의 화면을 출력하여 인가를 위한 사용자 동의를 요청한다.
- 사용자가 필수 동의항목과, 이 외의 원하는 동의항목에 동의한 뒤 “동의하고 계속하기” 버튼을 누른다.
- 카카오 인증 서버는 서비스 서버의 Redirect URI로 인가 코드를 전달한다.
- 토큰 받기
- 서비스 서버가 Redirect URI로 전달받은 인가 코드로 토큰 받기를 요청한다.
- 카카오 인증 서버가 토큰을 발급해 서비스 서버에 전달한다.
- 사용자 로그인 처리
- 서비스 서버가 발급받은 엑세스 토큰으로 사용자 정보 가져오기를 요청해 사용자의 회원번호 및 정보를 조회하여 서비스 회원인지 확인한다.
- 서비스 회원 정보 확인 결과에 따라 서비스 로그인 또는 회원 가입한다.
- 이 외 서비스에서 필요한 로그인 절차를 수행한 후, 카카오 로그인한 사용자의 서비스 로그인 처리를 완료한다.
Kakao Developer Setting
개발하기 전, Kakao Develoer(https://developers.kakao.com/)에서 애플리케이션을 추가해줘야 한다.
이후 도메인을 추가하고 카카오 로그인을 활성화해준뒤, Redirect URI를 설정해준다..
동의 항목 설정
사용자 정보를 요청하기 위해 동의 항목을 설정해준다.
- 해당 프로젝트에서는 닉네임은 로그인 이후에 받을 예정이기 때문에 프로필 사진만 필수 동의 상태로 바꿔준다.
로그인 요청
카카오 로그인 Rest API 문서를 보면 다음과 같은 요청을 하면 인가 코드를 받을 수 있다고 한다.
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URI}
- REDIRECT_URI: Kakao Developer Setting에서 설정한 http://localhost:8080/auth/login/kakao
- REST_API_KEY: 앱 설정의 앱 키에서 확인 가능
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=${REST_API_KEY}&redirect_uri=http://localhost:8080/auth/login/kakao로 접속해보면 다음과 같은 화면을 확인할 수 있다.
KakaoLoginPageController
로그인 페이지를 반환해줄 kakaoLoginPageController.java를 작성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.controller;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
@RequestMapping("/login")
public class KakaoLoginPageController {
@Value("${kakao.auth.client}")
private String client_id;
@Value("${kakao.auth.redirect}")
private String redirect_uri;
@GetMapping("/page")
public String loginPage(Model model) {
String location = "https://kauth.kakao.com/oauth/authorize?response_type=code&client_id=" + client_id + "redirect_uri=" + redirect_uri;
model.addAttribute("location", location);
return "login";
}
}
Thymeleaf 의존성을 추가해준 뒤, resources/templates에 login.html을 작성한다. 이때 thymeleaf는 resouces/templates에 있는 html 파일을 사용하기 때문에 다른 디렉토리에 넣어두어서는 안된다.
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>KakaoLogin</title>
</head>
<body>
<div class="container" style="display: flex; justify-content: center; align-content: center; align-items: center; flex-direction: column; margin: 200px auto;">
<h1>카카오 로그인</h1>
<a th:href="${location}">
<img src="/assets/kakao_login_medium_narrow.png">
</a>
</div>
</body>
</html>
localhost:8080/login/page에 접속하면 다음과 같은 화면이 출력된다.
카카오 로그인을 클릭하면 다음과 같은 화면이 출력되고, 로그인을 하면 등록해둔 Redirect URI에 파라미터로 code와 함께 Redirect되는 것을 확인할 수 있다.
- http://localhost:8080/auth/login/kakao?code=TGBJ5W5an5fiZkpj37mtaNmD2rXZdK2-XTuWz4jfJNvF46TKQMSR5QAAAAQKFxDvAAABlf-6buBSGUcvaFb1Eg
Redirect URI와 같이 code 전달받기
이제 Redirect된 URI에 전달된 code를 가져와본다.
KakaoLoginController
먼저 KakaoLoginController를 대략 작성해본다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.controller;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("")
public class KakaoLoginController {
@GetMapping("/auth/login/kakao")
public ResponseEntity<?> KakaoLogin(@RequestParam("code") String code) {
return new ResponseEntity<>(HttpStatus.OK);
}
}
- 등록해둔 URI에 GetMapping을 해두면 파라미터 code와 함께 받을 수 있다.
code를 통해 토큰 발급 요청
카카오로부터 받은 code를 카카오에 토큰 발급 요청을 하면, 사용자 정보가 담겨있는 토큰을 받을 수 있다.
- https://kauth.kakao.com/oauth/token 으로 POST 요청을 보내면, 토큰을 받을 수 있다.
따라서 카카오로부터 받은 ResponseDTO를 생성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoTokenResponseDto {
// 역직렬화를 위해 JsonProperty를 이용
@JsonProperty("token_type") // 토큰 타입
public String tokenType;
@JsonProperty("access_token") // 사용자 엑세스 토큰 값
public String accessToken;
@JsonProperty("id_token") // ID 토큰 값
public String idToken;
@JsonProperty("expires_in") // 엑세스 토큰과 ID 토큰의 만료 시간(초)
public String expiresIn;
@JsonProperty("refresh_token") // 사용자 리프레시 토큰 값
public String refreshToken;
@JsonProperty("refresh_token_expires_in") // 리프레시 토큰 만료 시간(초)
public String refreshTokenExpiresIn;
@JsonProperty("scope") // 인증된 사용자의 정보 조회 권한 범위
public String scope;
}
KakaoService
Spring Reactive Web dependency를 추가해준다. 이후 KakaoService를 작성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.service;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto.KakaoTokenResponseDto;
import io.netty.handler.codec.http.HttpHeaderValues;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatusCode;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Slf4j
@RequiredArgsConstructor
@Service
public class KakaoService {
private String clientId;
private final String KAUTH_TOKEN_URL_HOST;
private final String KAUTH_USER_URL_HOST;
@Autowired
public KakaoService(@Value("${kakao.auth.client}") String clientId) {
this.clientId = clientId;
KAUTH_TOKEN_URL_HOST = "https://kauth.kakao.com";
KAUTH_USER_URL_HOST = "https://kapi.kakao.com";
}
public String getAccessTokenFromKakao(String code) {
KakaoTokenResponseDto kakaoTokenResponseDto = WebClient.create(KAUTH_TOKEN_URL_HOST).post()
.uri(uriBuilder -> uriBuilder
.scheme("https")
.path("/oauth/token")
.queryParam("grant_type", "authorization_code")
.queryParam("client_id", clientId)
.queryParam("code", code)
.build(true))
.header(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, clientResponse -> Mono.error(new RuntimeException("Invalid Parameter")))
.onStatus(HttpStatusCode::is5xxServerError, clientResponse -> Mono.error(new RuntimeException("Internal Server Error")))
.bodyToMono(KakaoTokenResponseDto.class)
.block();
log.info(" [Kakao Service] Access Token ------> {}", kakaoTokenResponseDto.getAccessToken());
log.info(" [Kakao Service] Refresh Token ------> {}", kakaoTokenResponseDto.getRefreshToken());
log.info(" [Kakao Service] Id Token ------> {}", kakaoTokenResponseDto.getIdToken());
log.info(" [Kakao Service] Scope ------> {}", kakaoTokenResponseDto.getScope());
return kakaoTokenResponseDto.getAccessToken();
}
}
- Webclient로 HTTP 요청을 구현했다. 각 서비스마다 Custom Exception이 있다면 onStatue 메서드에 지정하면 된다.
- HTTP 요청을 받아모녀 .retrieve() 메서드 부터, Request Body 내용이 미리 지정해둔 KakaoTokenResponseDto에 json이 직렬화되어 들어가게 된다.
https://kauth.kakao.com/oauth/token?grant_type=authorizarion_code&client_id=${client_id}&code={code}로 Post 요청을 보내면, 받은 Response의 Body에 아래 내용을 받을 수 있다.
KakaoLoginController
이제 구현한 service를 controller에서 연동한다. KakaoLoginController에 내용을 추가한다.
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("")
public class KakaoLoginController {
private final KakaoService kakaoService;
@GetMapping("/auth/login/kakao")
public ResponseEntity<?> KakaoLogin(@RequestParam("code") String code) {
String accessToken = kakaoService.getAccessTokenFromKakao(code);
return new ResponseEntity<>(HttpStatus.OK);
}
}
- 이제 code를 이용해서 accessToken을 받아올 수 있다.
Token으로 사용자 정보 가져오기
이제 카카오에서 받은 access token으로 사용자 정보를 가져와본다.
KakaoService
먼저 사용자의 정보를 담을 KakaoUserInfoResponseDto를 추가한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Getter;
import lombok.NoArgsConstructor;
import java.util.Date;
import java.util.HashMap;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoUserInfoResponseDto {
//회원 번호
@JsonProperty("id")
public Long id;
//자동 연결 설정을 비활성화한 경우만 존재.
//true : 연결 상태, false : 연결 대기 상태
@JsonProperty("has_signed_up")
public Boolean hasSignedUp;
//서비스에 연결 완료된 시각. UTC
@JsonProperty("connected_at")
public Date connectedAt;
//카카오싱크 간편가입을 통해 로그인한 시각. UTC
@JsonProperty("synched_at")
public Date synchedAt;
//사용자 프로퍼티
@JsonProperty("properties")
public HashMap<String, String> properties;
//카카오 계정 정보
@JsonProperty("kakao_account")
public KakaoAccount kakaoAccount;
//uuid 등 추가 정보
@JsonProperty("for_partner")
public Partner partner;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class KakaoAccount {
//프로필 정보 제공 동의 여부
@JsonProperty("profile_needs_agreement")
public Boolean isProfileAgree;
//닉네임 제공 동의 여부
@JsonProperty("profile_nickname_needs_agreement")
public Boolean isNickNameAgree;
//프로필 사진 제공 동의 여부
@JsonProperty("profile_image_needs_agreement")
public Boolean isProfileImageAgree;
//사용자 프로필 정보
@JsonProperty("profile")
public Profile profile;
//이름 제공 동의 여부
@JsonProperty("name_needs_agreement")
public Boolean isNameAgree;
//카카오계정 이름
@JsonProperty("name")
public String name;
//이메일 제공 동의 여부
@JsonProperty("email_needs_agreement")
public Boolean isEmailAgree;
//이메일이 유효 여부
// true : 유효한 이메일, false : 이메일이 다른 카카오 계정에 사용돼 만료
@JsonProperty("is_email_valid")
public Boolean isEmailValid;
//이메일이 인증 여부
//true : 인증된 이메일, false : 인증되지 않은 이메일
@JsonProperty("is_email_verified")
public Boolean isEmailVerified;
//카카오계정 대표 이메일
@JsonProperty("email")
public String email;
//연령대 제공 동의 여부
@JsonProperty("age_range_needs_agreement")
public Boolean isAgeAgree;
//연령대
//참고 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info
@JsonProperty("age_range")
public String ageRange;
//출생 연도 제공 동의 여부
@JsonProperty("birthyear_needs_agreement")
public Boolean isBirthYearAgree;
//출생 연도 (YYYY 형식)
@JsonProperty("birthyear")
public String birthYear;
//생일 제공 동의 여부
@JsonProperty("birthday_needs_agreement")
public Boolean isBirthDayAgree;
//생일 (MMDD 형식)
@JsonProperty("birthday")
public String birthDay;
//생일 타입
// SOLAR(양력) 혹은 LUNAR(음력)
@JsonProperty("birthday_type")
public String birthDayType;
//성별 제공 동의 여부
@JsonProperty("gender_needs_agreement")
public Boolean isGenderAgree;
//성별
@JsonProperty("gender")
public String gender;
//전화번호 제공 동의 여부
@JsonProperty("phone_number_needs_agreement")
public Boolean isPhoneNumberAgree;
//전화번호
//국내 번호인 경우 +82 00-0000-0000 형식
@JsonProperty("phone_number")
public String phoneNumber;
//CI 동의 여부
@JsonProperty("ci_needs_agreement")
public Boolean isCIAgree;
//CI, 연계 정보
@JsonProperty("ci")
public String ci;
//CI 발급 시각, UTC
@JsonProperty("ci_authenticated_at")
public Date ciCreatedAt;
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Profile {
//닉네임
@JsonProperty("nickname")
public String nickName;
//프로필 미리보기 이미지 URL
@JsonProperty("thumbnail_image_url")
public String thumbnailImageUrl;
//프로필 사진 URL
@JsonProperty("profile_image_url")
public String profileImageUrl;
//프로필 사진 URL 기본 프로필인지 여부
//true : 기본 프로필, false : 사용자 등록
@JsonProperty("is_default_image")
public String isDefaultImage;
//닉네임이 기본 닉네임인지 여부
//true : 기본 닉네임, false : 사용자 등록
@JsonProperty("is_default_nickname")
public Boolean isDefaultNickName;
}
}
@Getter
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class Partner {
//고유 ID
@JsonProperty("uuid")
public String uuid;
}
}
KakaoService에 추가한다.
public KakaoUserInfoResponseDto getUserInfo(String accessToken) {
KakaoUserInfoResponseDto userInfo = WebClient.create(KAUTH_USER_URL_HOST)
.get()
.uri(uriBuilder -> uriBuilder
.scheme("https")
.path("/v2/user/me")
.build(true))
.header(HttpHeaders.AUTHORIZATION, "Bearer " + accessToken)
.header(HttpHeaders.CONTENT_TYPE, HttpHeaderValues.APPLICATION_X_WWW_FORM_URLENCODED.toString())
.retrieve()
.onStatus(HttpStatusCode::is4xxClientError, clientResponse -> Mono.error(new RuntimeException("Invalid Parameter")))
.onStatus(HttpStatusCode::is5xxServerError, clientResponse -> Mono.error(new RuntimeException("Internal Server Error")))
.bodyToMono(KakaoUserInfoResponseDto.class)
.block();
log.info(" [Kakao Service] Auth ID ------> {}", userInfo.getId());
log.info(" [Kakao Service] NickName ------> {}", userInfo.getKakaoAccount().getProfile().getNickName());
log.info(" [Kakao Service] Id Token ------> {}", userInfo.getKakaoAccount().getProfile().getProfileImageUrl());
return userInfo;
}
- https://kapi.kakao.com/v2/user/me에 헤더 Authorization에 Bearer token을 추가해서 GET 요청을 보내면, Response에 아래와 같은 Body를 받을 수 있다.
KakaoLoginController
최종적으로 KakaoLoginController는 다음과 같다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.controller;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto.KakaoUserInfoResponseDto;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.service.KakaoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("")
public class KakaoLoginController {
private final KakaoService kakaoService;
@GetMapping("/auth/login/kakao")
public ResponseEntity<?> KakaoLogin(@RequestParam("code") String code) {
String accessToken = kakaoService.getAccessTokenFromKakao(code);
KakaoUserInfoResponseDto userInfo = kakaoService.getUserInfo(accessToken);
// 여기에 서버 사용자 로그인(인증) 또는 회원가입 로직 추가
return new ResponseEntity<>(HttpStatus.OK);
}
}
회원가입, 로그인
로그인 이후 회원가입을 통해 카카오에서 제공하는 정보 외에 내용을 받을려고한다. 그래서 다음과 같이 Member를 정의해준다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.entity;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto.SignupRequestDto;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;
@Entity
@Table(name="members")
@Getter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Member {
@Id
private Long kakaoId;
private String name;
private String location;
@Enumerated(EnumType.STRING)
private Role role;
@Column(name = "profile_image_url")
private String profileImageUrl;
public enum Role{
CONSUMER, CORPORATE
}
public static Member create(SignupRequestDto dto) {
return Member.builder()
.kakaoId(dto.getKakaoId())
.name(dto.getNickname())
.location(dto.getLocation())
.role(Member.Role.valueOf(dto.getRole().toUpperCase()))
.profileImageUrl(dto.getProfileImageUrl())
.build();
}
}
또한 Member와 관련된 내용을 DB에 저장하기위해 MemerReposiroty를 작성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dao;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.Optional;
public interface MemberRepository extends JpaRepository<Member, Long> {
Optional<Member> findByKakaoId(Long kakaoId);
}
- findBykakaoId: kakaoId를 통해 DB에서 Member를 찾는다.
이제 MemberService와 MemberServiceImpl을 작성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.service;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dao.MemberRepository;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto.SignupRequestDto;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.entity.Member;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@RequiredArgsConstructor
public class MemberServiceImpl implements MemberService {
private final MemberRepository memberRepository;
@Override
public Member signup(SignupRequestDto dto) {
return memberRepository.save(Member.create(dto));
}
@Override
public Optional<Member> findByKakaoId(Long kakaoId) {
return memberRepository.findByKakaoId(kakaoId);
}
}
이제 회원가입을 위한 controller를 작성한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.controller;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.dto.SignupRequestDto;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.entity.Member;
import com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.service.MemberService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
@RestController
@RequiredArgsConstructor
@RequestMapping("/member")
public class MemberController {
private final MemberService memberService;
@PostMapping("/signup")
public ResponseEntity<Member> signup(@RequestBody SignupRequestDto dto) {
try {
Member savedMember = memberService.signup(dto);
return ResponseEntity.ok(savedMember);
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(null);
}
}
}
이제 테스트를 위해 SignupPageController를 작성해 Thymleaf를 이용해 테스트한다.
package com.example.seoulpublicdata2025backend.domain.kakaoSocialLogin.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping("/signup")
public class SignupPageController {
@GetMapping
public String signupPage(@RequestParam("kakaoId") Long kakaoId, @RequestParam("profileUrl") String profileUrl, Model model) {
model.addAttribute("kakaoId", kakaoId);
model.addAttribute("profileUrl", profileUrl);
return "signup";
}
}
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>회원가입</title>
</head>
<body>
<h2>추가 정보 입력</h2>
<!-- 🔥 프로필 이미지 미리보기 -->
<img th:src="${profileUrl}" alt="카카오 프로필 이미지" width="100" height="100" style="border-radius: 50%; margin-bottom: 10px;">
<form id="signupForm">
<input type="text" id="nickname" name="nickname" placeholder="닉네임" required>
<input type="text" id="location" name="location" placeholder="거주지" required>
<select id="role" name="role" required>
<option value="">사용자 유형 선택</option>
<option value="CONSUMER">소비자</option>
<option value="CORPORATE">기업</option>
</select>
<!-- 🔥 필수 데이터 (카카오 ID와 프로필 이미지 URL) -->
<input type="hidden" id="kakaoId" name="kakaoId" th:value="${kakaoId}">
<input type="hidden" id="profileImageUrl" name="profileImageUrl" th:value="${profileUrl}">
<button type="submit">가입</button>
</form>
<script>
document.getElementById('signupForm').addEventListener('submit', async function (e) {
e.preventDefault();
const kakaoId = document.getElementById('kakaoId').value;
const nickname = document.getElementById('nickname').value;
const location = document.getElementById('location').value;
const role = document.getElementById('role').value;
const profileImageUrl = document.getElementById('profileImageUrl').value;
const data = {
kakaoId: kakaoId,
nickname: nickname,
location: location,
role: role,
profileImageUrl: profileImageUrl
};
try {
const response = await fetch('/member/signup', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
});
if (response.ok) {
alert('회원가입 성공!');
window.location.href = '/'; // 필요시 리다이렉트 수정
} else {
alert('회원가입 실패: ' + response.status);
}
} catch (err) {
console.error('에러 발생:', err);
alert('서버 오류');
}
});
</script>
</body>
</html>
이제 회원가입이 가능해지고, 만약 회원가입한 회원이면 main 페이지로 가게된다.
댓글남기기