

1. DAO (Data Access Object)
- DAO๋ DB์ ์ง์ ํต์ ์ ํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ๊ฐ์ ธ์ค๋ ๊ฐ์ฒด์ด๋ค.
- ์ฌ์ฉ์ฒ : `MyBatis` ํน์ `JPA`์ ๊ฐ์ ORM์์ ์ค์ ๋ก DB ์ ๊ทผ์ ๋ด๋นํ๋ ๊ฐ์ฒด
- ํน์ง: ๋ณดํต ์ธํฐํ์ด์ค + Mapper (XML or ์ด๋ ธํ ์ด์ ๋ฐฉ์)์ผ๋ก ๊ตฌ์ฑ๋จ
์์ (MyBatis)
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface UserDAO {
// ์ฌ์ฉ์ ์ฝ์
@Insert("INSERT INTO users (username, email, password) VALUES (#{username}, #{email}, #{password})")
int insertUser(@Param("username") String username,
@Param("email") String email,
@Param("password") String password);
// ์ฌ์ฉ์ ID๋ก ์กฐํ
@Select("SELECT id, username, email FROM users WHERE id = #{id}")
UserEntity getUserById(@Param("id") int id);
}
์ด DAO๋ MyBatis๋ฅผ ์ฌ์ฉํ์ฌ users ํ
์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๊ณ , ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
์๋๋ UserDAO์ ์์ ์ฝ๋์
๋๋ค. ๋ ๊ฐ์ ๋ฉ์๋๋ฅผ ํฌํจํ์ฌ, ํ๋๋ ์ฌ์ฉ์๋ฅผ ์ฝ์
(insertUser), ๋ค๋ฅธ ํ๋๋ ID๋ก ์ฌ์ฉ์๋ฅผ ์กฐํ(getUserById)ํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
import org.apache.ibatis.annotations.Mapper;
@Mapper
public class UserDAO {
// ์ฌ์ฉ์ ์ฝ์
public int insertUser(UserInsertDto userInsertDto) {
return insert("insertUser", userInsertDto);
}
// ์ฌ์ฉ์ ์
๋ฐ์ดํธ
public int updateUser(UserUpdateDto userUpdateDto) {
return insert("updateUser", userUpdateDto);
}
}
2. DTO (Data Transfer Object)
ํด๋ผ์ด์ธํธ, ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ณผ์ ์์ ์ฌ์ฉํ๋ ๊ฐ์ฒด (Controller โ Service โ Client)์ด๋ค. DTO๊ฐ ์ ์ผ ๋ง์ ์ญํ ์ ์ํํ๋ค. ๊ทธ๋ฆฌ๊ณ DTO๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ ๊ฐ๋ฅํ๋ค (๊ฐ๋ณ) ๊ทธ๋์ @Setter ์ด๋ ธํ ์ด์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์ฌ์ฉ์ฒ: API ์๋ต/์์ฒญ์ ์ํ ๋ฐ์ดํฐ ํฌ๋งท์ ๋ง๋ค ๋ ์ฌ์ฉ
ํน์ง
- ์ผ๋ฐ์ ์ผ๋ก @JsonProperty ๋ฑ์ ์ฌ์ฉํด API ์๋ต ํ๋๋ฅผ ์ง์
- ๋ฐ์ดํฐ ๋ณํ ์ฉ๋๋ก ์ฌ์ฉ (Entity โ DTO ๋ณํ)
- Swagger์์๋ ์ฃผ๋ก DTO๊ฐ API ๋ฌธ์์์ ๋ ธ์ถ๋จ
- UserDto๋ ํ์ํ ๋ฐ์ดํฐ๋ง ํฌํจํ์ฌ API ๋ฌธ์ํ ์ ๋ถํ์ํ ํ๋๊ฐ ํฌํจ๋์ง ์๋๋ก ํ๋ค. (`swagger`๋ก `springdoc`์ ์ด์ฉํ๋ ๊ฒฝ์ฐ swagger์์ update.json ์ ํ์ ์๋ ์ปฌ๋ผ๋ค์ด ๋ณด์ด๋ ์์ธ ๊ด๋ จ)
ํ์๊ฐ์
DTO
// UserInsertDTO ํด๋์ค ์ถ๊ฐ
public class UserInsertDTO {
private String password;
private String userName;
private String userEmail;
private String userTel;
private int userAge;
public UserInsertDTO(String password, String userName, String userEmail,
String userTel, int userAge) {
this.password = password;
this.userName = userName;
this.userEmail = userEmail;
this.userTel = userTel;
this.userAge = userAge;
}
// Getter ๋ฐ Setter ์ถ๊ฐ
}
ํ์์ ๋ณด ์์ DTO ์ถ๊ฐ
// UserUpdateDTO ํด๋์ค ์ถ๊ฐ
public class UserUpdateDTO {
private String userName;
private String userEmail;
private String userTel;
private int userAge;
public UserUpdateDTO(String userName, String userEmail, String userTel, int userAge) {
this.userName = userName;
this.userEmail = userEmail;
this.userTel = userTel;
this.userAge = userAge;
}
// Getter ๋ฐ Setter ์ถ๊ฐ
}
์ด๋ ๊ฒ ํ์๊ฐ์
/ํ์์ ๋ณด ์์ ์ DTO๋ฅผ ๋ค๋ฅด๊ฒ ๊ตฌ์ฑํ๋ค๋ฉด ๋ถํ์ํ ๊ฐ์ด ๋ค์ด๊ฐ์ง ์๊ฒ ๋๋ค.
๊ฐ๊ฐ์ ์ฉ๋์ ๋ง๊ฒ DTO๋ฅผ ๊ตฌ๋ถํ๋ฉด Swagger์์ ๋ถํ์ํ ํ๋๊ฐ ๋ณด์ด์ง ์๋๋ค.
3. Entity
Entity๋ @Entity๋ก ํ์๋๊ณ , ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์ด๋ธ๊ณผ 1:1 ๋งคํ๋์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ&์กฐํํ ๋ ์ด์ฉ๋๋ ๊ฐ์ฒด์ด๋ค.
ORM (JPA, MyBatis)์์ DB ํ
์ด๋ธ๊ณผ ๋งคํํด์ ์์์ฑ ๊ด๋ฆฌ๋ฅผ ํ๋ค.
@Table, @Column ๋ฑ์ ์ด๋
ธํ
์ด์
์ผ๋ก DB์ ๋งคํํ๋ค.
ํ๋๊ฐ ๋ง์์ง ์ ์์ผ๋ฉฐ, API ์๋ต์ ๊ทธ๋๋ก ๋
ธ์ถ๋๋ฉด ๋ถํ์ํ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ์๋ ์๋ค. ๋น๋ฐ๋ฒํธ๋ ๊ฐ์ธ์ ๋ณด๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ํฌํจ๋ ์๊ฐ ์๋ค. Entity๋ JAP๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
Entity์์๋ ์ฃผ๋ก @Setter ์ด๋
ธํ
์ด์
๋ง๊ณ [updateUser]๋ฉ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์
๋ฐ์ดํธ ํ๋ค.
import jakarta.persistence.*;
import lombok.*;
@Entity
@Table(name = "user")
@Getter
// Protected User() {} JPA ๊ธฐ๋ณธ ์์ฑ์ ์๋ ์์ฑ
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String password;
private String userName;
private String userEmail;
private String userTel;
private int userAge;
// ์์ฑ์
public User(String password, String userName, String userEmail, String userTel, int userAge) {
this.password = password;
this.userName = userName;
this.userEmail = userEmail;
this.userTel = userTel;
this.userAge = userAge;
}
// Update ๋ฉ์๋ (Setter ๋์ ์ฌ์ฉ)
public void updateUser(String userName, String userEmail, String userTel, int userAge) {
this.userName = userName;
this.userEmail = userEmail;
this.userTel = userTel;
this.userAge = userAge;
}
}
4. VO (Value Object)
VO๋ ๊ฐ(๊ฐ์ฒด) ์์ฒด๋ก ์๋ฏธ๋ฅผ ๊ฐ์ง๋ฉฐ, ๋ด๊ธฐ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋ ๋ ์ฌ์ฉ๋๋ค. ๊ทธ๋์ ํน์ ๋๋ฉ์ธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ณ์ ๊ฐ์ฒด๋ก ์ฌ์ฉํ ๋ ์ฌ์ฉ๋๋ค. @Setter ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ง ์์ผ๋ฉฐ, ์์ฑ์๋ฅผ ํตํด์ ๊ฐ์ ์ด๊ธฐํํ๋ค. ํ ๋ฒ ์์ฑ์๋ฅผ ํตํด ๊ฐ์ด ์ด๊ธฐํ๋๋ฉด ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ด ๋ณด์ฅ๋๋ค.
- Email VO๋ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ ๊ฐ์ฒด๋ก, UserEntity์์ private Email email;๋ก ์ฌ์ฉ ๊ฐ๋ฅ
- Setter ์์ด ์์ฑ์์์๋ง ๊ฐ ์ค์ ๊ฐ๋ฅ (@AllArgsConstructor, @Getter ์ฌ์ฉ)
- VO๋ ์ฃผ๋ก ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ 1:1 ๋งคํ์ด ์ด๋ฃจ์ด์ง๋ค.
- ๊ทธ๋์ VO ๋ ์ฌ์ฉ์์๊ฒ ์กฐํ๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ๊ฐ์ ์ ๋ฌํ ๋ ์ด์ฉ๋๋ค.
- equals()์ hashCode()๋ฅผ ๋ฐ๋์ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ ์ ์๋๋ก ํจ.
*Entity: ํ ์ด๋ธ๊ณผ 1:1 ๋งคํ
*VO: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ 1:1 ๋งคํ (์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ VO์ ๋ด๊ธด๋ค)
5. Mybatis XML Mapper์์ DTO์ VO์ฌ์ฉ
`DTO`๋ `MyBatis XML Mapper` (UserMapper.xml)
์์1: Insert
public class UserInsertDTO {
private String userId;
private String password;
private String userName;
private String userEmail;
private String userTel;
private int userAge;
// ์์ฑ์
// Getter & Setter
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- ์ฌ์ฉ์ ๋ฑ๋ก -->
<insert id="insertUser" parameterType="com.example.dto.UserInsertDTO">
INSERT INTO users (user_id, password, user_name, user_email, user_tel, user_age)
VALUES (#{userId}, #{password}, #{userName}, #{userEmail}, #{userTel}, #{userAge})
</insert>
</mapper>
์์ 2: Update
public class UserUpdateDTO {
private String userId;
private String userName;
private String userEmail;
private String userPhone;
private int userAge;
// ์์ฑ์
// Getter & Setter
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.UserMapper">
<!-- ์ฌ์ฉ์ ์ ๋ณด ์
๋ฐ์ดํธ -->
<update id="updateUser" parameterType="com.example.dto.UserUpdateDTO">
UPDATE users
SET user_name = #{userName},
user_email = #{userEmail},
user_phone = #{userPhone},
user_age = #{userAge}
WHERE user_id = #{userId}
</update>
</mapper>
์์ 3: select
public class UserViewVO {
private String userID;
private String username;
private String email;
private String phone;
private int age;
// ์์ฑ์
// Getter ๋ง, no setter for immutability
<mapper namespace="com.example.UserViewMapper">
<!-- userID๋ก ํน์ ์ฌ์ฉ์ ์กฐํ -->
<select id="selectUserById" resultType="com.example.UserViewVO" parameterType="String">
SELECT user_id, username, email, phone, age
FROM user_view
WHERE user_id = #{userID}
</select>
<!-- ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ -->
<select id="selectAllUsers" resultType="com.example.UserViewVO">
SELECT user_id, username, email, phone, age
FROM user_view
</select>
</mapper>
6. equals()์ hashCode()
VO์์ equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํด์ผ ํ๋ ์ด์ ๋ ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ๊ธฐ ์ํด์์ด๋ค.
- `equals()`: ๋ ๊ฐ์ฒด์ ๊ฐ์ด ๊ฐ์ผ๋ฉด true๋ฅผ ๋ฐํํ๋๋ก ์ค๋ฒ๋ผ์ด๋
- `hashCode()`: ๋์ผํ ๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด๋ผ๋ฉด ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํ๋๋ก ์ค๋ฒ๋ผ์ด๋(HashSet, HashMap ๋ฑ ์ปฌ๋ ์ ์์ ์ค๋ณต์ ๋ฐฉ์งํ๋ ค๋ฉด ์ด๊ฒ๋ ์ค๋ฒ๋ผ์ด๋ฉ ํด์ผ ํ๋ค.)
๊ธฐ๋ณธ์ ์ผ๋ก Object ํด๋์ค์ equals()์ hashCode()๋ ๊ฐ์ฒด์ ์ฃผ์(์ฐธ์กฐ๊ฐ)๋ฅผ ๊ธฐ์ค์ผ๋ก ๋น๊ต๋ฅผ ํ๋ค.
ํ์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฑด ๊ฐ์ฒด์ ์์ฑ ๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ๋ ๊ฒ์ด๋ฏ๋ก ์ค๋ฒ๋ผ์ด๋๊ฐ ํ์ํ๋ค.
๋ง์ฝ์ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ์๋ ์ฝ๋๋ฅผ ๋ณด์.
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
}
public class Main {
public static void main(String[] args) {
User user1 = new User("Alice", 25);
User user2 = new User("Alice", 25);
System.out.println(user1.equals(user2)); // false (์ฃผ์๊ฐ ๋ค๋ฅด๋ฏ๋ก)
}
}
์๋ฅผ ๋ค์ด, ๊ฐ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ง ๋ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์์ ๋,
equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ธ์๋๋ค.
์ ์ฝ๋์์ user1๊ณผ user2๋ ๊ฐ์ name๊ณผ age ๊ฐ์ ๊ฐ์ง๊ณ ์์ง๋ง, equals()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ๋ค๋ฅด๊ฒ ํ๋จํ๋ค.
์ด์ equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํด ๋ณด์.
import java.util.Objects;
public class User {
private String name;
private int age;
public User(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true; // ๋์ผํ ์ฐธ์กฐ๊ฐ์ด๋ฉด true
if (obj == null || getClass() != obj.getClass()) return false;
User user = (User) obj;
return age == user.age && Objects.equals(name, user.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ์ ๊ฐ์ด๋ฉด ๋์ผํ ๊ฐ์ฒด๋ก ํ๋จํ๋ค.
public class Main {
public static void main(String[] args) {
User user1 = new User("Alice", 25);
User user2 = new User("Alice", 25);
System.out.println(user1.equals(user2)); // true (๊ฐ์ด ๊ฐ์์!)
}
}
์ hashCode()๋ ์ค๋ฒ๋ผ์ด๋ํด์ผ ํ ๊น? equals()๋ง ์ค๋ฒ๋ผ์ด๋ํ๋ฉด HashSet, HashMap ๊ฐ์ ์ปฌ๋ ์ ์์ ์ ๋๋ก ๋์ํ์ง ์๋๋ค. hashCode()๊ฐ ๋ค๋ฅด๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ผ๋ ํด์ ๊ธฐ๋ฐ ์๋ฃ๊ตฌ์กฐ์์ ๋ค๋ฅด๊ฒ ์ ์ฅ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ฅผ ๋ค์ด, HashSet์์ ๋์ผํ ๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด๊ฐ ์ค๋ณต๋์ง ์๊ฒ ํ๋ ค๋ฉด hashCode()๋ ๊ฐ์์ผ ํ๋ค.
public class Main {
public static void main(String[] args) {
Set<User> users = new HashSet<>();
users.add(new User("Alice", 25));
users.add(new User("Alice", 25));
System.out.println(users.size()); // 1 (์ค๋ณต ์ ์ฅ ๋ฐฉ์ง๋จ!)
}
}
'ํ๋ก๊ทธ๋๋ฐ์ธ์ด > Spring&JSP' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Swagger์ ๋ถํ์ํ ์ปฌ๋ผ์ด ๋ณด์ด๋ ์์ธ ๋ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ (2) | 2025.04.02 |
---|---|
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 12 _ ๋ถํธ์คํธ๋ฉ์ผ๋ก ๋ฉ์ธํ์ด์ง ๊พธ๋ฏธ๊ธฐ (106) | 2024.12.13 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 11 _ ๊ฒ์๊ธ ์์ , ์ญ์ ๊ธฐ๋ฅ (64) | 2024.12.13 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 11 _ ๊ฒ์ํ ๋ณด๊ธฐ ๊ธฐ๋ฅ (96) | 2024.12.09 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 10 _ ๊ฒ์ํ ๊ธ๋ชฉ๋ก ๊ธฐ๋ฅ (60) | 2024.12.09 |


1. DAO (Data Access Object)
- DAO๋ DB์ ์ง์ ํต์ ์ ํ๋ฉด์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ณ , ๊ฐ์ ธ์ค๋ ๊ฐ์ฒด์ด๋ค.
- ์ฌ์ฉ์ฒ :
MyBatis
ํน์JPA
์ ๊ฐ์ ORM์์ ์ค์ ๋ก DB ์ ๊ทผ์ ๋ด๋นํ๋ ๊ฐ์ฒด - ํน์ง: ๋ณดํต ์ธํฐํ์ด์ค + Mapper (XML or ์ด๋ ธํ ์ด์ ๋ฐฉ์)์ผ๋ก ๊ตฌ์ฑ๋จ
์์ (MyBatis)
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Insert; import org.apache.ibatis.annotations.Select; import org.apache.ibatis.annotations.Param; @Mapper public interface UserDAO { // ์ฌ์ฉ์ ์ฝ์
@Insert("INSERT INTO users (username, email, password) VALUES (#{username}, #{email}, #{password})") int insertUser(@Param("username") String username, @Param("email") String email, @Param("password") String password); // ์ฌ์ฉ์ ID๋ก ์กฐํ @Select("SELECT id, username, email FROM users WHERE id = #{id}") UserEntity getUserById(@Param("id") int id); }
์ด DAO๋ MyBatis๋ฅผ ์ฌ์ฉํ์ฌ users ํ
์ด๋ธ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์
ํ๊ณ , ID๋ฅผ ๊ธฐ๋ฐ์ผ๋ก ์ฌ์ฉ์๋ฅผ ์กฐํํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
์๋๋ UserDAO์ ์์ ์ฝ๋์
๋๋ค. ๋ ๊ฐ์ ๋ฉ์๋๋ฅผ ํฌํจํ์ฌ, ํ๋๋ ์ฌ์ฉ์๋ฅผ ์ฝ์
(insertUser), ๋ค๋ฅธ ํ๋๋ ID๋ก ์ฌ์ฉ์๋ฅผ ์กฐํ(getUserById)ํ๋ ๊ธฐ๋ฅ์ ์ํํฉ๋๋ค.
import org.apache.ibatis.annotations.Mapper; @Mapper public class UserDAO { // ์ฌ์ฉ์ ์ฝ์
public int insertUser(UserInsertDto userInsertDto) { return insert("insertUser", userInsertDto); } // ์ฌ์ฉ์ ์
๋ฐ์ดํธ public int updateUser(UserUpdateDto userUpdateDto) { return insert("updateUser", userUpdateDto); } }
2. DTO (Data Transfer Object)
ํด๋ผ์ด์ธํธ, ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฃผ๊ณ ๋ฐ๋ ๊ณผ์ ์์ ์ฌ์ฉํ๋ ๊ฐ์ฒด (Controller โ Service โ Client)์ด๋ค. DTO๊ฐ ์ ์ผ ๋ง์ ์ญํ ์ ์ํํ๋ค. ๊ทธ๋ฆฌ๊ณ DTO๋ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝ ๊ฐ๋ฅํ๋ค (๊ฐ๋ณ) ๊ทธ๋์ @Setter ์ด๋ ธํ ์ด์ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค.
์ฌ์ฉ์ฒ: API ์๋ต/์์ฒญ์ ์ํ ๋ฐ์ดํฐ ํฌ๋งท์ ๋ง๋ค ๋ ์ฌ์ฉ
ํน์ง
- ์ผ๋ฐ์ ์ผ๋ก @JsonProperty ๋ฑ์ ์ฌ์ฉํด API ์๋ต ํ๋๋ฅผ ์ง์
- ๋ฐ์ดํฐ ๋ณํ ์ฉ๋๋ก ์ฌ์ฉ (Entity โ DTO ๋ณํ)
- Swagger์์๋ ์ฃผ๋ก DTO๊ฐ API ๋ฌธ์์์ ๋ ธ์ถ๋จ
- UserDto๋ ํ์ํ ๋ฐ์ดํฐ๋ง ํฌํจํ์ฌ API ๋ฌธ์ํ ์ ๋ถํ์ํ ํ๋๊ฐ ํฌํจ๋์ง ์๋๋ก ํ๋ค. (
swagger
๋กspringdoc
์ ์ด์ฉํ๋ ๊ฒฝ์ฐ swagger์์ update.json ์ ํ์ ์๋ ์ปฌ๋ผ๋ค์ด ๋ณด์ด๋ ์์ธ ๊ด๋ จ)
ํ์๊ฐ์
DTO
// UserInsertDTO ํด๋์ค ์ถ๊ฐ public class UserInsertDTO { private String password; private String userName; private String userEmail; private String userTel; private int userAge; public UserInsertDTO(String password, String userName, String userEmail, String userTel, int userAge) { this.password = password; this.userName = userName; this.userEmail = userEmail; this.userTel = userTel; this.userAge = userAge; } // Getter ๋ฐ Setter ์ถ๊ฐ }
ํ์์ ๋ณด ์์ DTO ์ถ๊ฐ
// UserUpdateDTO ํด๋์ค ์ถ๊ฐ public class UserUpdateDTO { private String userName; private String userEmail; private String userTel; private int userAge; public UserUpdateDTO(String userName, String userEmail, String userTel, int userAge) { this.userName = userName; this.userEmail = userEmail; this.userTel = userTel; this.userAge = userAge; } // Getter ๋ฐ Setter ์ถ๊ฐ }
์ด๋ ๊ฒ ํ์๊ฐ์
/ํ์์ ๋ณด ์์ ์ DTO๋ฅผ ๋ค๋ฅด๊ฒ ๊ตฌ์ฑํ๋ค๋ฉด ๋ถํ์ํ ๊ฐ์ด ๋ค์ด๊ฐ์ง ์๊ฒ ๋๋ค.
๊ฐ๊ฐ์ ์ฉ๋์ ๋ง๊ฒ DTO๋ฅผ ๊ตฌ๋ถํ๋ฉด Swagger์์ ๋ถํ์ํ ํ๋๊ฐ ๋ณด์ด์ง ์๋๋ค.
3. Entity
Entity๋ @Entity๋ก ํ์๋๊ณ , ์ค์ ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ
์ด๋ธ๊ณผ 1:1 ๋งคํ๋์ด ๋ฐ์ดํฐ๋ฅผ ์ ์ฅ&์กฐํํ ๋ ์ด์ฉ๋๋ ๊ฐ์ฒด์ด๋ค.
ORM (JPA, MyBatis)์์ DB ํ
์ด๋ธ๊ณผ ๋งคํํด์ ์์์ฑ ๊ด๋ฆฌ๋ฅผ ํ๋ค.
@Table, @Column ๋ฑ์ ์ด๋
ธํ
์ด์
์ผ๋ก DB์ ๋งคํํ๋ค.
ํ๋๊ฐ ๋ง์์ง ์ ์์ผ๋ฉฐ, API ์๋ต์ ๊ทธ๋๋ก ๋
ธ์ถ๋๋ฉด ๋ถํ์ํ ๋ฐ์ดํฐ๊ฐ ํฌํจ๋ ์๋ ์๋ค. ๋น๋ฐ๋ฒํธ๋ ๊ฐ์ธ์ ๋ณด๊ฐ์ ๋ฏผ๊ฐํ ์ ๋ณด๊ฐ ํฌํจ๋ ์๊ฐ ์๋ค. Entity๋ JAP๋ฅผ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
Entity์์๋ ์ฃผ๋ก @Setter ์ด๋
ธํ
์ด์
๋ง๊ณ [updateUser]๋ฉ์๋๋ก ๋ฐ์ดํฐ๋ฅผ ์
๋ฐ์ดํธ ํ๋ค.
import jakarta.persistence.*; import lombok.*; @Entity @Table(name = "user") @Getter // Protected User() {} JPA ๊ธฐ๋ณธ ์์ฑ์ ์๋ ์์ฑ @NoArgsConstructor(access = AccessLevel.PROTECTED) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String password; private String userName; private String userEmail; private String userTel; private int userAge; // ์์ฑ์ public User(String password, String userName, String userEmail, String userTel, int userAge) { this.password = password; this.userName = userName; this.userEmail = userEmail; this.userTel = userTel; this.userAge = userAge; } // Update ๋ฉ์๋ (Setter ๋์ ์ฌ์ฉ) public void updateUser(String userName, String userEmail, String userTel, int userAge) { this.userName = userName; this.userEmail = userEmail; this.userTel = userTel; this.userAge = userAge; } }
4. VO (Value Object)
VO๋ ๊ฐ(๊ฐ์ฒด) ์์ฒด๋ก ์๋ฏธ๋ฅผ ๊ฐ์ง๋ฉฐ, ๋ด๊ธฐ๋ ๊ฐ์ด ๋ณ๊ฒฝ๋๋ฉด ์๋ ๋ ์ฌ์ฉ๋๋ค. ๊ทธ๋์ ํน์ ๋๋ฉ์ธ์์ ๋ฐ์ดํฐ๋ฅผ ๋ถ๋ณ์ ๊ฐ์ฒด๋ก ์ฌ์ฉํ ๋ ์ฌ์ฉ๋๋ค. @Setter ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํ์ง ์์ผ๋ฉฐ, ์์ฑ์๋ฅผ ํตํด์ ๊ฐ์ ์ด๊ธฐํํ๋ค. ํ ๋ฒ ์์ฑ์๋ฅผ ํตํด ๊ฐ์ด ์ด๊ธฐํ๋๋ฉด ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์๋ ๋ฐ์ดํฐ์ ๋ฌด๊ฒฐ์ฑ์ด ๋ณด์ฅ๋๋ค.
- Email VO๋ ๋ณ๊ฒฝ๋์ง ์๋ ๊ฐ ๊ฐ์ฒด๋ก, UserEntity์์ private Email email;๋ก ์ฌ์ฉ ๊ฐ๋ฅ
- Setter ์์ด ์์ฑ์์์๋ง ๊ฐ ์ค์ ๊ฐ๋ฅ (@AllArgsConstructor, @Getter ์ฌ์ฉ)
- VO๋ ์ฃผ๋ก ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ 1:1 ๋งคํ์ด ์ด๋ฃจ์ด์ง๋ค.
- ๊ทธ๋์ VO ๋ ์ฌ์ฉ์์๊ฒ ์กฐํ๋ ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ ๊ฐ์ ์ ๋ฌํ ๋ ์ด์ฉ๋๋ค.
- equals()์ hashCode()๋ฅผ ๋ฐ๋์ ์ค๋ฒ๋ผ์ด๋ํ์ฌ ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ ์ ์๋๋ก ํจ.
*Entity: ํ ์ด๋ธ๊ณผ 1:1 ๋งคํ
*VO: ์ฟผ๋ฆฌ ๊ฒฐ๊ณผ์ 1:1 ๋งคํ (์ฟผ๋ฆฌ ๊ฒฐ๊ณผ๊ฐ VO์ ๋ด๊ธด๋ค)
5. Mybatis XML Mapper์์ DTO์ VO์ฌ์ฉ
DTO
๋ MyBatis XML Mapper
(UserMapper.xml)
์์1: Insert
public class UserInsertDTO { private String userId; private String password; private String userName; private String userEmail; private String userTel; private int userAge; // ์์ฑ์ // Getter & Setter }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.UserMapper"> <!-- ์ฌ์ฉ์ ๋ฑ๋ก --> <insert id="insertUser" parameterType="com.example.dto.UserInsertDTO"> INSERT INTO users (user_id, password, user_name, user_email, user_tel, user_age) VALUES (#{userId}, #{password}, #{userName}, #{userEmail}, #{userTel}, #{userAge}) </insert> </mapper>
์์ 2: Update
public class UserUpdateDTO { private String userId; private String userName; private String userEmail; private String userPhone; private int userAge; // ์์ฑ์ // Getter & Setter }
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.example.mapper.UserMapper"> <!-- ์ฌ์ฉ์ ์ ๋ณด ์
๋ฐ์ดํธ --> <update id="updateUser" parameterType="com.example.dto.UserUpdateDTO"> UPDATE users SET user_name = #{userName}, user_email = #{userEmail}, user_phone = #{userPhone}, user_age = #{userAge} WHERE user_id = #{userId} </update> </mapper>
์์ 3: select
public class UserViewVO { private String userID; private String username; private String email; private String phone; private int age; // ์์ฑ์ // Getter ๋ง, no setter for immutability
<mapper namespace="com.example.UserViewMapper"> <!-- userID๋ก ํน์ ์ฌ์ฉ์ ์กฐํ --> <select id="selectUserById" resultType="com.example.UserViewVO" parameterType="String"> SELECT user_id, username, email, phone, age FROM user_view WHERE user_id = #{userID} </select> <!-- ๋ชจ๋ ์ฌ์ฉ์ ์กฐํ --> <select id="selectAllUsers" resultType="com.example.UserViewVO"> SELECT user_id, username, email, phone, age FROM user_view </select> </mapper>
6. equals()์ hashCode()
VO์์ equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํด์ผ ํ๋ ์ด์ ๋ ๋์ผํ ๊ฐ์ ๊ฐ์ง๋ ๊ฐ์ฒด๋ฅผ ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ๊ธฐ ์ํด์์ด๋ค.
equals()
: ๋ ๊ฐ์ฒด์ ๊ฐ์ด ๊ฐ์ผ๋ฉด true๋ฅผ ๋ฐํํ๋๋ก ์ค๋ฒ๋ผ์ด๋hashCode()
: ๋์ผํ ๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด๋ผ๋ฉด ๊ฐ์ ํด์์ฝ๋๋ฅผ ๋ฐํํ๋๋ก ์ค๋ฒ๋ผ์ด๋(HashSet, HashMap ๋ฑ ์ปฌ๋ ์ ์์ ์ค๋ณต์ ๋ฐฉ์งํ๋ ค๋ฉด ์ด๊ฒ๋ ์ค๋ฒ๋ผ์ด๋ฉ ํด์ผ ํ๋ค.)
๊ธฐ๋ณธ์ ์ผ๋ก Object ํด๋์ค์ equals()์ hashCode()๋ ๊ฐ์ฒด์ ์ฃผ์(์ฐธ์กฐ๊ฐ)๋ฅผ ๊ธฐ์ค์ผ๋ก ๋น๊ต๋ฅผ ํ๋ค.
ํ์ง๋ง ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฑด ๊ฐ์ฒด์ ์์ฑ ๊ฐ์ด ๊ฐ์ผ๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ก ํ๋จํ๋ ๊ฒ์ด๋ฏ๋ก ์ค๋ฒ๋ผ์ด๋๊ฐ ํ์ํ๋ค.
๋ง์ฝ์ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ์ด๋ค ์ผ์ด ์ผ์ด๋๋์ง ์๋ ์ฝ๋๋ฅผ ๋ณด์.
public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } }
public class Main { public static void main(String[] args) { User user1 = new User("Alice", 25); User user2 = new User("Alice", 25); System.out.println(user1.equals(user2)); // false (์ฃผ์๊ฐ ๋ค๋ฅด๋ฏ๋ก) } }
์๋ฅผ ๋ค์ด, ๊ฐ์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ๊ฐ์ง ๋ ๊ฐ์ ๊ฐ์ฒด๋ฅผ ๋ง๋ค์์ ๋,
equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์ธ์๋๋ค.
์ ์ฝ๋์์ user1๊ณผ user2๋ ๊ฐ์ name๊ณผ age ๊ฐ์ ๊ฐ์ง๊ณ ์์ง๋ง, equals()๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ์ง ์์ผ๋ฉด ๋ค๋ฅด๊ฒ ํ๋จํ๋ค.
์ด์ equals()์ hashCode()๋ฅผ ์ค๋ฒ๋ผ์ด๋ ํด ๋ณด์.
import java.util.Objects; public class User { private String name; private int age; public User(String name, int age) { this.name = name; this.age = age; } @Override public boolean equals(Object obj) { if (this == obj) return true; // ๋์ผํ ์ฐธ์กฐ๊ฐ์ด๋ฉด true if (obj == null || getClass() != obj.getClass()) return false; User user = (User) obj; return age == user.age && Objects.equals(name, user.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
์ด๋ ๊ฒ ํ๋ฉด ๊ฐ์ ๊ฐ์ด๋ฉด ๋์ผํ ๊ฐ์ฒด๋ก ํ๋จํ๋ค.
public class Main { public static void main(String[] args) { User user1 = new User("Alice", 25); User user2 = new User("Alice", 25); System.out.println(user1.equals(user2)); // true (๊ฐ์ด ๊ฐ์์!) } }
์ hashCode()๋ ์ค๋ฒ๋ผ์ด๋ํด์ผ ํ ๊น? equals()๋ง ์ค๋ฒ๋ผ์ด๋ํ๋ฉด HashSet, HashMap ๊ฐ์ ์ปฌ๋ ์ ์์ ์ ๋๋ก ๋์ํ์ง ์๋๋ค. hashCode()๊ฐ ๋ค๋ฅด๋ฉด ๊ฐ์ ๊ฐ์ฒด๋ผ๋ ํด์ ๊ธฐ๋ฐ ์๋ฃ๊ตฌ์กฐ์์ ๋ค๋ฅด๊ฒ ์ ์ฅ๋ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค. ์๋ฅผ ๋ค์ด, HashSet์์ ๋์ผํ ๊ฐ์ ๊ฐ์ง ๊ฐ์ฒด๊ฐ ์ค๋ณต๋์ง ์๊ฒ ํ๋ ค๋ฉด hashCode()๋ ๊ฐ์์ผ ํ๋ค.
public class Main { public static void main(String[] args) { Set<User> users = new HashSet<>(); users.add(new User("Alice", 25)); users.add(new User("Alice", 25)); System.out.println(users.size()); // 1 (์ค๋ณต ์ ์ฅ ๋ฐฉ์ง๋จ!) } }
'ํ๋ก๊ทธ๋๋ฐ์ธ์ด > Spring&JSP' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] Swagger์ ๋ถํ์ํ ์ปฌ๋ผ์ด ๋ณด์ด๋ ์์ธ ๋ฐ ํด๊ฒฐ ๋ฐฉ๋ฒ (2) | 2025.04.02 |
---|---|
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 12 _ ๋ถํธ์คํธ๋ฉ์ผ๋ก ๋ฉ์ธํ์ด์ง ๊พธ๋ฏธ๊ธฐ (106) | 2024.12.13 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 11 _ ๊ฒ์๊ธ ์์ , ์ญ์ ๊ธฐ๋ฅ (64) | 2024.12.13 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 11 _ ๊ฒ์ํ ๋ณด๊ธฐ ๊ธฐ๋ฅ (96) | 2024.12.09 |
[JSP] ๊ฒ์ํ ๋ง๋ค๊ธฐ 10 _ ๊ฒ์ํ ๊ธ๋ชฉ๋ก ๊ธฐ๋ฅ (60) | 2024.12.09 |