👉 답변 방향: 사용했던 기능과 프로젝트에서의 역할 중심으로 설명
🔹예시 답변:
"웹 애플리케이션에서 MySQL을 사용하여 사용자 정보 저장, 로그 데이터 관리 등의 작업을 했습니다. MyBatis를 이용하여 SQL을 작성했고, 인덱스를 활용해 성능을 최적화한 경험도 있습니다."
👉 답변 방향: 테이블 설계 시 고려했던 사항, 정규화, 인덱스 전략 등을 설명
🔹예시 답변:
"사용자 계정과 주문 데이터를 저장하는 테이블을 설계한 경험이 있습니다. 데이터 중복을 줄이기 위해 정규화를 진행했으며, 성능을 위해 자주 조회하는 컬럼에 인덱스를 설정했습니다."
👉 답변 방향: 성능 저하 요인과 이를 해결한 경험을 설명
🔹예시 답변:
"대량 데이터 처리 시, 인덱스가 없는 WHERE 조건 검색으로 인해 성능 저하가 발생한 경험이 있습니다. 실행 계획(EXPLAIN)을 확인하여 적절한 인덱스를 추가하고, 쿼리 최적화를 통해 성능을 개선했습니다."
👉 답변 방향: 자주 검색하는 컬럼, 카디널리티(고유값 개수), 복합 인덱스 활용 여부 등을 설명
🔹예시 답변:
"자주 조회하는 컬럼이나 JOIN 시 사용되는 컬럼에 인덱스를 설정합니다. 또한, 단일 컬럼보다는 복합 인덱스를 활용하여 여러 검색 조건을 최적화하는 경우도 있습니다."
👉 답변 방향: 트랜잭션의 개념, COMMIT/ROLLBACK 사용 경험 설명
예시 답변:
"주문 결제 기능을 개발할 때, 데이터 정합성을 위해 트랜잭션을 사용했습니다. 주문 테이블과 결제 테이블을 동시에 업데이트해야 했기 때문에, 중간에 오류가 발생하면 ROLLBACK을 수행하도록 처리했습니다."
❗️어렵게 생각할 필요 ❌. 이렇게 쉽게 대답하면 된다.
👉 답변 방향: MyBatis(SQL Mapper)와 JPA(ORM)의 차이점 및 본인의 경험을 설명
예시 답변:
"MyBatis는 SQL을 직접 작성할 수 있어 복잡한 쿼리를 최적화하기 쉽지만, 반복적인 SQL 코드가 많아질 수 있습니다. 반면 JPA는 객체와 테이블 매핑을 자동화하여 개발 속도를 높여주지만, 복잡한 SQL 최적화가 어려울 수 있습니다. 프로젝트에서 주어진 요구 사항에 따라 선택해야 한다고 생각합니다."
| 비교 항목 | MySQL | MariaDB |
|---|---|---|
| 라이선스 | Oracle 소유, 일부 기능이 유료(Enterprise) | 100% 오픈소스 |
| 성능 | 기본적인 성능은 유사하지만 일부 기능에서 느릴 수 있음 | InnoDB 성능 개선, 멀티쓰레딩 최적화 |
| 스토리지 엔진 | InnoDB, MyISAM 등 | 추가 엔진 지원(Aria, TokuDB, Spider 등) |
| 호환성 | 최신 기능이 MariaDB와 다를 수 있음 | MySQL과 높은 호환성 유지 |
📌공통점
▶ MariaDB는 MySQL의 오픈소스 대안으로, 성능과 확장성 면에서 개선된 버전이다.
| 비교 항목 | MySQL | PostgreSQL |
|---|---|---|
| 데이터 모델 | 관계형 데이터베이스(RDBMS) | 객체-관계형 데이터베이스(ORDBMS) |
| 확장성 | 읽기 성능 최적화 (레플리케이션 활용) | 쓰기 성능 우수 (멀티버전 동시성 제어, MVCC) |
| ACID 지원 | InnoDB 엔진 사용 시 지원 | 기본적으로 강력한 ACID 지원 |
| JSON 지원 | JSON 컬럼 지원 | JSONB(이진 JSON) 지원으로 성능 우수 |
| 트랜잭션 | 트랜잭션 지원(InnoDB) | 복잡한 트랜잭션 지원에 강함 |
▶ PostgreSQL은 대규모 데이터 처리, 복잡한 쿼리 최적화, JSON 데이터 활용이 필요한 경우 MySQL보다 적합하다.
| 비교 항목 | MySQL | Oracle DB |
|---|---|---|
| 라이선스 | 오픈소스 | 유료(Enterprise 버전) |
| 성능 | 중소형 시스템에 적합 | 대규모 엔터프라이즈 시스템에 최적화 |
| 스토리지 엔진 | InnoDB, MyISAM 등 | 자체적인 고성능 스토리지 엔진 사용 |
| 트랜잭션 | InnoDB 기반으로 트랜잭션 지원 | 고급 트랜잭션 기능(Flashback, Parallel Query) 제공 |
| 확장성 | 수직 확장(Replication, Sharding 가능) | 수직 및 수평 확장 모두 지원 |
▶ Oracle DB는 금융, 대기업 시스템 등 대규모 데이터 처리가 필요한 경우 적합하다.
| 비교 항목 | MySQL | MS SQL Server |
|---|---|---|
| 운영체제 지원 | Windows, Linux 등 다양함 | 주로 Windows 환경 최적화 |
| 라이선스 | 오픈소스 | 유료(Enterprise 버전) |
| 트랜잭션 | InnoDB 사용 시 강력한 트랜잭션 지원 | 트랜잭션 관리 기능이 강력함 |
| 통합 환경 | 다양한 애플리케이션과 연동 가능 | .NET 및 Microsoft 제품과 강력한 연동 |
| 성능 | 읽기 최적화 | 대규모 엔터프라이즈 환경에서 안정적 |
▶ MS SQL Server는 Windows 기반 엔터프라이즈 애플리케이션 개발에 최적화된 DBMS이다.
면접에서 MySQL을 다른 DBMS와 비교하는 질문이 나오면, 사용 목적과 특징에 따라 적절한 선택이 필요하다는 점을 강조하면 좋다.
SQL Mapper 프레임워크(SQL 쿼리와 객체를 매핑하는 도구 또는 기술)XML 또는 어노테이션을 사용하여 SQL 쿼리와 자바 객체를 매핑할 수 있도록 지원.*.xml 파일을 사용하여 SQL을 정의하는 방식. <mapper> 태그를 활용하여 SQL을 작성하고, Java 인터페이스와 연결. <if>, <choose> 등을 사용하여 SQL을 동적으로 변경 가능. <select id="getUserById" parameterType="int" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
<select id="findUsers" resultType="User">
SELECT * FROM users
WHERE 1=1
<if test="name != null">
AND name = #{name}
</if>
<if test="age != null">
AND age = #{age}
</if>
</select>
@Select, @Insert, @Update, @Delete 등의 어노테이션을 활용하여 SQL을 작성. @Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(int id);
public class UserSqlProvider {
public String findUsers(Map<String, Object> params) {
StringBuilder sql = new StringBuilder("SELECT * FROM users WHERE 1=1 ");
if (params.get("name") != null) {
sql.append("AND name = #{name} ");
}
if (params.get("age") != null) {
sql.append("AND age = #{age} ");
}
return sql.toString();
}
}
@Mapper
public interface UserMapper {
@SelectProvider(type = UserSqlProvider.class, method = "findUsers")
List<User> findUsers(@Param("name") String name, @Param("age") Integer age);
}
| 비교 항목 | XML 기반 SQL (<if>, <choose> 사용) | 어노테이션 기반 SQL (@SelectProvider 사용) |
|---|---|---|
| 동적 SQL 작성 | <if>, <choose>, <trim> 등 XML 태그 사용 | @SelectProvider를 활용하여 Java 코드에서 SQL 생성 |
| 유지보수성 | SQL이 XML 파일로 분리되어 관리 용이 | SQL이 Java 코드 내부에 포함되므로 복잡한 쿼리 작성 시 가독성이 떨어질 수 있음 |
| 가독성 | SQL과 Java 코드가 분리되어 명확 | Java 코드에서 SQL을 문자열로 처리해야 하므로 가독성 저하 |
| 복잡한 동적 쿼리 처리 | <if>, <foreach>, <set> 등을 활용하여 유연한 조건 처리 가능 | StringBuilder 등을 사용해야 하므로 유지보수 어려움 |
MyBatis에서 SQL을 실행하는 방식은 크게 ① SqlSession을 직접 사용하는 방식, ② @Mapper 인터페이스 기반 방식 두 가지가 있음.
| 비교 항목 | SqlSession을 직접 사용 | @Mapper 인터페이스 사용 |
|---|---|---|
| 코드 작성 방식 | SqlSession을 사용하여 직접 SQL 실행 | @Mapper 인터페이스를 선언하면 MyBatis가 자동으로 구현 |
| 유지보수성 | SQL 실행 코드가 많아짐 | 인터페이스만 선언하면 되므로 코드량 감소 |
| 유연성 | 동적으로 SQL을 조작하는데 유리 | 정적인 SQL 실행에 적합 |
| 사용 예시 | 동적 쿼리 생성, 트랜잭션 관리 등 직접 컨트롤할 때 사용 | CRUD와 같은 단순한 DB 작업 |
SqlSession을 직접 사용하는 방식 (직접 구현 방식)👉 SqlSession 객체를 활용하여 SQL을 실행하는 방식으로, SQL을 직접 호출하고 트랜잭션을 수동 관리할 수 있음.
public class UserDAO {
private final SqlSession sqlSession;
public UserDAO(SqlSession sqlSession) {
this.sqlSession = sqlSession;
}
public User getUserById(int id) {
return sqlSession.selectOne("UserMapper.getUserById", id);
}
public void insertUser(User user) {
sqlSession.insert("UserMapper.insertUser", user);
}
}
📌 특징:
✔ sqlSession.selectOne(), sqlSession.insert() 등을 사용하여 SQL을 직접 실행
✔ 트랜잭션을 직접 관리 가능 (sqlSession.commit(), sqlSession.rollback())
✔ 동적 SQL을 작성하기 쉽지만, 코드량이 많아질 수 있음
💡 언제 사용하면 좋을까?
@Mapper 인터페이스 기반 방식 (자동 제공 방식)👉 @Mapper 인터페이스를 선언하면 MyBatis가 자동으로 구현체를 생성하여 SQL을 실행할 수 있도록 해줌.
@Mapper 기반)@Mapper
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{id}")
User getUserById(@Param("id") int id);
@Insert("INSERT INTO users(name, age) VALUES (#{name}, #{age})")
void insertUser(User user);
}
📌 특징:
✔ @Mapper 인터페이스만 작성하면 MyBatis가 자동으로 구현체를 생성
✔ SQL 실행 코드가 간결하고 유지보수성이 향상됨
✔ 하지만, 복잡한 로직을 구현할 때는 한계가 있음
💡 언제 사용하면 좋을까?
SqlSession vs. @Mapper 방식 선택 기준| 선택 기준 | SqlSession 방식 | @Mapper 방식 |
|---|---|---|
| 코드량 | 많음 (직접 작성 필요) | 적음 (자동 생성) |
| 유지보수성 | SQL을 직접 관리해야 하므로 어려움 | 인터페이스만 관리하면 되므로 쉬움 |
| 트랜잭션 제어 | 직접 트랜잭션 관리 가능 | 스프링이 자동 관리 |
| 동적 SQL 작성 | 유리함 (SqlSession 활용) | 제한적 (복잡한 SQL은 XML 사용 필요) |
| 일반적인 CRUD | 불필요하게 복잡해질 수 있음 | 간단하고 효율적 |
✅ 단순한 CRUD 작업은 @Mapper 인터페이스 방식이 유지보수에 유리
✅ 복잡한 트랜잭션이나 동적 SQL 처리가 필요할 경우 SqlSession 방식이 더 적합
✅ 두 가지 방식을 혼용하여 필요에 따라 적절하게 선택하는 것이 중요
다음과 같이 4가지 방식(SQL Mapper의 XML 기반, 어노테이션 기반, SqlSession 방식, @Mapper 방식)을 적절하게 조합해서 사용해야 하는 이유와 함께 설명을 추가할게.
MyBatis를 활용할 때 SQL Mapper(XML 방식 & 어노테이션 방식)와 SQL 실행 방식(SqlSession & @Mapper 인터페이스 방식)을 각각 선택할 수 있음.
이 4가지 방식을 적절하게 조합하면 유지보수성과 유연성을 극대화할 수 있음.
1️⃣ 간단한 CRUD는 @Mapper + 어노테이션 기반 SQL을 활용
@Select, @Insert 등의 어노테이션을 사용하면 코드가 간결해지고 가독성이 향상됨. 2️⃣ 복잡한 동적 쿼리는 XML 기반 SQL Mapper를 사용
<if>, <foreach>, <choose> 등의 태그를 활용하면 가독성과 유지보수성이 뛰어난 동적 SQL 작성 가능. 3️⃣ 트랜잭션이 필요한 경우 SqlSession을 직접 활용
sqlSession.commit() 또는 sqlSession.rollback()을 통해 세밀한 트랜잭션 관리 가능. 4️⃣ 일반적인 SQL 실행은 @Mapper 인터페이스 기반으로 사용
@Mapper 인터페이스 기반 방식으로 해결 가능. | 시나리오 | 추천 조합 방식 | 설명 |
|---|---|---|
| 기본적인 CRUD | @Mapper + 어노테이션 기반 SQL | 코드량이 적고 가독성이 좋음. 단순한 SQL 처리에 적합. |
| 복잡한 동적 SQL | @Mapper + XML 기반 SQL Mapper | XML을 활용하면 동적 SQL의 유지보수성이 향상됨. |
| 트랜잭션이 필요한 경우 | SqlSession 직접 사용 + XML 기반 SQL | 트랜잭션을 세밀하게 관리해야 할 때 적합. |
| 고성능, 대량 데이터 처리 | SqlSession 직접 사용 + XML 기반 SQL | batch 처리, 커서 기반 조회 등 고성능 SQL 작업에 적합. |
✅ 단순한 SQL은 @Mapper + 어노테이션을 활용하고, 복잡한 SQL은 XML 기반 Mapper를 사용
✅ 트랜잭션이 필요한 경우 SqlSession을 직접 활용하여 제어
✅ 필요에 따라 @Mapper와 XML Mapper를 혼용하여 유연한 SQL 실행 가능