0206 ~ 0226
# 0206 ~ 0226
# 0214 - Thread dump์ Heap dump
๊ฐ๋ฐฉ์ฉ์ด๋ก์จ dump๋ ์์คํ ์ ์ ์ฅ๋ ์ ๋ณด๋ฅผ ๋ณต์ฌํ์ฌ ๋ฝ์ ๊ฒ. ๋๋ ๊ทธ์ ๊ฐ์์ผ๋ก ์ฐ์ธ๋ค. ์ผ์ข ์ snapshot ๊ฐ๋ ์ธ๋ฐ ์ฃผ๋ก ๋ถ์ ์ต์ ํ์ ๋ง์ด ์ฐ์ธ๋ค. DB dump, Thread dump ๋ฑ์ด ์๋ค.
# Thread Dump
- ํ๋ก์ธ์ค์ ์ํ ๋ชจ๋ thread๋ค์ ์ํ๋ฅผ ๊ธฐ๋กํ๊ฒ
- ์ฌ๊ธฐ์ ๋งํ๋ thread๋ค ์ค ์ผ๋ถ๋ JVM ๋ด๋ถ thread ์ด๊ณ ์ผ๋ถ๋ ์คํ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ thread์ด๋ค
- Thread dump๋ ๋ฐ์๋ ๋ฌธ์ ๋ค์ ์ง๋จ, ๋ถ์ํ๊ณ jvm ์ฑ๋ฅ์ ์ต์ ํํ๋๋ฐ ํ์ํ ์ ๋ณด๋ฅผ ๋ณด์ฌ์ค๋ค
- ์๋ฅผ ๋ค์ด Thread dump๋ ์๋์ผ๋ก ๋ฐ๋๋ฝ์ ํ์ํ๋ค
๋ฐ๋๋ฝ์ด๋? ์ด์์ฒด์ ํน์ ์ํํธ์จ์ด์ ์๋ชป๋ ์์ ๊ด๋ฆฌ๋ก ์ธํ์ฌ ๋ ์ด์์ ํ๋ก์ธ์ค(์ฌํ๋ฉด ์ด์์ฒด์ ์์ฒด๋ ํฌํจ)๊ฐ ํจ๊ป ๋ฉ์ถ์ด ๋ฒ๋ฆฌ๋ ํ์์ ๋งํ๋ค
์ฐ๋ฆฌ๋๋ผ ๋ง๋ก ๊ต์ฐฉ์ํ๋ผ๊ณ ํ๋ค
๋ฐ๋๋ฝ์ ๋ ๊ฐ ์ด์์ Thread์์ ์์ ์ ์๋ฃํ๊ธฐ ์ํด ์๋์ ์์ ์ด ๋๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฐ๋ค
# Heap Dump
- ํน์ ์์ ์ JVM heap ์์ญ์ ์๋ ๋ชจ๋ ๊ฐ์ฒด์ ์ค๋ ์ท
- ์ผ๋ฐ์ ์ผ๋ก ์๊ณ ์๋ JVM ๊ตฌ์กฐ์์ heap ์์ญ์ ์๊ฐํ๋ฉด ๋๋ค
- GC๊ฐ ํ์์ ๋ถํ์ํ ๊ฐ์ฒด๋ฅผ ์ ๊ฑฐํ์ง ๋ชปํ๋๊ฒฝ์ฐ Java VisualVM์ ์ฌ์ฉํ์ฌ ํด๋น ๊ฐ์ฒด์ ๋ํ ์ ๋ณด๋ฅผ ์ป์ด๋ผ ์ ์
# [ Heap Dump ๋ ๋ณด๊ธฐ ]
# ์ค์๊ฐ ๋ถ์ํ๊ธฐ
jmap -heap <PID>
# ํ์ผ๋ก ์ถ๋ ฅํ๊ธฐ
jmap -dump:format=b,file=<FILE_OUTPUT> <PID>
2
3
4
5
# 0222 - @Transient
@Transient๋ ์ํฐํฐ ๊ฐ์ฒด์ ๋ฐ์ดํฐ์ ํ ์ด๋ธ์ ์ปฌ๋ผ๊ณผ ๋งคํํ๊ณ ์๋ ๊ด๊ณ๋ฅผ ์ ์ธํ๊ธฐ ์ํด ์ฌ์ฉํ๋ค.
@Entity
public class Member{
@Id
private Long id; // PK
private String userId; // ์ฌ์ฉ์ ์์ด๋
private String password; // ๋น๋ฐ๋ฒํธ
private String confirmPassword; // ๋น๋ฐ๋ฒํธ ์ฌ์
๋ ฅ
}
2
3
4
5
6
7
8
@Entity
public class Member{
@Id
private Long id;
private String userId;
private String password;
// [1] @Transient ์ ์ธ
javax.persistence.@Transient
private String confirmPassword; // ๋น๋ฐ๋ฒํธ ์ฌ์
๋ ฅ ๋งคํ ์ ์ธ
}
2
3
4
5
6
7
8
9
10
11
# @Transient ์ดํด
@Transient๋ JPA์ ํ์ค์ด๋ผ ํ ์ ์๋ javax.persistence ํจํค์ง์ ํฌํจ๋์ด์๋ ์ปฌ๋ผ์ ์ ์ธํ๊ธฐ(์์ ๋์์์ ์ ์ธ ์ํค๊ธฐ) ์ํด ์ฌ์ฉํ๋ ์ปฌ๋ผ ๋งคํ ๋ ํผ๋ฐ์ค ์ ๋ ธํ ์ด์ ์ด๋ค.
package javax.persistence;
@Target({ElementType.METHOD, ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Transient {}
2
3
4
@Transient๋ ๋ฉ์๋์ ํ๋์ ์ ์ธํ ์ ์๊ณ @Entity ํด๋์ค๋ฟ๋ง์๋๋ผ @MappedSuperclass, @Embeddable ํด๋์ค์ ํ๋๋ getter ๋ฉ์๋์ ์ ์ธํ ์ ์๋ค.
Specifies that the property or field is not persistent. It is used to annotate a property or field of an entity class, mapped superclass, or embeddable class. -ย Oracle Doc - @Transient (opens new window)
# [ ์์ ๋์์์ ์ ์ธ ]
๋ฌด์๋ณด๋ค ์์(persistence)์ด๋ผ๋ ๊ฐ๋
์ JPA์ ๊ฐ์ฅ ๊ทผ๊ฐ์ด ๋๋ ๊ฐ๋
์ด๋ค. ๋ค์ ๋งํด JPA์์ ์์์ฑ ์ปจํ
์คํธ(Persistence context)๋ผ๋ ๋
ผ๋ฆฌ์ ์ธ ํจ๋ฌ๋ค์์ ๊ตฌํ์ฒด๋ผ ํ ์ ์๋ ์ํฐํฐ ๋งค๋์ (Entity Manager)๊ฐ ์กด์ฌํ๊ณ , ์ด ์ํฐํฐ ๋งค๋์ ์์ @Entity ๊ฐ์ฒด๋ฅผ ๊ด๋ฆฌํ๊ฒ ๋๋ค.
์ํฐํฐ ๊ฐ์ฒด์ ์ํ๊ฐ ์์ ์ํ(managed, persistent state)์ผ ๋, ๋น๋ก์ ์ํฐํฐ ๋งค๋์ ์ ์ํด ๊ด๋ฆฌ๋๋ค. ์์ ์ํ์ ์ํฐํฐ ๊ฐ์ฒด๋ ์ํฐํฐ ๋งค๋์ ์ ์ํด [1]
๋ณํ์ ๋ํ ์๋ ๊ฐ์ง(Dierty Checking), [2]
CRUD SQL ์๋ ์์ฑ ์์
๋ฐ ๊ทธ์ธ ์ผ๋ จ์ ๋ชจ๋ JPA์ ๋ด๋ถ์ ์ธ ๋์ ํ๋ก์ธ์ค์์ ํ์ฉ๋๋ค.
ํ์ง๋ง ์์ ๋์์์ ์ ์ธ๋๋ค๋ฉด, ๋๋ ํด๋น ํ๋๋ ๋ฉ์๋๋ ์ํฐํฐ ๋งค๋์ ์ ๊ด๋ฆฌ ๋์์์ ์ ์ธ๋จ์ ์๋ฏธํ๋ค. ์ฆ ํด๋น ํ๋์ ๋ํด @Transient ์ ๋
ธํ
์ด์
์ ์ ์ธํ๊ฒ ๋๋ฉด ์์ ๋์์์ ์ ์ธ๋์ด ์์ ์ค๋ช
ํ [1, 2]
์์
๋ค์ ์ํํ์ง ์๋๋ค. ์ด๋ฌํ ๊ฒฐ๊ณผ๋ฅผ ํ ๋๋ก "ํ
์ด๋ธ์ ์ปฌ๋ผ๊ณผ ๋งคํ์ ํ์ง ์๋๋ค."๋ผ๊ณ ์ดํดํด๋ ๋ฌด๋ฐฉํ๋ค.
# @Transient ๊ฐ๋จํ ์์์ ์ฌ์ฉ๋ฒ
@Entity
public class Product {
@Id
private Long id;
private String name;
private BigDecimal price;
private boolean isEvent;
// ^-- ์์ ์ ์ธ ๋์
public void runEventProcess(){
if(isEvent){
// ... ์ด๋ฒคํธ ๋ก์ง ์ํ
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
isEnvent
ํ๋์ ๊ฒฝ์ฐ Hokking ๋ชฉ์ ์ผ๋ก ํน์ ๋ ์ง๋ ์๊ฐ์ด ๋๋ฉด ํ์ฑํ(true)๋์ด, ์ํ ๊ฐ๊ฒฉ์ ๋ํ ํ ์ธ์จ ์ ์ฉ๊ณผ ๊ฐ์ ์ํ์ ๋ํ ์ด๋ฒคํธ ๋ก์ง์ ์ ์ฉ ์ํค๊ธฐ ์ํจ์ด๋ค.
์ด์ฒ๋ผ ํน์ ํ๋์ ๋ํด ํด๋์ค์์๋ง ์ฌ์ฉ๋๊ณ , ํ ์ด๋ธ ์ปฌ๋ผ์ผ๋ก ๊ด๋ฆฌํ๊ณ ์ถ์ง ์์ ๊ฒฝ์ฐ์ ์ฌ์ฉํ๋ค.
Hibernate:
create table product (
id bigint not null,
is_event boolean not null, <-- ์์ ์ ์ธ ๋์
name varchar(255),
price decimal(19,2),
primary key (id)
)
2
3
4
5
6
7
8
# [ @Transient ๋ ๊ฐ์ง ๋ฐฉ์ ]
@Transient ์ ๋ ธํ ์ด์ ์ ๋ ๊ฐ์ง ๋ฐฉ์์ ํตํด ์ ์ธํ ์ ์๋๋ก ์ ๊ณตํ๊ณ ์๋ค.
- ElementType.FIELD
@Entity
public class Product{
@Id
private Long id;
private String name;
private BigDecimal price;
@Transient
private boolean isEvent;
// ^-- ํด๋น ํ๋ ์์ ์ ์ธ ๋์
}
2
3
4
5
6
7
8
9
10
- ElementType.METHOD
@Entity
public class Product{
private Long id;
private String isEvent;
@Id @GeneratedValue
public Long getId(){ return this.id; }
public void setId(Long id){ this.id = id; }
// ^-- @GeneratedValue๋ JPA์ ๋ด๋ถ์ ์ธ ํ๋ก์ธ์ค์ ์ํด
// setter ๋ฉ์๋๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ์
ํ
ํ๊ธฐ ๋๋ฌธ์ ๊ตฌ์ฑํจ
@Transient // <-- ํด๋น ๋ฉ์๋ ์์ ์ ์ธ ๋์
public String getIsEventProduct(){ return this.isEvent; }
}
2
3
4
5
6
7
8
9
10
11
12
13
๋ค์ ์ฝ๋๋ ํ๋ ๋ฐฉ์๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ์ํํ๊ฒ ๋๋ค. ์ฃผ์ํ ์ ์ setter ๋ฉ์๋๊ฐ ์๋, getter ๋ฉ์๋์ ์ ๋ ธํ ์ด์ ์ ์ ์ธํด์ค์ผ ํ๋ค.
# ๋ฉ์๋/ํ๋ ๋ฐฉ์์ ์ง์ํ๋ JPA ์ ๋ ธํ ์ด์ ์ ์ฃผ์์ฌํญ
# [ ๊ฐ๋ฐ ์๋์๋ ๋ค๋ฅด๊ฒ ๋์ํ๋ JPA ]
@Entity
public class Member{
@Id
private Long id;
private String userId;
private String password;
private String confirmPassword;
@Transient // <-- ๋ฌธ์ ๊ฐ ๋๋ ๋ถ๋ถ
public String getComfirmPassword(){ return this.confirmPassword; }
}
2
3
4
5
6
7
8
9
10
11
- confirmPassword ํ๋๋ฅผ ์์ ๋์์์ ์ ์ธํ๋ค.
- getComfirmPassword() ๋ฉ์๋์ @Trasient ์ ๋ ธํ ์ด์ ์ ์ธ
- ๊ธฐ๋ํ๋ ๊ฒฐ๊ณผ -> ํ ์ด๋ธ ์ปฌ๋ผ ์์ฑ ๋ฐ CRUD SQL๋ฌธ ๋์ ์ปฌ๋ผ ์ ์ธ
Hibernate:
create table member (
id bigint not null,
user_id varchar(255),
password varchar(255),
confirm_password varchar(255), <-- ํ์ง๋ง ์์ ๋์์์ ์ ์ธ๋์ง ์์
primary key (id)
)
2
3
4
5
6
7
8
ํ์ง๋ง ์ค์ ์ฝ๋๋ ๋ค๋ฅด๊ฒ ๋์๋๋ค.
# [ ๋ฌธ์ ์ ์์ธ ํ์ - ์ํฐํฐ ์ ๊ทผ ๋ฐฉ์์ ๋ํ ์ดํด ]
JPA ์คํ์ ๋ฐ๋ฅด์๋ฉด, JPA๋ ๋ ๊ฐ์ง ๋ฐฉ์์ ํตํด ์์ ์ํ(managed, persistent state)์ธ ์ํฐํฐ ๊ฐ์ฒด์ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ค.
- ํ๋กํผํฐ ๋ฐฉ์(getter/setter Method, JavaBeans Property ์คํ์ผ)
- ํ๋ ๋ฐฉ์(Instance Fileds)
JPA 1.0(JSR 220) (opens new window)
JPA 2.0(JSR 317) (opens new window)
JPA 2.1(JSR 338) (opens new window)
// [1] ํ๋ ๋ฐฉ์
@Entity
public class Member{
@Id
private Long id;
private String name;
...
}
// [2] ๋ฉ์๋ ๋ฐฉ์
@Entity
public class Member{
private Long id;
private String name;
@Id
public Long getId(){return this.id;}
public void setId(Long id){this.id = id;}
public String getName(){return this.name;}
public void setName(String name){this.name = name;}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
JPA์ ๋ ๊ฐ์ง ์ ๊ทผ ๋ฐฉ์ ์ค ์ ํํ์ฌ ๊ฐ๋ฐํ ์ ์๋๋ก, ํ๋ ๋ ๋ฒจ์ ์ ์ธ์ํฌ ์ ์๋ ๋ชจ๋ JPA์ ์ ๋ ธํ ์ด์ ๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก Property ๋ฐฉ์์ ์ง์ํ๊ธฐ ์ํด ๋ฉ์๋ ๋ ๋ฒจ์ ์ง์ํ๋ค.
์ฌ๊ธฐ์ ์ค์ํ ํต์ฌ์ ์ค๊ณ ๋ฐฉ์์ ๋ฐ๋ผ JPA๋ ์ํฐํฐ ๊ฐ์ฒด์ ์ ๊ทผ ๋ฐฉ์์ด ๋ค๋ฅด๊ฒ ๊ฒฐ์ ๋๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก ์ํฐํฐ ๋งค๋์ ์ 1์ฐจ ์บ์๋ Map<@Id, @Entity>
ํํ๋ก ์ค๊ณ๋์ด key์ ํด๋นํ๋ @Id์ value์ ํด๋นํ๋ ์ํฐํฐ ๊ฐ์ฒด๋ฅผ ์ ์ฅํ์ฌ ๊ด๋ฆฌํ๋ค.
๊ฒฐ๊ณผ์ ์ผ๋ก JPA์ ์ํฐํฐ์ ์ ๊ทผ ๋ฐฉ์์ @Id ์ ๋ ธํ ์ด์ ์ ์์น์ ์ํด ๊ฒฐ์ ๋๋ฉฐ, ์ํฐํฐ์ ๋ชจ๋ ํ๋ ๋๋ ์์๋ ์ํฐํฐ์ ๊ณ์ธต์ ๋ํด์๋ ์ผ๊ด์ฑ ์๊ฒ ์ ์ฉํด์ค์ผ ํ๋ค.
์ํฐํฐ์ ๊ณ์ธต์ ๋ํด์๋ ์ผ๊ด์ฑ ์๊ฒ ์ ์ฉํด์ค์ผ ํฉ๋๋ค.
@Entity
public class Member{
@Id // ํ๋ ๋ฐฉ์
private Long id;
private String userId;
private String password;
private String confirmPassword;
@Transient // JPA์์ ์ธ์ ๋ถ๊ฐ โ ๋์ ์ํจ
public String getComfirmPassword(){ return this.confirmPassword; }
}
2
3
4
5
6
7
8
9
10
11
12
13
๋ฐ๋ผ์ ๋ค์ ๋ฌธ์ ๊ฐ ๋ ์ํฐํฐ ๊ตฌ์กฐ์์ @Id ์ ๋ ธํ ์ด์ ์ ์์น๊ฐ ํ๋์ ์์ผ๋ฏ๋ก JPA๋ ํ๋ ์ ๊ทผ ๋ฐฉ์์ ๋ฐ๋ฅด๊ฒ ๋๋ค. ์ด๋ฌํ ์ด์ ๋ก confirmPassword ํ๋๋ ์์ ๋์์์ ์ ์ธ๋์ง ์๋๋ค.
# [ ์ ๋ฆฌ ]
- @Transient๋ ์์ ๋์์์ ์ ์ธํ๋ค.
- JPA ์ปฌ๋ผ ๋งคํ ๋ ํผ๋ฐ์ค ์ ๋ ธํ ์ด์ ์ Filed, Property ๋ฐฉ์์ ์ง์ํ๊ธฐ ์ํด ํ๋์ ๋ฉ์๋์ ์ ์ธํ ์ ์๋ค.
- ์ปฌ๋ผ ๋งคํ ๋ ํผ๋ฐ์ค ์ ๋
ธํ
์ด์
์ ์ฌ์ฉํ ๋ JPA์ ์ํฐํฐ ์ ๊ทผ ๋ฐฉ์์ ์ดํด๋ณด์.
- @Id ์ ๋ ธํ ์ด์ ์ ์์น๋ฅผ ๋ณด์.(@Access ์ ๋ ธํ ์ด์ ์ผ๋ก ์ ๊ทผ ๋ฐฉ์์ ์ฌ์ ์ํ์ง ์๋ ์ด์)
- QueryDSL ๋ํ JPA์ ์ํฐํฐ ์ ๊ทผ ๋ฐฉ์์ ๊ธฐ์ค์ผ๋ก QDomain ํด๋์ค๋ฅผ ์์ฑํ๋ค.
- ๋ํ, @Transient ์ ๋ ธํ ์ด์ ์ด ์ ์ธ๋ ํ๋๋ ๋ฉ์๋๋ QDomain ํด๋์ค์ย ์ฟผ๋ฆฌ ํ์ ์์ฑ๊ณผ์ ์์ ์ ์ธ๋๋ค.
# 0224 - Instant vs LocalDateTime
# Instant
- Instant ํด๋์ค๋ ๋จ์ด์ ์๋ฏธ์ ๊ฐ์ด ์๊ฐ, ์ฆ์๋ฅผ ์๋ฏธํ๋ค.
- ์ปดํจํ
์ ํ๊ธฐ ์ํด Timestamp๋ก ๊ธฐ์ ์ ์ธ ํํ์ ํ ๊ฒ.
- ์ฆ, ์ธ๊ฐ๋ณด๋ค๋ ๊ธฐ๊ณ์ ์นํ์ ์ด๋ค.
- long ํํ๋ก Unix Timestamp๋ฅผ ์ ์ฅํ๊ธฐ ๋๋ฌธ์ ์ฐ์ฐ์ด ๋น ๋ฅด๋ค.
- Unix Timestamp ๋
Year 2038 problem
๋ฌธ์ ๊ฐ ์์ด ์ด๋ฅผ ๋ณด์ํ ๊ฒ์ด Instant ํด๋์ค์ด๋ค. - ์ง์ ๋ฒ์
MIN_SECOND
ย =ย-10000000-01-01T00:00Z
MAX_SECOND
ย =ย1000000000-12-31T23:59:59.99999999Z
private static final long MIN_SECOND = -31557014167219200L;
private static final long MAX_SECOND = 31556889864403199L;
2
- ๊ฐ์ฒด ์์ฑ
Instant now = Instant.now();
println(now);
// 2022-08-08T16:09:17.105081Z -- 2022๋
08์ 09์ผ 01์ 09๋ถ 17์ด
2
3
- ๋๋ ธ์ด๊น์ง ํํ ๊ฐ๋ฅ(๋ค์ Z๋ฅผ ํํํจ)
- Timestamp๋ ๋ณธ๋ longํ์ ์ด๋ค. toString()์ ์ฌ์ ์ ํจ.
public static Instant now(){
return Clock.currentInstant();
}
public abstract class Clock {
private static final long OFFSET_SEED = System.currentTimeMillis() / 1000 - 1024;
private static long offset = OFFSET_SEED;
// ์์คํ
์ ํ์ฌ ์๊ฐ์ ๊ฐ์ ธ์จ๋ค ๋๋
ธ์ด๋ก ๊ฐ์ ธ์ค๋ ๊ฒ์ ๋ฐ๋ฆฌ์ด๋ก ํํํด์ค๋ค.
static Instant currentInstant() {
long localOffset = offset;
long adjustment = VM.getNanoTimeAdjustment(localOffset);
// ๋ฐ๋ฆฌ์ด๋ฅผ ๋๋
ธ์ด๋ก ๋ณํํด์ ๊ฐ์ ธ์จ๋ค
...
return Instant.ofEpochSecond(localOffset, adjustment);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# LocalDateTime
- LocalDateTime์ ๋ ์ง + ์๊ฐ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ ์๋ค. Timezone์ด ์๋ค.
- LocalDateTime์ ์ธ๊ฐ์๊ฒ ์นํ์ ์ธ ํ์
- LocalDateTime์ ํ์ฌ ๋ก์ปฌ ์๊ฐ์ ๋ง์ถฐ์ ์๊ฐ์ ํํ
LocalDateTime now = LocalDateTime.now();
println(now);
// 2022-08-09T01:09:17.113332 2022๋
08์ 09์ผ 01์ 09๋ถ 17์ด
2
3
- ์ธ์คํด์ค์ Tiemzone ๊ธฐ๋ฐ์ผ๋ก Offset์ ์์ฑํ ํ ํ์ฌ ์์ ๊ธฐ์ค์ผ๋ก LocalDate, LocalTime ๊ฐ์ฒด๋ฅผ ์์ฑ ํ LocalDateTime์ ์์ฑํ๋ค.
public final class LocalDateTime {
public static LocalDateTime now() {
return now(Clock.systemDefaultZone());
}
}
public static Clock systemDefaultZone() {
// ์์คํ
์ ZoneId๋ฅผ ๊ฐ์ ธ์จ๋ค
return new SystemClock(ZoneId.systemDefault());
}
public static LocalDateTime now(Clock clock) {
Objects.requireNonNull(clock, "clock");
final Instant now = clock.instant();
// ZoneId๋ฅผ ๊ธฐ๋ฐ์ผ๋ก Offset ์ ๋ณด๋ฅผ ๊ฐ์ ธ์จ๋ค.
ZoneOffset offset = clock.getZone().getRules().getOffset(now);
return ofEpochSecond(now.getEpochSecond(), now.getNano(), offset);
}
public static LocalDateTime ofEpochSecond(long epochSecond, int nanoOfSecond, ZoneOffset offset) {
Objects.requireNonNull(offset, "offset");
NANO_OF_SECOND.checkValidValue(nanoOfSecond);
long localSecond = epochSecond + offset.getTotalSeconds();
long localEpochDay = Math.floorDiv(localSecond, SECONDS_PER_DAY);
int secsOfDay = Math.floorMod(localSecond, SECONDS_PER_DAY);
LocalDate date = LocalDate.ofEpochDay(localEpochDay);
LocalTime time = LocalTime.ofNanoOfDay(secsOfDay * NANOS_PER_SECOND + nanoOfSecond);
return new LocalDateTime(date, time);
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# [ LocalDateTime์ ์ฌ์ฉ ํ์ ๋ ๋ฌธ์ ์ ]
- ๊ธ๋ก๋ฒ ํ๊ฒฝ์ ๊ฒฝ์ฐ UTC๋ฅผ ๋ฐ๋ก ์ค์ ํด ์ฃผ์ง ์๋ ์ด์ ๊ฐ๊ฐ Timezone์ ๋ง์ถฐ ๋ฐ์ดํฐ๊ฐ ์์ฑ๋๋ค.
# [ ์ด๋ค ์ํฉ์ ์ฌ์ฉํ๋ ๊ฒ์ด ์ ํฉํ ๊น ]
- Timestamp๋ฅผ UTC ํ์์ผ๋ก ์ ์ฅํ๋ ๊ณณ ์ฆ DB, ๋ฐฑ์๋ ๋น์ฆ๋์ค ๋ก์ง, ๋ฐ์ดํฐ ๊ตํ, ์ง๋ ฌํ ์๋๋ฆฌ์ค์ ์ ํฉํ๋ค.(์ฐ์ฐํ๊ธฐ ์ฌ์)
- ๊ธ๋ก๋ฒ ๋ฐ์นญํ ์๋น์ค ๋น์ฆ๋์ค ์ฑ ๊ฐ๋ฐ ์ Instant ๋ ZonedDateTime ํด๋์ค๋ฅผ ๋ง์ด ์ฌ์ฉ