0. 시작

  현재 진행중인 프로젝트에서 인가/인증을 담당하는 Auth-server 와 회원정보를 조회하는 Member-server를 분리하기로 결정이 났다.

Member-server는 클라이언트에 노출하지않고,  다른 서비스에서 회원 정보를 조회하는데만 사용하는 용도로 만들기 위하여 분리를 하는걸로 결정이 났다.

 

1. 문제

  인가인증 서버의 경우 SpringSecurity를 사용하지만, MemberServer는 spring security 없이 사용을 하기로 했기에 여기서 사소한 문제가 발생되었다.

 

인가인증 서버의 엔티티는 다음과 같다.

@Entity
@Getter
@Table(name = "users")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@AllArgsConstructor
@Builder
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String nickname;

    @Column(nullable = false)
    private Role role;
     
     
     ...

 

편의성을 이유로 엔티티가 순수하게 유지되지 않고, Security의 UserDetails를 상속받아서 사용을 하고있는 모습이다.

 

MeberServer와 authServer가 같은 UserEntity를 사용해야 하는데, 이 둘은 서버가 분리된 환경에서 심지어 한쪽은 security를 사용하고 반대쪽은 사용하지 않는 상황이다. MemberServer에서 UserDetails를 상속받지않는 그냥 UserEntity를 복붙해서 사용한다면, 유지 보수및 변경 대응이 너무 번거로워질것 같은 생각이 들었다.

 

그래서 이들을 공통 모듈을 상속받게 하여서 관리포인트를 하나로 만들어야하는 과제가 주어졌다.

 

2. 주요 포인트.

  공통 모듈을 만드는 방법에도 두가지가 존재한다. 인가인증 서버와 MemberServer의 루트에 멀티모듈 방식으로 참조하게 하는 방법이 있고, 완전 별개의 프로젝트로 분리를 하여 Jar로 의존하거나 Gradle로 연동하는 방법이 있다.

 

멀티모듈 방식으로 한다면 개발속도도 빠르고, 따로 엔티티를 위해서 빌드를 해줄 필요는 없다.  하지만 서버간 완전 분리를 원하는 상황이라 UserEntity를 따로 git으로 관리를 해주는 수고가 들더라도 별개의 프로젝트로 분리를 하여 공통단으로 사용하기로 결정하였다.

 

 3. UserEntity전용 Common 프로젝트 생성

dependencies {
    implementation 'jakarta.persistence:jakarta.persistence-api:3.1.0'
    compileOnly 'org.projectlombok:lombok'
}

우선은 Entity전용으로만 사용할 공통모듈이라 JPA와 편의성 롬복만 의존성으로 넣어준다.(추후 다른 공통단 넣으면 그때 의존을 걸어준다.)

 

그리고 일반 프로젝트 처럼 패키지를 만들고 entity를 작성해준다.

security가 없는 순수 엔티티로 만들어준다.

import lombok.*;
@Entity
@Getter
@AllArgsConstructor
@NoArgsConstructor
@Table(name = "users")
public class Users {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false, unique = true)
    private String username;

    @Column(nullable = false)
    private String password;

    @Column(nullable = false, unique = true)
    private String email;

    @Column(nullable = false)
    private String nickname;

    @Column(nullable = false)
    private Role role;

}

 

//추가 2025 03-24
이때  Common 프로젝트에서 application.yml을 제거해야 datasource충돌 에러가 나지않는다.

 

그리고 이것을 깃 레파지토리를 따로 파서 올려 준 후에 이 공통 entity를 사용하고자 하는 Member-server 프로젝트로 돌아오자.

 

터미널에서 공통단을 서브모듈로 추가를 해주면 된다.

git submodule add https://github.com/깃헙아이디/레파지토리명.git 원하는폴더명

 

나는 common이라는 폴더에 공통단이 다 들어왔으면 좋다고 생각해서 common으로 해줬다.

git submodule add https://github.com/깃헙아이디/레파지토리명.git common

 

 

그럼 이렇게 common으로 다운로드가 잘 된 모습니다.

 

그 후 Member-server의 settings.gradle로 들어가서

include ':common'
project(':common').projectDir = file('common')

 

아까 공통모듈이 다운로드되도록 지정한 폴더명으로  추가를 해주고 build.gradle로 가서 dependencies{} 에 

dependencies{
...
implementation project(':common') // 다운받은 공통모듈 의존성 추가
...
}

의존성을 추가해주면 된다.

 

//추가 2025-03-24
Member-server의 메인메소드에서 다음과 같이 @EntityScan을 사용하여 common 모듈도 함께 스캔하도록 명시를 해줘야 한다.

@SpringBootApplication
@EntityScan({"com.msa.member", "com.msa.common"})
public class MemberApplication {
    public static void main(String[] args) {
        SpringApplication.run(MemberApplication.class, args);
    }

}

 

 

이렇게 해주면 공통모듈을 만드는 과정이 끝이 났고 원하는 곳에서 호출하여 사용하면 된다.

 

SearchRepository

import com.msa.common.entity.Users;

@Repository
public interface SearchRepository extends  JpaRepository<Users, Long> {
    
}

 

 

MemberService

package com.msa.member.search.service;

import com.msa.common.entity.Users;
import com.msa.member.search.repository.SearchRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.util.List;

@Service
@RequiredArgsConstructor
public class SearchService {
    private final SearchRepository searchRepository;
    
    public void findAllMember() {
        List<Users> all = searchRepository.findAll();
        all.forEach(a -> {
            System.out.println(a.getUsername());
        });
    }
}

 

 

2편에선 Auth-server에서 사용하는 UserEntity에서 UserDetails 상속을 지우고 공통단을 사용하여 인가인증이 작동되도록 해보자.

+ Recent posts