고을마을 : 나의 코딩 이야기

항해99 9주차 WIL[카카오 OAuth 로그인 완료, github actions를 활용한 CI/CD 구현] 본문

항해99 7기/WIL(Weekly I Learned

항해99 9주차 WIL[카카오 OAuth 로그인 완료, github actions를 활용한 CI/CD 구현]

고을마을 2022. 7. 11. 00:18
@Service
@RequiredArgsConstructor
public class KakaoUserService {

    private final UserRepository userRepository;
    private final PasswordEncoder passwordEncoder;

    @Value("${kakao_client_id}")
    private String client_id;

    @Value("${kakao_redirect_uri}")
    private String redirect_uri;

    public KakaoUserInfo kakaoLogin(String code) throws JsonProcessingException {
        // "인가 코드"로 AccessToken 요청
        String accessToken = getAccessToken(code);
        System.out.println(1);

        KakaoUserInfo kakaoUserInfo = getKakaoUserInfo(accessToken);
        System.out.println(3);

        User kakaoUser = userRepository.findByUsername(kakaoUserInfo.getKakaoMemberId()).orElse(null);
        if  (kakaoUser == null) {
            System.out.println("if");
            registerKakaoUser(kakaoUserInfo);
        }
        System.out.println(4);

//        return getKakaoUserInfo(accessToken);
        return kakaoUserInfo;
    }

    private String getAccessToken(String code) throws JsonProcessingException {

        // HTTP Header 생성
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

        // HTTP Body 생성
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.add("grant_type", "authorization_code");
        body.add("client_id", client_id);
        body.add("redirect_uri", redirect_uri);
        body.add("code", code);

        // HTTP 요청 보내기
        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(body, headers);
        RestTemplate rt = new RestTemplate();
        ResponseEntity<String> response = rt.exchange(
                "https://kauth.kakao.com/oauth/token",
                HttpMethod.POST,
                kakaoTokenRequest,
                String.class
        );

        // HTTP 응답 (JSON) -> AccessToken 파싱
        String responseBody = response.getBody();
        ObjectMapper objectMapper = new ObjectMapper();    // Json 형식 java에서 사용하기 위해 objectMapper 사용
        JsonNode jsonNode = objectMapper.readTree(responseBody);
        return jsonNode.get("access_token").asText();
    }

    // AccessToken 으로 카카오 사용자 정보 가져오기
    private KakaoUserInfo getKakaoUserInfo(String accessToken) throws JsonProcessingException {

        // HTTP Header 생성
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", "Bearer " + accessToken);
        headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

        // HTTP 요청 보내기
        HttpEntity<MultiValueMap<String, String>> kakaoUserInfoRequest = new HttpEntity<>(headers);
        RestTemplate rt = new RestTemplate();
        ResponseEntity<String> response = rt.exchange(
                "https://kapi.kakao.com/v2/user/me",
                HttpMethod.POST,
                kakaoUserInfoRequest,
                String.class
        );
        System.out.println(2);

        String responseBody = response.getBody();
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(responseBody);
        Long kakaoId = jsonNode.get("id").asLong();
        String email = jsonNode.get("kakao_account").get("email").asText();
        return KakaoUserInfo.builder()
                .kakaoId(kakaoId)
                .kakaoMemberId(email)
                .build();
    }

    // 첫 소셜로그인일 경우 DB 저장
    private void registerKakaoUser(KakaoUserInfo kakaoUserInfo) {

        String password = UUID.randomUUID().toString();
        String encodedPassword = passwordEncoder.encode(password);

        System.out.println("registerKakaoUser");
        System.out.println(kakaoUserInfo.getKakaoMemberId());
        User kakaoUser = User.builder()
                .kakaoId(kakaoUserInfo.getKakaoId())
                .username(kakaoUserInfo.getKakaoMemberId())
                .password(encodedPassword)
                .nickname("default")
                .role(UserRoleEnum.USER)
                .build();
        userRepository.save(kakaoUser);
        System.out.println("save");
    }

}

 

// 카카오 로그인 유저 상태 확인
public StatusResponseDto SignupUserCheck(Long kakaoId) {

    User loginUser = userRepository.findByKakaoId(kakaoId).orElse(null);

    if (loginUser.getNickname().equals("default")) {
        KakaoUserInfo kakaoUserInfo = KakaoUserInfo.builder()
                .userId(loginUser.getId())
                .kakaoId(kakaoId)
                .build();
        return new StatusResponseDto("추가 정보 작성이 필요한 유저입니다", kakaoUserInfo);
    } else {
        TokenDto tokenDto = jwtTokenProvider.createToken(loginUser);
        return new StatusResponseDto("로그인 성공", tokenDto);
    }
}

 

spring.jpa.hibernate.ddl-auto=update
spring.jpa.hibernate.ddl-auto=create

 

 

카카오 oAuth 참고자료

https://www.youtube.com/watch?v=WACDTFroYNI&list=PL93mKxaRDidECgjOBjPgI3Dyo8ka6Ilqm&index=68 

 

 

 

 

name: Java CI with Gradle

on:
  push:
    branches: [ release ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Create ./src/main/resources/
        run: |
          mkdir -p ./src/main/resources/

      - name: make application.properties
        run: |
          cd ./src/main/resources
          touch ./application.properties
          echo "${{ secrets.PROPERTIES }}" > ./application.properties
        shell: bash

      - name: Grant execute permission for gradlew
        run: chmod +x ./gradlew
        shell: bash

      - name: Build with Gradle
        run: ./gradlew build
        shell: bash

      - name: Make zip file #1
        run: zip -qq -r ./$GITHUB_SHA.zip .
        shell: bash

      - name: Configure AWS credentials #2
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      - name: Upload to S3 #3
        run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://{s3 이름}/$GITHUB_SHA.zip

      - name: Code Deploy #4
        run: aws deploy create-deployment --application-name {iam이름}
          --deployment-config-name CodeDeployDefault.OneAtATime
          --deployment-group-name dev
          --s3-location bucket={s3 이름},bundleType=zip,key=$GITHUB_SHA.zip

+ appspec.yml, deploy.sh도 작성해야함.

 

 

ci/cd 참고자료

https://goodgid.github.io/Github-Action-CI-CD-AWS-EC2/

 

Github Action으로 CI/CD 구축하기 - 1편 : AWS EC2 생성 및 설정

Index

goodgid.github.io

https://isntyet.github.io/deploy/github-action%EA%B3%BC-aws-code-deploy%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-spring-boot-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0(4)/ 

 

github action과 aws code deploy를 이용하여 spring boot 배포하기(4)

Repository = action_codedeploy

isntyet.github.io

https://www.youtube.com/watch?v=Np64aq4AlLg