์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” EntityGraph์˜ ์‚ฌ์šฉ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๋ ค๊ณ  ํ•œ๋‹ค.

Entity๊ตฌ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

@Entity
class Team(
    var title: String,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB์—์„œ ์ž๋™์œผ๋กœ ID increment
    @Column(name = "team_id")
    var id: Long = 0L
    
    // Onwer Entity๋ฅผ Player๋กœ ์ง€์ •, Lazy type fetch, Persistence ์ „์ด ํƒ€์ž…
    @OneToMany(mappedBy="team", cascade=[CascaseType.ALL], fetch = FetchType.LAZY) 
    var players : MutableList<Player> = mutableListOf()
}

@Entity
class Player(
    var name : String,
    
    @ManyToOne
    @JoinColumn(name = "team_id") // ์™ธ๋ž˜ํ‚ค ๋งคํ•‘์„ ์œ„ํ•œ ์„ค์ •
    var game: Game
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB์—์„œ ์ž๋™์œผ๋กœ ID increment
    @Column(name = "player_id")
    var id: Long = 0L
    
    var count : Long
}

Game <--> Player ์—”ํ‹ฐํ‹ฐ๊ฐ€ 1:N์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค.

ํ˜„์žฌ Team์˜ players๋Š” LAZY type์œผ๋กœ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋˜์–ด์žˆ๋Š”๋ฐ,

ํ•˜๋‚˜์˜ team.players ์กฐํšŒ์‹œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด 2๊ฐœ์˜ query๊ฐ€ ์ƒ์„ฑ๋œ๋‹ค.

select 
team0_.team_id as team_id1_3_0_, 
team0_.name as name2_3_0_ 
from 
team team0_ 
where 
team0_.team_id=?

select 
players0_.team_id as team_id4_1_0_, 
players0_.player_id as player_i1_1_0_, 
players0_.player_id as player_i1_1_1_, 
players0_.count as count2_1_1_, 
players0_.name as name3_1_1_, 
players0_.team_id as team_id4_1_1_ 
from 
player players0_ 
where 
players0_.team_id=?

๋‹ค๋ฅธ ์‚ฌ๋žŒ๋“ค์˜ ๊ธ€๋“ค์„ ๋ณด๋‹ˆ, ์—ฌ๊ธฐ์—์„œ N + 1๊ฐœ์˜ Query๋ฌธ์ด ๋ฐœ์ƒํ•œ๋‹ค๊ณ  ํ•˜๋˜๋ฐ,

Fetch type์„ EAGER, LAZY๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ๋‹ค๋ฅธ ์˜ต์…˜๋“ค์„ ๋งŒ์ ธ๋ณด์•„๋„

Query๋ฌธ์€ ๋™์ผํ•˜๊ฒŒ 2๊ฐœ๋งŒ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

(์•„์ง JPA ORM๊ณผ ์นœ์ˆ™ํ•˜์ง€ ์•Š์•„์„œ ๋ชป๋‹ค๋ฃจ๋Š” ๊ฒƒ ์ผ์ˆ˜๋„ ์žˆ๋‹ค..)

 

ํ•˜์ง€๋งŒ ํ•˜๋‚˜์˜ request์— ๋Œ€ํ•ด 2๊ฐœ์˜ ์ฟผ๋ฆฌ๋ฌธ์ด ์ƒ๊ธฐ๋Š” ๊ฒƒ๋„ ์ด์ƒ์ ์ด์ง€๋Š” ์•Š๊ธฐ์—,

ํ•˜๋‚˜์˜ left outer join Query ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด์ž.

Team Repository์— ๋‹ค์Œ๊ณผ ๊ฐ™์ด @EntityGraph๋ฅผ ์„ค์ •ํ•œ๋‹ค.

interface TeamRepository : CrudRepository<Team, Long> {
    @EntityGraph(attributePaths = ["players"])
    override fun findById(id: Long): Optional<Team>
}

๋ณ€๊ฒฝ ํ›„์—๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด Query๊ฐ€ ๋‚˜๊ฐ€๊ฒŒ ๋œ๋‹ค.

select 
team0_.team_id as team_id1_3_0_, 
team0_.name as name2_3_0_, 
players1_.team_id as team_id4_1_1_, 
players1_.player_id as player_i1_1_1_, 
players1_.player_id as player_i1_1_2_, 
players1_.count as count2_1_2_, 
players1_.name as name3_1_2_, 
players1_.team_id as team_id4_1_2_ 
from 
team team0_ 
left outer join 
player players1_ 
on 
team0_.team_id=players1_.team_id 
where 
team0_.team_id=?

 

์ด๋กœ ์ธํ•ด fetch type EAGER์™€๋„ ๋น„์Šทํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

 

์˜ค๋Š˜์€ ์—ฌ๊ธฐ๊นŒ์ง€..

ํ‹€๋ฆฐ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์ง€์ ์€ ์–ธ์ œ๋“ ์ง€ ํ™˜์˜์ž…๋‹ˆ๋‹ค

'Coding > SpringBoot' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[SpringBoot] Kotlin - Database Lock - 1  (0) 2021.04.21

์ตœ๊ทผ์— ์„œ๋ฒ„ ๊ฐœ๋ฐœ์„ ํ•˜๋Š” ์™€์ค‘์—.. ํฐ ์‹ค์ˆ˜๋ฅผ ์ €์งˆ๋Ÿฌ ๋ฒ„๋ ธ๋‹ค.

์„œ๋ฒ„์˜ ๊ตฌ์„ฑ ์š”๊ฑด์ด ์•„๋ž˜์™€ ๊ฐ™์•˜๋‹ค.


1. ์„œ๋ฒ„๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ธ์Šคํ„ด์Šค์—์„œ ๋™์ž‘ํ•˜๋Š” ๊ฒƒ์„ ๊ฐ€์ •

2. ๋™์‹œ๋‹ค๋ฐœ์ ์ธ ์š”์ฒญ์—๋„ ๋ฌธ์ œ๊ฐ€ ์—†๋„๋ก ์„ค๊ณ„


์—ฌ๊ธฐ์—์„œ 1๋ฒˆ์€ ์–ด๋Š์ •๋„ ๊ฐ์•ˆ์„ ํ–ˆ์ง€๋งŒ 2๋ฒˆ์„ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์ง€ ์ƒ๊ฐ์ง€๋„ ๋ชปํ–ˆ๋‹ค

์•„๋Š” ์‚ฌ๋žŒ์—๊ฒŒ๋Š” ๋ณด์ด๊ฒ ์ง€๋งŒ.. ๋‚ด๊ณต์ด ๋ถ€์กฑํ•˜์—ฌ ๋ชป๋ณด๊ณ  ์ง€๋‚˜๊ฐ”๋˜ ํƒ“์ธ๊ฒƒ ๊ฐ™๋‹ค..

์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Database์˜ ๋™์‹œ์„ฑ์„ ํ•ด๊ฒฐํ•ด์•ผ ํ•˜๋Š”๋ฐ


1. Read/Write์—์„œ Lock์„ ๊ฑธ์–ด์ฃผ๊ฑฐ๋‚˜

2. insert / update query๋ฅผ ํ•  ๋•Œ database ๋ฅผ ๋ฐ”๋กœ ์ฐธ์กฐํ•˜๋„๋ก ํ•ด์•ผ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.


์ฆ‰, Controller๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” Service function์—์„œ

@Transactional์ด ๊ฑธ๋ ค์žˆ๋‹ค๊ณ  ํ•ด์„œ Database์˜ ๋™์‹œ์„ฑ์„ ๋งŒ์กฑํ•  ์ˆ˜ ์—†๊ณ ,

๋ณ„๋„์˜ ์„ค์ •์„ ํ•ด ์ฃผ๊ฑฐ๋‚˜ Query๋ฅผ ๋‚ ๋ ค์•ผ ํ•˜๋Š” ๊ฒƒ์ด์—ˆ๋‹ค.

Entity๊ตฌ์„ฑ์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

@Entity
class Team(
    var title: String,
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB์—์„œ ์ž๋™์œผ๋กœ ID increment
    @Column(name = "team_id")
    var id: Long = 0L
    
    // Onwer Entity๋ฅผ Player๋กœ ์ง€์ •, Lazy type fetch, Persistence ์ „์ด ํƒ€์ž…
    @OneToMany(mappedBy="team", cascade=[CascaseType.ALL], fetch = FetchType.LAZY) 
    var players : MutableList<Player> = mutableListOf()
}

@Entity
class Player(
    var name : String,
    
    @ManyToOne
    @JoinColumn(name = "team_id") // ์™ธ๋ž˜ํ‚ค ๋งคํ•‘์„ ์œ„ํ•œ ์„ค์ •
    var game: Game
) {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // DB์—์„œ ์ž๋™์œผ๋กœ ID increment
    @Column(name = "player_id")
    var id: Long = 0L
    
    var count : Long
}

Game <--> Player ์—”ํ‹ฐํ‹ฐ๊ฐ€ 1:N์œผ๋กœ ์„ค์ •๋˜์–ด ์žˆ๋‹ค.

Game์ด MappedBy๋ฅผ Player์˜ "team" field๋กœ ๋ช…์‹œ ํ•ด ์คŒ์œผ๋กœ์จ Player๊ฐ€ Owner๋กœ ๋“ฑ๋ก.

Player table์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋ž˜ Query๋ฌธ๊ณผ ๊ฐ™์ด Foreign Key๋ฅผ ์ƒ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค.

alter table player add constraint FKdvd6ljes11r44igawmpm1mc5s foreign key (team_id) references team

์—ฌ๊ธฐ์—์„œ Player ์ƒ์„ฑ ์‹œ Team์˜ total_player_number๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.

๋‹น์—ฐํžˆ ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์ƒ์„ฑ๋  ๋•Œ ๋งˆ๋‹ค 1์”ฉ ์ฆ๊ฐ€๋˜์–ด์•ผ ํ•  ๊ฒƒ์ด๋‹ค.

ํ•˜์ง€๋งŒ, ์—ฌ๋Ÿฌ Client๊ฐ€ ๋™์‹œ์— Player๋ฅผ ์ƒ์„ฑํ•˜๊ณ , Database๊ฐ€ Lock์ด ๋˜์ง€ ์•Š์„๋•Œ๋ฅผ ๊ฐ€์ •ํ•ด๋ณด์ž.

 

2๊ฐœ์˜ Client์—์„œ ๊ฐ๊ฐ Player๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ํ•œ๋‹ค.

๋˜ํ•œ, ๊ฐ๊ฐ์˜ Client์—์„œ Team ์ •๋ณด๋ฅผ ์ฝ์„ ๋•Œ total_player_number๊ฐ€ 0์ด์—ˆ๋‹ค.

์ด ๋•Œ, ๋™์‹œ์— request๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋˜๋ฉด 2๊ฐœ์˜ Player๊ฐ€ ์ƒ์„ฑ๋˜์—ˆ์ง€๋งŒ

Team์˜ total_player_number๋Š” 1์ด ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์กด์žฌํ•œ๋‹ค.

 

์ฒซ๋ฒˆ์งธ Player๋กœ ์ธํ•ด total_player_number๊ฐ€ 1๋กœ ์ฆ๊ฐ€ํ•˜์ง€๋งŒ,

๋‘๋ฒˆ ์งธ Player ์ €์žฅ ๋‹น์‹œ ์ด๋ฏธ ์ฝ์–ด์˜จ team์˜ ํ•ด๋‹น ํ•„๋“œ ๊ฐ’์ด 0์ด๊ธฐ ๋•Œ๋ฌธ์—

1 -> 2๋กœ ๋ณ€ํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ 1 -> 1๋กœ ๋ฎ์–ด์”Œ์›Œ ์งˆ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.


๋™์‹œ์„ฑ์„ ๊ณ ๋ คํ•˜์ง€ ์•Š์•˜์„ ๋•Œ Query ๋ฌธ

select 
team0_.team_id as team_id1_3_0_, 
team0_.name as name2_3_0_, 
team0_.total_player_number as total_pl3_3_0_, 
players1_.team_id as team_id4_1_1_, 
players1_.player_id as player_i1_1_1_, 
players1_.player_id as player_i1_1_2_, 
players1_.count as count2_1_2_, 
players1_.name as name3_1_2_, 
players1_.team_id as team_id4_1_2_ 
from 
team team0_ 
left outer join 
player players1_ 
on 
team0_.team_id=players1_.team_id 
where team0_.team_id=?

insert into player 
(player_id, count, name, team_id) 
values 
(null, ?, ?, ?)

update team 
set 
name=?, 
total_player_number=? 
where 
team_id=?

 

Team repository๋ฅผ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด์„œ Pessimistic Lock์„ ๊ฑธ์–ด์ฃผ์—ˆ๋‹ค.

interface TeamRepository : JpaRepository<Team, Long> {
    @Lock(LockModeType.PESSIMISTIC_WRITE)	// ๋น„๊ด€์  Lock (Read / Write ๋ชจ๋‘)
    @EntityGraph(attributePaths = ["players"])
    override fun findById(id: Long): Optional<Team>
}

๋™์‹œ์„ฑ์„ ๊ณ ๋ คํ–ˆ์„ ๋•Œ Query ๋ฌธ

select 
team0_.team_id as team_id1_3_0_, 
team0_.name as name2_3_0_, 
team0_.total_player_number as total_pl3_3_0_, 
players1_.team_id as team_id4_1_1_, 
players1_.player_id as player_i1_1_1_, 
players1_.player_id as player_i1_1_2_, 
players1_.count as count2_1_2_, 
players1_.name as name3_1_2_, 
players1_.team_id as team_id4_1_2_ 
from 
team team0_ 
left outer join 
player players1_ 
on 
team0_.team_id=players1_.team_id 
where 
team0_.team_id=? 
for update		/* Database lock์„ ์œ„ํ•ด for update ๋ผ๋Š” ๊ตฌ๋ฌธ์ด ์ถ”๊ฐ€ ๋จ */

insert into player 
(player_id, count, name, team_id) 
values 
(null, ?, ?, ?)

update team 
set 
name=?, 
total_player_number=? 
where 
team_id=?

๋‹ค๋ฅธ๊ฑด ๋™์ผํ•˜์ง€๋งŒ, select ๋ฌธ์—์„œ ๋’ค์— ~ for update ๊ฐ€ ๋ถ™์–ด์žˆ๋‹ค.

์ด๋Š” ๋™์‹œ์„ฑ ์ œ์–ด๋ฅผ ์œ„ํ•ด ํŠน์ • row์— READ / WRITE Lock์ด ๊ฑธ๋ ค์žˆ๋‹ค๋Š” ๋ง์ด๋‹ค (๋ฐฐํƒ€์  Lock).

๋งŒ์•ฝ, Read๋Š” ์ž์œ ๋กญ๊ฒŒ ํ•˜๋˜, Write์—์„œ๋งŒ Lock์„ ๊ฑธ๊ณ ์‹ถ๋‹ค๋ฉด PESSIMISTIC_READ ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.


๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ ์ง์ ‘ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ๋‹ค.

 

'Coding > SpringBoot' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[SpringBoot] Kotlin - Entity Graph  (1) 2021.04.22

์•ˆ๋…•ํ•˜์„ธ์š”?

์ฝ”๋”ฉํ•˜๋Š” ๋ชจ์ฃผ๋ถ€ ์ž…๋‹ˆ๋‹ค!

 

์ด๋ฒˆ ์‹œ๋ฆฌ์ฆˆ๋Š”, ์ฝ”ํ‹€๋ฆฐ(Kotlin) ์ด๋ผ๋Š” ์–ธ์–ด๋ฅผ ์‚ฌ์šฉํ•ด์„œ

์•ˆ๋“œ๋กœ์ด๋“œ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์–ดํ”Œ์„ ๋งŒ๋“ค์–ด ๋ณผ๊ฑฐ์—์š”!


1. ์†Œ๊ฐœ ๋ฐ ๊ฐœ์š”

 

์ฝ”ํ‹€๋ฆฐ์ด๋ž€?

IntelliJ IDEA์˜ ๊ฐœ๋ฐœ์‚ฌ 

JetBrains ์—์„œ 2011๋…„์— ๊ณต๊ฐœํ–ˆ๊ณ ,


2017๋…„ ๊ตฌ๊ธ€์ด ์•ˆ๋“œ๋กœ์ด๋“œ ๊ณต์‹์–ธ์–ด๋กœ ์ถ”๊ฐ€ํ•œ ์–ธ์–ด์—์š”!

๊ตฌ๊ธ€์ด ๋ฐ€์–ด์ฃผ๊ณ  ์žˆ์œผ๋‹ˆ, ๋˜๊ฒŒ ํ•ซํ•œ ์–ธ์–ด์ฃ !

 

Java๊ฐ€ ์ต์ˆ™ํ•˜์‹  ๋ถ„๋“ค์„ ์œ„ํ•ด,

์ฝ”ํ‹€๋ฆฐ๊ณผ Java๋ฅผ ๊ฐ„๋‹จํžˆ ๋น„๊ต ํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™์•„์š”

  Kotlin Java
๊ณตํ†ต์  ๊ฐ์ฒด ์ง€ํ–ฅํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด
์ฐจ์ด์  Null ํ• ๋‹น์ด ๊ฐ€๋Šฅ
๊ธฐ๋ณธํ˜• ํƒ€์ž…๋งˆ์ € ํด๋ž˜์Šค๋กœ ์กด์žฌ
๊ณ ์ฐจํ•จ์ˆ˜ / ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์‚ฌ์šฉ ๊ฐ€๋Šฅ
Data ํด๋ž˜์Šค ์‚ฌ์šฉ ๊ฐ€๋Šฅ
์ฝ”๋ฃจํ‹ด ์‚ฌ์šฉ ๊ฐ€๋Šฅ
Null ํ• ๋‹น์ด ๋ถˆ๊ฐ€๋Šฅ
๊ฐ์ฒด ๋‹จ์œ„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ๋ฐฉ์‹

 

์ฝ”ํ‹€๋ฆฐ์ด ์ž๋ฐ”๋ณด๋‹ค ์ตœ๊ทผ์— ๊ฐœ๋ฐœ๋œ ์–ธ์–ด์ด๋‹ค ๋ณด๋‹ˆ,

ํŽธ๋ฆฌํ•˜๊ณ  ๊ตฌ์กฐ์ ์œผ๋กœ ์ž˜ ๋งŒ๋“ค์–ด์ง„ ์–ธ์–ด์ธ๊ฒƒ ๊ฐ™์•„์š”.

 

์ด๋ฒˆ ์‹œ๋ฆฌ์ฆˆ๋Š”, ์ดˆ๋ณด์ž๋“ค์˜ ๋ˆˆ๋†’์ด์— ๋งž์ถ”์–ด

์ฝ”๋“œ๋ฅผ ๋”ฐ๋ผ์„œ ์‹คํ–‰ํ•˜๋ฉด ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค!

๋ผ๋Š”๋ฐ ์ดˆ์ ์„ ์ข€ ๋งž์ถ”๊ณ  ์ง„ํ–‰ํ• ๊นŒ ํ•ฉ๋‹ˆ๋‹ค.

 

๋‹จ, ๋ชจ๋“  ์ž‘์—…๋“ค์€ ๋ชจ๋ฐ”์ผ์—์„œ๋Š” ์•ˆ๋˜๊ณ ..

PC์—์„œ ์ง„ํ–‰ํ•˜์…”์•ผ ํ•ฉ๋‹ˆ๋‹ค!


2. ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค ์„ค์น˜

 

์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ์— ์•ž์„œ, ์„ธํŒ…์„ ๋จผ์ € ํ•ด์ค์‹œ๋‹ค

์•„๋ž˜์˜ ๋งํฌ์—์„œ ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค๋ฅผ ์„ค์น˜ํ•ด ์ฃผ์„ธ์š”

(VsCode๋ฅผ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๋“ค์€, ๊ทธ๋ƒฅ ์“ฐ์…”๋„ ๋ฌด๋ฐฉํ•ฉ๋‹ˆ๋‹ค)

 

developer.android.com/studio?hl=ko

 

Download Android Studio and SDK tools  |  Android ์ŠคํŠœ๋””์˜ค

developer.android.com

์œˆ๋„์šฐ์™€ ๋งฅ๋ถ ๋ชจ๋‘ ์„ค์น˜๊ฐ€๋Šฅํ•˜๋‚˜,

์„ค์ •์ด ์•ฝ๊ฐ„์”ฉ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์–ด์š”.

(์ €๋Š” ๋งฅ๋ถ์œผ๋กœ ์ง„ํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค!)


3. ์ƒˆ ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

 

์ด์ œ ์ฝ”ํ‹€๋ฆฐ์„ ์ด์šฉํ•ด์„œ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณผ๊นŒ์š”?

์•„๋ž˜์˜ ๊ทธ๋ฆผ์„ ๋”ฐ๋ผ ์™€์ฃผ์„ธ์š”!

์ƒˆ๋กœ์šด ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์ค๋‹ˆ๋‹ค

 

๊ธฐ๋ณธ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ๋ˆŒ๋Ÿฌ ์ง„ํ–‰ํ•ด์ฃผ์„ธ์š”

 

๋งŒ๋“ค ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์ด๋ฆ„์„ ์ž…๋ ฅํ•˜๊ณ , Kotlin์„ ์–ธ์–ด๋กœ ์„ ํƒํ•ด์ฃผ์„ธ์š”

 

์™„์„ฑ์ด ๋˜์—ˆ๋‹ค๋ฉด, ์•„๋ž˜์˜ ํ™”๋ฉด์ด ๋‚˜์˜ฌ๊ฒ๋‹ˆ๋‹ค!

MainActivity.kt ๊ฐ€ ์ƒ์„ฑ๋œ ๋ชจ์Šต์ž…๋‹ˆ๋‹ค.


4. ์ฝ”๋“œ ์‚ฝ์ž…๊ณผ AVD (๊ฐ€์ƒ ๋””๋ฐ”์ด์Šค) ์‹คํ–‰

 

์ฝ”ํ‹€๋ฆฐ์€ ์•„๋ž˜์˜ 4๊ฐ€์ง€๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ์š”,


Activity
Service
Broadcast receiver
Content provider


์ด ์ค‘์—์„œ ๊ฐ€์žฅ ์ค‘์š”ํ•˜๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” Activity ๋Š”,

๊ทธ๋ฆผ์ด๋‚˜ ๊ธ€์”จ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์‹œ๊ฐ์ ์ธ ์š”์†Œ๋“ค์„

ํœด๋Œ€ํฐ์˜ ํ™”๋ฉด์— ๋„์›Œ์ฃผ๋Š” ์—ญํ• ์„ ํ•ด์š”.

 

์ฝ”๋”ฉ์˜ ๋ง›์„ ์‚ด์ง ๋ณด๊ธฐ์œ„ํ•ด์„œ,

์•„๋ž˜์˜ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ ๋ผ์ธ9์™€ ๋ผ์ธ17์— ๊ฐ๊ฐ

์ฝ”๋“œ๋ฅผ ์‚ฝ์ž… ํ•ด ๋ณผ๊นŒ์š”?

Line 9  --> import android.widget.Toast
Line 17 --> Toast.makeText(this, "hello, formicae", Toast.LENGTH_LONG).show()

 

์‚ฝ์ž…์„ ํ•˜์…จ๋‹ค๋ฉด, ์‹คํ–‰์„ ๋ˆŒ๋Ÿฌ์ฃผ์„ธ์š”!

Run ์„ ํด๋ฆญ

 

๋งŒ์•ฝ, ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค๊ฐ€ ์ฒ˜์Œ์ด์‹œ๋ผ๋ฉด

๊ฐ€์ƒ ๋””๋ฐ”์ด์Šค ์„ค์น˜๊ฐ€ ํ•„์š”ํ• ๊ฑฐ์—์š”.

AVD Manager๋ฅผ ํด๋ฆญ
Create Virtual Device๋ฅผ ๋ˆŒ๋Ÿฌ ์ƒ์„ฑ ํ•ด์ฃผ์‹œ๋ฉด ๋ฉ๋‹ˆ๋‹ค

 

๋””๋ฐ”์ด์Šค์—์„œ ์‹คํ–‰์ด ์™„๋ฃŒ๊ฐ€ ๋˜์—ˆ๋‹ค๋ฉด,

์•„๋ž˜์™€ ๊ฐ™์ด "hello, formicae" ๋ผ๋Š” ๋ฌธ๊ตฌ๊ฐ€

์ž ๊น ์˜ฌ๋ผ์™”๋‹ค๊ฐ€ ์‚ฌ๋ผ์ง€๋Š” ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

 

์ด๊ฒƒ์€ Toast๋ผ๋Š” ๋‚ด์žฅ ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•œ ๊ฒƒ์ธ๋ฐ์š”,

์•ž์œผ๋กœ๋„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์œ ์šฉํ•œ ํด๋ž˜์Šค๋“ค๊ณผ

์ง์ ‘ ๋งŒ๋“  ํด๋ž˜์Šค๋“ค์„ ์ด์šฉํ•ด ์–ดํ”Œ์„ ๋งŒ๋“ค์–ด ๋ณด์•„์š”!

 

์—ฌ๊ธฐ๊นŒ์ง€๊ฐ€ ๊ธฐ๋ณธ์ ์ธ ์„ค์ •์„ ๋‹ค๋ฃจ์—ˆ๊ณ ,

๋‹ค์Œ ํฌ์ŠคํŒ…์—์„œ๋Š” ์ฝ”๋“œ๋ฅผ ์กฐ๊ธˆ์”ฉ ๋ฐ”๊พธ์–ด ๊ฐ€๋ฉฐ

์–ด๋–ค ๊ฒƒ๋“ค์„ ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์†Œ๊ฐœ ํ•ด ๋ณผ๊นŒ ํ•ด์š”!

 

๊ทธ๋Ÿผ ๋‹ค์Œ ํฌ์ŠคํŒ…์œผ๋กœ ๊ณ ๊ณ ์”ฝ :)

'Coding > Kotlin' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

Android ๊ฐœ๋ฐœ - Google service ์—ฐ๋™ํ•˜๊ธฐ  (0) 2021.03.20
์•ˆ๋“œ๋กœ์ด๋“œ release key store ๊ด€๋ฆฌ  (0) 2021.03.20

+ Recent posts