๋ชฉ๋กBack-end (35)
DevLog ๐ถ
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์๋ ์ ์ผ๋ ๊ธ์ธ๋ฐ, ์์ฆ ๋ธ๋ก๊ทธ๋ฅผ ๋๋ฌด ์ ์ด ๊ฒ ๊ฐ์์ ์ค๋๋ง์ ์ฌ๋ฆฌ๋ ๊ธ ๐ถ ํผ์ ๊ณต๋ถํ ๊ฒธ ์์ฑํ ๊ธ์ด์์ด์ ๋ค์ ์ค๋ช ์ด ๋ถ์กฑํฉ๋๋ค...! ๐ฑ ์ํฐํฐ ์๊ฐ @Entity @EntityListeners(AuditingEntityListener.class) public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(nullable = false) @CreatedDate private LocalDateTime createdAt; @LastModifiedDate private LocalDateTime updatedAt; User ํด๋์ค๋ ์ฌ์ฉ์์ ๋ํ ์ํฐํฐ์ด๋ฉฐ, id..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ JPA์์ @OneToMany ๋จ๋ฐฉํฅ ๋งคํ๋ณด๋ค๋ ๋ค๋์ผ ์๋ฐฉํฅ ๋งคํ์ ๊ถ์ฅํ๋ค๋ ๋ง์ ๋ณด์์ ๊ฒ์ด๋ค. ํ์ง๋ง, ๊ฐ์ฒด์งํฅ์ผ๋ก ์ฝ๋๋ฅผ ์ค๊ณํ๋ค ๋ณด๋ฉด ๋ค๋์ผ์ ์ํฉ๋ณด๋ค๋ 1์ธ ์ํฐํฐ๋ฅผ ๊ธฐ์ค์ผ๋ก N์ธ ์ํฐํฐ๋ฅผ ์กฐํํ๋ ๊ฒฝ์ฐ๊ฐ ๋ ๋ง๊ณ , (์ ์ด๋ ๋ด ๊ฒฝํ์์๋ ๊ทธ๋ฌ๋ค) N์ธ ์ํฐํฐ๊ฐ ๊ตณ์ด 1์ธ ์ํฐํฐ์ ๋ํ ์ ๋ณด๋ฅผ ๋ชฐ๋ผ๋ ๋๋ ์ ์ด ๋ง์๋ค. ๊ทธ๋ฌ๋ค ๋ณด๋ ์์ฐ์ค๋ฝ๊ฒ ์ผ๋๋ค ๋จ๋ฐฉํฅ ๋งคํ์ ๋ง์ด ์ฌ์ฉํ์๋๋ฐ, ์ ๊ทธ๋ฌ๋ ๊ฒ์ธ์ง ๊ถ๊ธํด์ ๋๋ฆ๋๋ก ์คํ์ ํด๋ณด๊ณ ์ ํ๋ค. (ex. ๊ฒ์๊ธ๊ณผ ๊ฒ์๊ธ ์ด๋ฏธ์ง์ ๊ด๊ณ์์, ๊ฒ์๊ธ ์ด๋ฏธ์ง๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ฒ์๊ธ ์ ๋ณด๋ฅผ ์ฐพ์์ค๋ ๊ฒ๋ณด๋ค๋ ๊ฒ์๊ธ์ ๊ธฐ์ค์ผ๋ก ๊ฒ์๊ธ ์ด๋ฏธ์ง ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๋ ๊ฒ ๋ ๋ง์์) ๐ฑ ๊ธฐ๋ณธ ์ํฐํฐ ์ค๊ณํ๊ธฐ @Entity class Board( @Id @..
๐ฑ JPA ๊ธฐ๋ณธ ํค ์์ฑ ์ ๋ต JPA์์ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํค ์์ฑ ์ ๋ต์ ํฌ๊ฒ 5๊ฐ์ง๋ก ๋๋์ด์ง๋ค. - TABLE, SEQUENCE, IDENTITY, UUID, AUTO ๊ฐ ์ ๋ต์ ๋ํด์ ํ๋์ฉ ์์๋ณด๋๋ก ํ์. ๐ฑ TABLE ๐ก Indicates that the persistence provider must assign primary keys for the entity using an underlying database table to ensure uniqueness. - ๋ฐ์ดํฐ๋ฒ ์ด์ค ํ ์ด๋ธ์ ์ฌ์ฉํ์ฌ ์ํฐํฐ์ ๊ธฐ๋ณธ ํค๋ฅผ ํ ๋นํด์ผ ํ๋ค. ๐ฌ ์ํฐํฐ ์ค์ @Entity class User( @Id @GeneratedValue(strategy = GenerationType.TABLE) val id: Lon..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ง๋ ํฌ์คํ ์์๋ CascadeType.REMOVE์ ๋ํด์ ์ค์ ์ ์ผ๋ก ์์๋ดค์๋๋ฐ, ์ด๋ฒ์๋ orphanRemoval=true ์ต์ ์ ๋ํด์ ํ ๋ฒ ์์๋ณด์. ์ํฐํฐ ์ธํ ์ ์ง๋ ๋ฒ๊ณผ ๊ฑฐ์ ๋์ผํ๊ธฐ ๋๋ฌธ์ ๋ณํ๊ฐ ์๊ธด ๋ถ๋ถ์ ๋ํด์๋ง ๋ฐ๋ก ์ง๋๋ก ํ๊ฒ ๋ค. ๐ฑ ์ํฐํฐ ์์ ํ๊ธฐ ์ด๋ฒ์๋ CascadeType.REMOVE ๋์ ์ orphanRemoval=true๋ฅผ ์ ์ฉํ์. @Entity class Concert( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long = 0L, @Column(nullable = false) val name: String, @Column(nullable = false) val ticketLi..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ JPA๋ฅผ ๊ณต๋ถํ๋ฉด์ CascadeType.REMOVE์ orphanRemoval = true ์ต์ ์ ๋ํด์ ์ด๋ค ์ฐจ์ด๊ฐ ์๋์ง ์ ๋๋ก ์ธ์งํ ์ ์ด ์๋ ๊ฒ ๊ฐ์์, ์ด๋ฒ์ ๊ณต๋ถํ ๊ฒธ ์ฌ๋ฌ ๊ฐ์ง ํ ์คํธ๋ฅผ ์งํํด๋ณด๋ฉฐ ๋ ์ต์ ์ ์ฐจ์ด๋ฅผ ๊ณต๋ถํด๋ณด์๋ค. ๊ฒฐ๊ณผ์ ์ผ๋ก ๋งํ์๋ฉด Cascade ์ต์ ์ ๋ถ๋ชจ ์ํฐํฐ์ ์์ ์ํฐํฐ์ ์์ ์ํ๋ฅผ ๊ด๋ฆฌํ๋ ๊ฒ์ด๊ณ , orphanRemoval์ ์กฐ๊ธ ๋ ์ธ๋ถ์ ์ผ๋ก ๊ณ ์ ๊ฐ์ฒด์ ๋ํ ๊ด๋ฆฌ๋ผ๋ ์๊ฐ์ด ๋ค์๋ค. ์ง๊ธ๋ถํฐ ์ฌ๋ฌ ์ผ์คํธ๋ฅผ ํ ์คํธํ๋ฉฐ ํ๋์ฉ ์์๋ณด์. ๐ฑ ์ํฐํฐ ์ธํ ํ๊ธฐ 1:N ๊ด๊ณ๋ฅผ ๋ด๋นํด์ค '์ฝ์ํธ' ์ํฐํฐ์ '์ฝ์ํธ ํฐ์ผ' ์ํฐํฐ๋ฅผ ์์ฑํ์๋ค. ๋ ์ฌ์ด์ ๊ด๊ณ๋ ์๋ฐฉํฅ์ผ๋ก ์ค์ ํ์์ผ๋ฉฐ, ํ๋์ ์ฝ์ํธ๋ ์ฌ๋ฌ ๊ฐ์ ์ฝ์ํธ ํฐ์ผ์ ๋ณด์ ํ ์ ์๋๋ก ์ค๊ณํ์..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ฌ์ค rest-docs๋ ๋ฏธ์ ์๊ตฌ์ฌํญ์ ์๋์์ง๋ง, ๊ฐ์ธ์ ์ธ ์์ฌ์ผ๋ก ํ ๋ฒ ์ง์ ๊ตฌ์ถํด๋ณด๊ณ ์ถ๋ค๋ ์๊ฐ์ด ๋ค์์ด์ ๋ฏธ์ ํ๋ ๊น์ ํจ๊ป ์งํํ๊ฒ ๋์๋ค. (์ด์ฐจํผ ์ถํ ๋ฏธ์ ์งํํ๋ฉด์ ํ๋ก ํธ ํฌ๋ฃจ์ ํ์ ํ๊ฒ ๋๋ฉด ์ธํ ํด์ผ ํ๋๊น...) RestDocs๋ฅผ ์ฐ๋ํ ๋ ์ธ์ ํ ์คํธ ๋ ๋ฒจ์์ ์งํํ ์ง (RestAssured) ์๋๋ฉด ์ปจํธ๋กค๋ฌ์ ๋จ์ ํ ์คํธ์์ ์งํํ ์ง ๊ณ ๋ฏผํ์๋๋ฐ, RestAssured๋ฅผ ํตํด ์ฌ์ฉํ๊ฒ ๋๋ฉด BDD ์คํ์ผ์ด๋ผ ๋ ์ง๊ด์ ์ผ ๊ฒ ๊ฐ๊ธด ํ์ง๋ง ์๋ฌด๋๋ ์๋๊ฐ ๋๋ฆฌ๋ค ๋ณด๋๊น ๊ทธ๋ฅ ์ปจํธ๋กค๋ฌ ๋ ์ด์ด์์ ์งํํ๋ค. (์ค์ ๋ก๋ ์ปจํธ๋กค๋ฌ ๋ ๋ฒจ์์ ๋ง์ด ์งํํ๋ ๊ฒ ๊ฐ๋ค.) โ๏ธ Rest-docs๊ฐ ์ด๋ค ๊ฑฐ์ง? Spring Rest Docs๋ Restful ์๋น์ค์ ๋ํด ์ ํํ๊ณ ..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ง๋ ํฌ์คํ ์์๋ ์ค์์ ์ํ์ ์ํฐํฐ๋ ์ง์ฐ ๋ก๋ฉํ ์ ์๋ค๊ณ ๋งํ๋ค. ์ด๋, ์ง์ฐ ๋ก๋ฉ์ ์ํ ํ๋ก์ ๊ฐ์ฒด๋ฅผ ์ด๊ธฐํํ๊ธฐ ์ํด ์์์ฑ ์ปจํ ์คํธ๊ฐ ํ์ํ๋ฐ, ์ค์์ ์ํ์ ์ํฐํฐ๋ ์์์ฑ ์ปจํ ์คํธ์ ๊ด๋ฆฌ ๋ฒ์์์ ๋ฒ์ด๋ฌ๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ ๋ค๋ฉด, ์ค์์ ์ํ์ ์ํฐํฐ๋ ์ด๋ป๊ฒ ์ฒ๋ฆฌํด์ผ ํ ๊น? ๐ฑ ๊ธ๋ก๋ฒ ํ์น ์ ๋ต์ LAZY์์ EAGER๋ก ์์ ํ๊ธฐ ๊ฐ๋จํ๊ฒ ๋งํ๋ฉด ์ง์ฐ ๋ก๋ฉ์ ์ฌ์ฉํ์ง ๋ง๊ณ , ์ฆ์ ๋ก๋ฉ์ ์ฌ์ฉํ์๋ ๊ฒ์ด๋ค ๐ @Entity @Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) public class Crew { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private ..
๊ธ์์ผ์ ๊ทผ๋กํ๋ฉด์ ๊ตฌ๊ตฌ์ ๊ทผ๋ก ํฌ๋ฃจ๋ค์ ๋์ ๋๋ถ์ JPA๋ฅผ ๋ค์๊ธ ๊ณต๋ถํ๊ฒ ๋๋ค ๐ ๋๋ ์์ ํ๊ฒ ์ ์๋ ๋ด์ฉ์ ์๋์ง๋ผ ์๋๋๋ก ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค. ๐ฑ ์์์ฑ ์ปจํ ์คํธ์ ํธ๋์ญ์ ๐ก ์์์ฑ ์ปจํ ์คํธ๋? ์ํฐํฐ๋ฅผ ์์ํ์ํค๋ ํ๊ฒฝ. EntityManager๋ฅผ ํตํด ์ํฐํฐ๋ฅผ ์ ์ฅํ๊ฑฐ๋ ์กฐํํ๋ฉด ์์์ฑ ์ปจํ ์คํธ์ ๋ณด๊ด๋ ์ํฐํฐ ์ ๋ณด๋ฅผ ๋ฐํ์ผ๋ก ์์ฒญ์ ์ฒ๋ฆฌํ๊ฒ ๋๋ค. EntityManager ์์ฑ ์ 1๊ฐ๊ฐ ๋ง๋ค์ด์ง๋ค. ๐ฌ ํน์ง - ์๋ณ์ ๊ฐ์ผ๋ก ์ํฐํฐ๋ฅผ ๊ตฌ๋ถํ๋ค. - ํธ๋์ญ์ ์ปค๋ฐ ์์ ์ flush. (์ฐ๊ธฐ ์ง์ฐ - ๋ด๋ถ ์ฟผ๋ฆฌ ์ ์ฅ์์ SQL ์ ์ฅ ํ ํ ๋ฒ์ ํ๋ฌ์) - 1์ฐจ ์บ์๋ฅผ ์ฌ์ฉํ๋ค. (์ฒ์์ 1์ฐจ ์บ์์์ ์ํฐํฐ ์กฐํ > ์์ผ๋ฉด DB ์กฐํ > 1์ฐจ ์บ์์ ์ ์ฅํ๋ ํํ = '์์ํ') - ..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์ด์ ํฌ์คํ ๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก ์คํฐ๋์์ ๋งก์ 'ํ ์คํธ' ํํธ์ ๋ํด์ ๋ธ๋ก๊ทธ์ ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค ๐ ํ ์คํธ ์ชฝ์ ๊ณต์ ๋ฌธ์๋ ์๊ฐ๋ณด๋ค ๊ฐ๋ ์ฑ์ด ๋๋ฌด ์ ์ข์์ ์ต๋ํ ๊ฐ๋ตํ๊ฒ๋ง ํ์ด๋ณด์๋ค. ์์ง ๋ชจ๋ฅด๋ ๊ฒ ์ ๋ง ๋ง์ ๊ฒ ๊ฐ๋ค ใ ใ ๐ฑ ํตํฉ ํ ์คํธ vs ์ธ์ ํ ์คํธ ํตํฉ ํ ์คํธ๋ ํน์ ์์ ์ ์ํํ๊ธฐ ์ํด, ์ธ๋ถ ์์ ๋ค๊ณผ ์ฐ๊ด๋์ด ์๋ค๋ฉด ํด๋น ์ธ๋ถ ์์ ๋ค์ ํฌํจํ์ฌ ๊ตฌ์ฑ ์์๊ฐ ์ ๋์๊ฐ๋์ง ํ ์คํธํ๋ ๋ฐฉ๋ฒ์ผ๋ก, @SpringBootTest ์ด๋ ธํ ์ด์ ์ ํ์ฉํ์ฌ ์งํํ๋ ๋ฐฉ๋ฒ์ด ๋ง๋ค. (๊ด๋ จ๋ ๋ชจ๋ ๋น์ ๊ฐ์ ธ์์ ํ ์คํธ ํ๋ ๋๋) ๋ฐ๋ฉด, ์ธ์ ํ ์คํธ์ ๊ฒฝ์ฐ ์ฌ์ฉ์์ ์๋๋ฆฌ์ค์ ๋ง์ถฐ ์ํํ๋ ํ ์คํธ์ด๋ค. ์ธ์ ํ ์คํธ์ ๋ฐฉ๋ฒ๋ก ์ผ๋ก E2E ํ ์คํธ๋ฅผ ํตํด ์ฃผ์ด์ง ์๋๋ฆฌ์ค์ ๋ฐ๋ผ ์ ํ๋ฆฌ์ผ์ด์ ์ ๋ชจ๋ ..
๐ฑ ๋ค์ด๊ฐ๊ธฐ ์ ์คํฐ๋์์ ๋ฐํ ์๋ฃ๋ก ์ค๋นํ๋ ๋ด์ฉ์ธ๋ฐ, ๋ธ๋ก๊ทธ์๋ ์ฎ๊ฒจ๋๋ฉด ์ข์ ๊ฒ ๊ฐ์์ ์ ๋ฆฌํ๋ ๊ธ ๐ ํ๋กค๋ก๊ทธ ๋ก๋๋งต์ ํค์๋ ์์ฃผ๋ก ์ ๋ฆฌํ์์ต๋๋ค! ๐ฑ DI (์์กด๊ด๊ณ ์ฃผ์ ) โ๏ธ ์์กดํ๋ค? A๊ฐ B๋ฅผ ์ฌ์ฉํ๊ณ , B๋ฅผ ๋ณ๊ฒฝํ๋ฉด A์ ์ํฅ์ ๋ผ์น๋ ๊ด๊ณ. ์์กด๊ด๊ณ ์ฃผ์ ์ ๋ค์ ์ธ ๊ฐ์ง ์กฐ๊ฑด์ ์ถฉ์กฑํ๋ ์์ ์ ์๋ฏธํ๋ค. - ํด๋์ค ๋ชจ๋ธ์ด๋ ์ฝ๋์๋ ๋ฐํ์ ์์ ์ ์์กด๊ด๊ณ๊ฐ ๋๋ฌ๋์ง ์๋๋ก, ์ธํฐํ์ด์ค๋ง ์์กดํด์ผ ํ๋ค. - ๋ฐํ์ ์์ ์ ์์กด๊ด๊ณ๋ ์ปจํ ์ด๋๋ ํฉํฐ๋ฆฌ์ ๊ฐ์ ์ 3์ ์กด์ฌ (ex. IoC container)๊ฐ ๊ฒฐ์ ํ๋ค. - ์์กด๊ด๊ณ๋ ์ฌ์ฉํ ์ค๋ธ์ ํธ์ ๋ํ ๋ ํผ๋ฐ์ค๋ฅผ ์ธ๋ถ์์ ์ ๊ณตํด์ค์ผ๋ก์ ๋ง๋ค์ด์ง๋ค. โ๏ธ DI๋ฅผ ์ฌ์ฉํ๋ฉด ๋ฌด์์ด ์ข์๊ฐ? - ๊ฐ์ฒด๊ฐ์ ๊ฒฐํฉ๋ ๊ฐ์ → ์ฌ์ฌ์ฉ์ฑ, ์ ์ง๋ณด..