SPARTA 과제/TEAM | commerce

팀) 커머스 - DB 생성 시 값 넣기

kjw81024 2026. 2. 27. 13:58

트러블슈팅 2 / 문제 3 해결 방법

 

문제

처음 슈퍼관리자가 회원가입을 하려고 하면 PENDING (승인대기) 상태로 들어가게 됨

근데 승인상태로 바꿔주려면 ACTIVE 상태의 SUPER_ADMIN 이 필요

 

해결

3개 정도의 방법을 생각해봤다

 

(1) ID 가 1이면 슈퍼관리자 일테니까 Status 를 ACTIVE 로 설정하는 로직 작성

(2) DB 에 직접 ID, email, password, ACTIVE, SUPER_ADMIN 등의 정보를 넣고 시작 

(3) 회원가입 후 Status 만 ACTIVE 로 바꿔주기 


1번 방법 

 ID 가 1이면 슈퍼관리자 일테니까 Status 를 ACTIVE 로 설정하는 로직 작성

if (admin.getId == 1) setAdminStatus = ACTIVE

위 의미의 코드를 사용해보려고 했는데 table 을 정리하려고 delete 를 사용하고 다시 새 슈퍼관리자를 만들려고 하니까 

id 가 1이 아닌 이후의 수로 매핑됨

table 을 아예 던져버리긴 싫어서 일단 이 방법은 보류

 

아니면 아예 DB 를 쭉 확인하면서 SUPER ADMIN 이면서 ACTIVE 인 사람이 없으면 ACTIVE 권한을 주는 방법도 생각해봤다


2번 방법

DB 에 직접 ID, email, password, ACTIVE, SUPER_ADMIN 등의 정보를 넣고 시작 

로그인이 안 됨

왜 그러나 확인해봤더니... 생각해보니 pw 에 encoding 이 걸려있음 ....... DB 에 encoding 된 pw 로 다시 업데이트 해줘야만 동작

encoding 결과도 매번 달라져서 미리 다른곳에 적어둘 수도 없는 문제...


3번 방법

회원가입 후 Status 만 ACTIVE 로 바꿔주기 

 

일단 현재는 코드를 건드리지않고 3번 방법을 사용하고있다...

회원가입을 하면 PENDING 상태로 DB 에 슈퍼관리자가 들어오게 되는데 그 때 상태만 ACTIVE 로 수동으로 바꿔서 사용한다.

어떻게 할지 더 고민해봐야할듯함...


최종 사용 방법

어떻게 보면 1번과 2번의 방법을 모두 사용한것과 비슷한데

실행시  table 이 비어있는지 확인하고, email, encoding 된 password, ACTIVE, ROLE 값을 넣어주는 방법을 사용했다

 

참고자료: https://j-d-i.tistory.com/275

 

스프링 부트 애플리케이션 시작 시 코드 실행 (CommandLineRunner)

스프링 부트 애플리케이션을 시작할 때 특정 코드를 실행해야 할 때가 있다. ex) 애플리케이션 초기화 이전에 데이터 베이스 초기화 스크립트를 실행, 혹은 외부 REST 서비스를 호출해서 데이터

j-d-i.tistory.com

 

실행 파일을 누르면 시작 시에 특정 코드를 실행시키고 싶을 때 사용하는 방법 3개를 모두 해봤다

기본 코드

if (adminRepository.count() == 0){
    Admin admin = new Admin(
            "테스트용 init 슈퍼관리자",
            "testAdmin@test.com",
            PasswordEncoder.encode("newPassword"),
            "010-9999-9999",
            Role.SUPER_ADMIN,
            AdminStatus.ACTIVE
    );
    adminRepository.save(admin);
}

1) 메인클래스에 인터페이스 구현1

 

Application 이 CommandLineRunner 를 implements 하게 하고 내부에 run method 를 Override 하도록 한다.

궁금했던 점은 왜 run 안에 메서드를 구현하지 않고 따로 @Bean 을 만드는지였음

 

그냥 run 메서드 내부에 넣어서 사용해봤다

문제없이 실행된다 


2) 메인클래스에서 인터페이스 구현 2

 

tistory 를 보니까 @Bean 밑에 생성자 처럼 생긴게 들어간다.

뭔가 했더니 Bean 생성 메서드였음 -> CommandLineRunner 라는 객체를 만들고 Bean 으로 등록하겠다!

-> 해당 메소드 내부에 해당 객체를 만들고 return 해주는 로직이 필요 

 

또 이상한건 구조였다... return 문이 바로 나오는 구조

보니까 lambda 를 사용한 거 같음 람다를 풀어서 써보니까 아래형태가 되었음

# lambda 사용 x 

CommandLineRunner createBean() {
	CommandLineRunner args = new CommandLineRunner(){
    	@Override
        public void run(String...args){
        	System.out.println("executed");
        }
    };
    
    return runner;
}

# lambda 사용 o

CommandLineRunner createBean(){
	return args -> {
    	System.out.println("executed");
    };
}

즉 CommandLineRunner 구현체 객체를 생성하고 바로 return 하는 게 람다로 축약된것

@EnableJpaAuditing
@RequiredArgsConstructor
@SpringBootApplication
public class CommerceApplication implements CommandLineRunner {
	public static void main(String[] args) {
        SpringApplication.run(CommerceApplication.class, args);
    }

    @Override
    public void run(String... args) throws ServiceException {
        System.out.println("CommandLineRunner executed");
    }

    @Bean
    public CommandLineRunner commandLineRunner(AdminRepository adminRepository, PasswordEncoder passwordEncoder){
        return args -> {
            if (adminRepository.count() == 0){
                Admin admin = new Admin(
                        "2. 테스트용 init 슈퍼관리자",
                        "testAdmin@test.com",
                        passwordEncoder.encode("newPassword"),
                        "010-9999-9999",
                        Role.SUPER_ADMIN,
                        AdminStatus.ACTIVE
                );
                adminRepository.save(admin);
            }
        };

    }
}

 

두번째로 작성한 코드도 잘 돌아간다 (table 은 application propertise 에서 create 로 설정해서 매번 초기화됨)


3) @Component  붙여서 구현

사실 위를 했으면 다른... 건 따로 할 필요 없어보인다.

그냥 main 함수 내부에 구현하는게 아니라 

원하는 클래스를 하나 만들고 implements 를 옮겨서 구현해주면 됨

 

@Component
@RequiredArgsConstructor
public class InitAdmin implements CommandLineRunner {
    private final AdminRepository adminRepository;
    private final PasswordEncoder passwordEncoder;

    @Override
    public void run(String... args) throws Exception {

        if (adminRepository.count() == 0){
            Admin admin = new Admin(
                    "3. 테스트용 init 슈퍼관리자",
                    "testAdmin@test.com",
                    passwordEncoder.encode("newPassword"),
                    "010-9999-9999",
                    Role.SUPER_ADMIN,
                    AdminStatus.ACTIVE
            );
            adminRepository.save(admin);
        }
    }
}

4) @Bean 붙여서 구현

근데 값이 안 들어감....

-> @Configuration 붙여주기 : Bean 생성 전용 클래스 

원래 Bean 어노테이션을 사용할 때 @Configuration 안에서 씀

 

돌렸는데 또 안 돌아감

initAdmin 이라는 bean 이 이미 존재한다는데 나는 쓴적이 없어서 뭐지??? 했다...

The bean 'initAdmin', defined in class path resource [com/example/commerce/global/config/InitAdmin.class], could not be registered. A bean with that name has already been defined in file [C:\Users\user\Documents\SPARTA_bootcamp\commerce\commerce\build\classes\java\main\com\example\commerce\global\config\InitAdmin.class] and overriding is disabled.

 

-> Spring 에서 bean 이름을 결정할 때 Class 이름 첫글자를 소문자로 해서 저장 : 클래스 명이 InitAdmin 이고 내가 쓴 @Bean 이름도 initAdmin 이라서 충돌 발생

 

-> 함수명을 바꿔주니 정상적으로 동작한다.

@Configuration
@RequiredArgsConstructor
public class InitAdmin {
    private final AdminRepository adminRepository;
    private final PasswordEncoder passwordEncoder;

    @Bean
    public CommandLineRunner newInitAdmin(){

        return args -> {
            if (adminRepository.count() == 0){
                Admin admin = new Admin(
                        "4. 테스트용 init 슈퍼관리자",
                        "testAdmin@test.com",
                        passwordEncoder.encode("newPassword"),
                        "010-9999-9999",
                        Role.SUPER_ADMIN,
                        AdminStatus.ACTIVE
                );
                adminRepository.save(admin);
            }
        };
    }
}

 


결론

어렵지 않은 내용 같았는데 Bean 과 Component, CommandLineRunner, Configuration 등 이름이랑 개념만 알던걸 직접 적용해서 사용해보려고 하니까 많이 헤맸다.... (ㅠㅠ)

 

똑같이 잘 동작하고 DB 에 저장되는것을 확인했지만 뭐가 제일 좋은건지 모르겠다... 모두 손에 안 익어서 편리한걸 고를 수도 없음

  장점 단점
1번
메인 내부에서
직접 run 실행
간단하고 파일을 하나만 써도 됨  main 클래스가 너무 커지고 역할 분리가 안 됨
Runner 를 여러개 정의할 수 없음 
복잡
2번
메인 내부에서
분리하여 Bean 호출
간단하고 파일을 하나만 써도 됨 
람다 사용 가능 (간단)
main 클래스가 너무 커지고 역할 분리가 안 됨
init 해야하는게 많아지면 복잡해진다 

3번
클래스 분리하여
Component 호출
직관적
클래스 단위 관리가 가능 
DI 가 component 덕에 자동으로 됨 
람다 사용 가능 (간단)
 
4번
클래스 분리하여
Configuration, Bean 호출
람다 사용 가능 (간단)
Spring 정석 
 

'SPARTA 과제 > TEAM | commerce' 카테고리의 다른 글

팀) 커머스 - Soft Delete  (0) 2026.02.27
팀) 커머스 트러블슈팅 (3)  (0) 2026.02.27
팀) 커머스 - 리스트 출력  (0) 2026.02.22
팀) 커머스 트러블슈팅 (2)  (0) 2026.02.20
팀) 커머스 트러블슈팅 (1)  (0) 2026.02.19