목차
- Java 기본 문법
- Spring 핵심 개념
- Spring Security + JWT
- 면접 예상 질문과 답변
1. Java 기본 문법
1.1 생성자 (Constructor)
포인트: "생성자가 무엇이고 언제 호출되나요?"
public class Person {
private String name;
private int age;
// 기본 생성자
public Person() {
this.name = "Unknown";
this.age = 0;
}
// 매개변수 생성자
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
// 사용
Person person = new Person("홍길동", 25); // 생성자 자동 호출
핵심 답변:
- 생성자는 객체가 생성될 때 자동으로 호출되는 특별한 메서드
- 클래스 이름과 동일하며 반환 타입이 없음
- 객체의 초기 상태를 설정하는 역할
- 기본 생성자는 매개변수 생성자가 없을 때만 자동 생성됨
1.2 접근 제어자
포인트: "private, public의 차이와 캡슐화의 이점은?"
public class BankAccount {
private int balance; // 외부 접근 차단
public String accountNumber; // 외부 접근 가능
public void deposit(int amount) {
if (amount > 0) { // 검증 로직
this.balance += amount;
}
}
public int getBalance() { // 통제된 접근
return balance;
}
}
핵심 답변:
- private: 클래스 내부에서만 접근 가능
- public: 어디서든 접근 가능
- 캡슐화의 이점: 데이터 보호, 검증 로직 적용, 내부 구현 변경 시 외부 코드 영향 최소화
1.3 static 키워드
포인트: "static 변수와 인스턴스 변수의 차이는?"
public class Counter {
private static int totalCount = 0; // 클래스 변수 (모든 인스턴스 공유)
private int instanceCount = 0; // 인스턴스 변수 (객체마다 독립)
public Counter() {
totalCount++; // 모든 객체가 공유
instanceCount++; // 각 객체마다 독립
}
public static int getTotalCount() { // 객체 생성 없이 호출 가능
return totalCount;
}
}
핵심 답변:
- static: 클래스 로딩 시 메모리에 할당, 모든 인스턴스가 공유
- 인스턴스 변수: 객체마다 독립적인 메모리 공간
- static 메서드는 객체 생성 없이 클래스명으로 직접 호출 가능
1.4 인터페이스와 추상 클래스
포인트: "인터페이스와 추상 클래스의 차이점은?"
// 인터페이스 - 계약서 역할
interface Drawable {
void draw(); // 추상 메서드
default void print() { // Java 8+ default 메서드
System.out.println("Drawing...");
}
}
// 추상 클래스 - 공통 기능 + 강제 구현
abstract class Animal {
protected String name; // 공통 필드
public Animal(String name) { // 공통 생성자
this.name = name;
}
public void sleep() { // 구현된 메서드
System.out.println(name + " is sleeping");
}
public abstract void makeSound(); // 추상 메서드
}
핵심 답변:
- 인터페이스: 다중 구현 가능, 계약서 역할, 모든 메서드가 기본적으로 추상
- 추상 클래스: 단일 상속, 공통 기능 제공 + 강제 구현 메서드
1.5 제네릭 (Generics)
포인트: "제네릭을 사용하는 이유는?"
// 제네릭 없이
List list = new ArrayList();
list.add("문자열");
list.add(123);
String str = (String) list.get(0); // 형변환 필요, 런타임 에러 위험
// 제네릭 사용
List<String> stringList = new ArrayList<>();
stringList.add("문자열");
// stringList.add(123); // 컴파일 에러!
String str = stringList.get(0); // 형변환 불필요
핵심 답변:
- 타입 안전성: 컴파일 타임에 타입 체크
- 형변환 제거: 명시적 캐스팅 불필요
- 코드 재사용성: 하나의 코드로 여러 타입 처리
2. Spring 핵심 개념
2.1 의존성 주입 (Dependency Injection)
포인트: "의존성 주입이 무엇이고 왜 사용하나요?"

핵심 답변:
- 정의: 객체 간 의존 관계를 외부에서 주입하는 방식
- 장점:
- 느슨한 결합으로 유연성 증대
- 테스트 용이성 (Mock 객체 주입 가능)
- 코드 재사용성 향상
- 관심사 분리
2.2 생성자 주입을 권장하는 이유
포인트: "필드 주입 vs 생성자 주입의 차이는?"
// ❌ 필드 주입 (권장하지 않음)
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
// 의존성이 없어도 객체 생성 가능 (NullPointerException 위험)
}
// ✅ 생성자 주입 (권장)
@Service
@RequiredArgsConstructor
public class UserService {
private final UserRepository userRepository; // final 사용 가능
// 생성자 호출 시 의존성 필수 보장
}
핵심 답변:
- 불변성: final 키워드로 변경 불가능
- 필수 의존성 보장: 객체 생성 시 반드시 주입
- 테스트 용이성: 생성자로 Mock 객체 주입 가능
- 순환 의존성 방지: 컴파일 타임에 발견
@Autowired 란?
Spring이 필요한 객체(Bean)를 자동으로 찾아서 주입해주는 기능입니다. 개발자가 직접 객체를 생성하지 않아도 Spring이 알아서 필요한 객체를 찾아 연결해줍니다.
2.3 Spring Bean 생명주기와 @PostConstruct
포인트: "@PostConstruct를 언제 사용하나요?"

Spring Bean 생명주기:
- 객체 생성 (생성자 호출)
- 의존성 주입 (필드, setter 주입 등)
- @PostConstruct 메서드 실행 ← 여기서 안전한 초기화!
- 빈 사용 가능
- @PreDestroy 메서드 실행
- 객체 소멸
핵심 답변:
- 외부 설정값에 의존하는 복잡한 초기화에 사용
- 생성자에서는 의존성이 완전히 준비되지 않을 수 있음
- 한 번만 실행되며 Spring이 실행 타이밍 보장
2.4 주요 어노테이션
포인트: "@Component, @Service, @Repository의 차이는?"
@Component // 일반적인 Spring Bean
public class FileUtil { }
@Service // 비즈니스 로직 (@Component + 의미)
public class UserService { }
@Repository // 데이터 접근 (@Component + 예외 변환)
public class UserRepository { }
@Controller // 웹 MVC 컨트롤러
public class UserController { }
@RestController // REST API (@Controller + @ResponseBody)
public class ApiController { }
핵심 답변:
- 모두 @Component를 기반으로 하는 특화된 스테레오타입
- 의미적 구분: 코드 가독성과 AOP 적용 시 구분 가능
- @Repository: DataAccessException 변환 기능 추가
3. Spring Security & JWT
3.1 JWT 토큰의 구조와 동작 원리
포인트: "JWT가 무엇이고 어떻게 동작하나요?"

JWT 구조:
- Header: 토큰 타입과 해시 알고리즘
- Payload: 실제 데이터 (Claims)
- Signature: 무결성 검증용 서명
핵심 답변:
- Stateless: 서버가 세션 상태를 저장하지 않음
- Self-contained: 토큰 자체에 사용자 정보 포함
- 확장성: 마이크로서비스 환경에 적합
3.2 Spring Security 인증 흐름
포인트: "Spring Security의 인증 과정을 설명해주세요"

인증 흐름:
- 클라이언트가 JWT 토큰과 함께 요청
- JwtAuthenticationFilter에서 토큰 추출
- 토큰 유효성 검증 (만료, 서명, 블랙리스트)
- 유효하면 SecurityContext에 인증 정보 저장
- 컨트롤러에서 @AuthenticationPrincipal로 사용자 정보 접근
핵심 답변:
- Filter Chain: 요청이 컨트롤러에 도달하기 전 보안 검사
- SecurityContext: 현재 스레드의 인증 정보 저장소
- Stateless Session: 세션 대신 토큰으로 상태 관리
4. 면접 예상 질문과 답변
Q1. "Spring에서 Bean은 언제 생성되나요?"
답변:

- Singleton (기본): 애플리케이션 시작 시 생성, 하나의 인스턴스만 존재
- Prototype: 요청할 때마다 새로운 인스턴스 생성
- Lazy: @Lazy 어노테이션 시 실제 사용할 때 생성
Q2. "생성자 주입이 필드 주입보다 좋은 이유는?"
답변:

- 불변성: final 키워드 사용 가능
- 테스트 용이성: 생성자로 Mock 주입
- 필수 의존성 보장: 의존성 없으면 객체 생성 불가
- 순환 의존성 방지: 컴파일 타임에 발견
Q3. "@PostConstruct는 언제 사용하나요?"
답변:

사용 시기:
- 외부 설정값(@Value, @ConfigurationProperties)에 의존하는 초기화
- 다른 Bean에 의존하는 복잡한 초기화
- 외부 리소스 연결 (DB, Redis, API 클라이언트)
Q4. "JWT의 보안 취약점과 대응 방안은?"
답변:
취약점:
- 토큰 탈취: XSS, Man-in-the-middle 공격
- 만료되지 않은 토큰: 장기간 유효한 토큰 위험
- 무효화 불가: 로그아웃 시 토큰 무효화 어려움
대응 방안:

Q5. "Spring에서 예외 처리는 어떻게 하나요?"
답변:



포인트:
- 도메인별 예외 분리: 명확한 예외 계층
- @RestControllerAdvice: 전역 예외 처리
- 일관된 응답 형식: 클라이언트 처리 용이
자가 질문! 스스로에게 물어보는 시간
1. @Value vs @ConfigurationProperties
"설정이 많아질수록 @ConfigurationProperties가 유리합니다. 타입 안전성과 IDE 지원이 뛰어나고, Bean Validation으로 검증도 가능합니다."
2. Builder 패턴 성능
"미미한 성능 차이는 있지만, 실제 비즈니스 로직에서는 무시할 수준입니다. 가독성과 유지보수성이 더 중요한 경우가 많습니다."
3. Spring Bean 생명주기
"미미한 성능 차이는 있지만, 실제 비즈니스 로직에서는 무시할 수준입니다. 가독성과 유지보수성이 더 중요한 경우가 많습니다."
'Spring 7기 프로젝트 > 아웃소싱 팀 프로젝트' 카테고리의 다른 글
| [트러블슈팅] JWT + Spring Security 기반 인증/인가 시스템 구현 후기 (프로젝트 정리본) (0) | 2025.06.18 |
|---|---|
| [트러블슈팅] 나만의 Spring Security + JWT를 활용한 인증 시스템 구조 (0) | 2025.06.17 |
| [트러블슈팅] Spring Boot에서 이벤트 기반 아키텍처 구현 시 마주하는 도전과제와 해결책 (0) | 2025.06.16 |
| [트러블슈팅] 과도한 엔지니어링 : 이벤트 기반 아키텍처 삽질기 (0) | 2025.06.15 |
| [트러블슈팅] 대시보드 성능 최적화: GROUP BY 지옥에서 이벤트 기반 통계로 (0) | 2025.06.15 |