트러블슈팅 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 |