๐ Backend/๐ฟ Springboot

Spring Boot :: @FeignClient ๋ก ์ธ๋ถ REST API ๊ฐํธ ํธ์ถ
๋ค์ด๊ฐ๋ฉด์ ์นด์นด์ค ๋ฐ ์ ํ ๋ก๊ทธ์ธ์ ๊ตฌํํ๋ฉด์ ์ธ๋ถ API ์๋ฒ์ ์ ๊ทผํด ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์์ผ ํ๋ ์ผ์ด ๋ง์์ก๊ณ , API ์ฃผ์๋ฅผ ์ค์ ํ์ผ์ ์ ์ฅํ ํ ์ง์ HttpURLConnection ์ ์์ฑํด์ ์ฐ๊ฒฐํ๋ ์ฝ๋๊ฐ ์ค๋ณต๋๊ฒ ๋์๋ค. ๋ ์ง์ HttpURLConnection ์ ์ฐ๊ฒฐํด ์ธ๋ถ API ์์ ๋ฐ์ดํฐ๋ฅผ ๋ฐ์์ค๋ฉด ๋ฐ์์จ JSON ์ ์ง์ ํ์ฑํด์ผ ํ๋ ๋ถํธํจ๋ ์กด์ฌํ๋ค. ์ ๋ฆฌํ์๋ฉด, ์ธ๋ถ API ๋ฅผ ๊ฐํธํ๊ฒ ํธ์ถํ๊ณ ์ถ์ด์ ํธ์ถ ๊ฒฐ๊ณผ๋ฅผ ์ง์ ํ์ฑํ๋ ๊ณผ์ ์ด ๋ฒ๊ฑฐ๋ก์์ FeignClient ๋ฅผ ์ฌ์ฉํ๊ฒ ๋์๋ค. ์๋ ์ค๋ช ์์๋ ๋ง์ด ์์๋ฅผ ๋๋ Github API ๋ฅผ ์ด์ฉํด์ ์ฝ๋๋ฅผ ์์ฑํด๋ณด์๋ค. FeinClient Feign ์ Netflix ์์ ๊ฐ๋ฐํ REST Client ์ด๋ค. ๊ธฐ์กด์ Rest..

JUnit :: ParameterizedTest ๋ก ๊ฒฝ๊ณ๊ฐ ํ ์คํธํ๊ธฐ
๊ฒฝ๊ณ๊ฐ์์ ์ฅ์ ๊ฐ ๋ง์ด ์ผ์ด๋๋ค ํ ์คํธํ ๋๋ input ๊ฐ์ ๊ฒฝ๊ณ๊ฐ์ ๋ํด์ ํญ์ ํ ์คํธ๋ฅผ ์งํํด์ผ ํ๋ค ๊ทธ๋ฌ๊ธฐ ์ํด ParameterizedTest ๋ฅผ ์ด์ฉํ๋ฉด ์ฌ๋ฌ ๋ฐ์ดํฐ ์์ค๋ฅผ ์ฌ์ฉํ ์ ์๋ค. build.gradle ์์ junit-jupiter-params ์ถ๊ฐ testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.2' ์์ธํ ๋ด์ฉ์ ์๋ ๋งํฌ ์ฐธ์กฐ https://www.petrikainulainen.net/programming/testing/junit-5-tutorial-writing-parameterized-tests/ ์ค์ต ๋น๋ฐ๋ฒํธ ์ ๋ ฅ ๊ฐ ๊ฒ์ฆ ํ ์คํธ ์๊ตฌ์ฌํญ ๋น๋ฐ๋ฒํธ๋ ์ต์ 8์ ์ด์ 12์ ์ดํ์ฌ์ผ ํ๋ค. ๋น๋ฐ๋ฒํธ๊ฐ 8์ ๋ฏธ..

JPA :: ๋ฒํฌ์ฑ ์์ ์ฟผ๋ฆฌ
๋ฒํฌ ์ฐ์ฐ ์ฌ๋ฌ ๊ฑด์ ๋ฐ์ดํฐ๋ฅผ ํ ๋ฒ์ ์์ ํ๊ฑฐ๋ ์ญ์ ์กฐ๊ฑด์ ๋ง๋ ๊ฐ์ฒด๋ฅผ ๋ค ๊ฐ์ง๊ณ ์์ ์์ ํ ํ์ ์์ด DB ์ฟผ๋ฆฌ๋ก ํด๊ฒฐํ๋ ๊ฒ. JPA Bulk ์์ ์ฝ๋ : ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์ ๋์ด๋ณด๋ค ๋ง์ ํ์๋ค์ ๋์ด๋ฅผ +1 ์ํจ๋ค. public int bulkAgePlus(int age) { return em.createQuery( "update Member m set m.age = m.age + 1" + " where m.age >= :age") .setParameter("age", age) .executeUpdate(); } ํ ์คํธ ์ฝ๋ @Test public void bulkUpdate() { //given memberJpaRepository.save(new Member("member1", 10)); m..

JPA :: ํ์ด์ง๊ณผ ์ ๋ ฌ
๊ธฐ์กด JPA ํ์ด์ง๊ณผ ์ ๋ ฌ public List findByPage(int age, int offset, int limit) { return em.createQuery("select m from Member m where m.age = :age order by m.username desc") .setParameter("age", age) .setFirstResult(offset) .setMaxResults(limit) .getResultList(); } public long totalCount(int age) { return em.createQuery("select count(m) from Member m where m.age = :age", Long.class) .setParameter("age", a..

JPA :: Query Method ๊ธฐ๋ฅ
์คํ๋ง ๋ฐ์ดํฐ JPA ๊ฐ ์ ๊ณตํ๋ ๋ง๋ฒ๊ฐ์ ๊ธฐ๋ฅ์ด ์๋ค. ๋ฐ๋ก โ์ฟผ๋ฆฌ ๋ฉ์๋โ ๊ธฐ๋ฅ์ธ๋ฐ, ๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด 3๊ฐ์ง ๊ธฐ๋ฅ์ด ์๋ค. ๋ฉ์๋ ์ด๋ฆ์ผ๋ก ์ฟผ๋ฆฌ ์์ฑ ๋ฉ์๋ ์ด๋ฆ์ผ๋ก JPA NamedQuery ํธ์ถ @Query ์ด๋ ธํ ์ด์ ์ ์ฌ์ฉํด์ Repository interface ์ ์ฟผ๋ฆฌ ์ง์ ์ ์ Method ์ด๋ฆ์ผ๋ก Query ์์ฑ ๋ฉ์๋ ์ด๋ฆ์ ๋ถ์ํด์ JPQL ์ฟผ๋ฆฌ ์คํ ์) ์ด๋ฆ๊ณผ ๋์ด๋ฅผ ๊ธฐ์ค์ผ๋ก ํ์์ ์กฐํํ๋ ค๋ฉด ? // ์์ JPA Repository public List findByUsernameAndAgeGreaterThan(String username, int age) { return em.createQuery("select m from Member m where m.username = :us..

Spring Boot :: Spring Data ํจํค์ง ๊ตฌ์กฐ
Spring Data JPA ๋ฅผ ํ์ฉํด์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ ๋ JpaRepository ๋ฅผ ์์๋ฐ์์ ์ฌ์ฉํ๋ค. ์ด JpaRepository ์์ ๋ค์ด๊ฐ๋ฉด ๋ ๋ค๋ฅธ Repository ๋ฅผ ์์๋ฐ๊ณ ๋ ์์๋ฐ๊ณ ,, ์ด ๊ตฌ์กฐ์ ๋ํด์ ๊ธฐ๋กํด๋๊ณ ์ ํ๋ค. ์ธํฐํ์ด์ค ์ดํด๋ณด๊ธฐ ๋จผ์ MemberRepository ๋ผ๋ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ๋ง๋ค์ด๋ณด์๋ค. public interface MemberRepository extends JpaRepository { } ์ฌ๊ธฐ์ JpaRepository ์์ ๋ค์ด๊ฐ๋ณด์. ํจํค์ง ์์น๋ org.springframework.data.jpa.repository ์ด๋ค. JpaRepository ๋ PagingAndSortingRepository ๋ฅผ ์์๋ฐ๊ณ ์๊ณ , PagingAndSort..

Spring Boot :: Spring Data JPA
์ธํฐํ์ด์ค๋ง ์ ์ํด๋ CRUD ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค ? ํ ์คํธ ์ฝ๋๋ฅผ ํตํด์ CRUD ๊ธฐ๋ฅ์ด ๋์ํ๋์ง ๊ฐ๋จํ๊ฒ ํ ์คํธํด๋ณด์. ํ ์คํธ ์์ Entity ์์ฑ ์์ JPA Repository ์์ฑ ํ ํ ์คํธ Data JPA Repository ์์ฑ ํ ํ ์คํธ Entity ์์ฑ ๋จผ์ Member Entity ๋ฅผ ๋ง๋ค์. @Entity @Getter @Setter @NoArgsConstructor(access = AccessLevel.PROTECTED) @ToString(of = {"id", "username"}) public class Member { @Id @GeneratedValue @Column(name = "member_id") private Long id; private String usernam..

JPA :: Auditing ์ํฐํฐ ๊ณตํต ์ ๋ณด ์ถ๊ฐํ๊ธฐ
Auditing JPA ์์ ๋๋ฉ์ธ์ RDB ํ ์ด๋ธ์ ๋งคํํ ๋, ๋๋ฉ์ธ๋ค์ด ๊ณตํต์ผ๋ก ๊ฐ์ง๊ณ ์๋ ํ๋๋ค ์กด์ฌ ์์ฑ์ผ์, ์์ ์ผ์, ์์ฑ์, ์์ ์ ๋ฑ JPA ์์ Audit ๊ธฐ๋ฅ ์ ๊ณต Spring Data JPA ์์ ์๊ฐ ๊ฐ์ ์๋์ผ๋ก ๋ฃ์ด์ค Auditing ์์ ์ฝ๋ build.gradle ์ ์์กด์ฑ ์ถ๊ฐ dependency { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' } ์คํ๋ง ๋ถํธ์์ gradle ๋ก ์์กด์ฑ์ ๊ด๋ฆฌํ๋ค๋ฉด spring-boot-starter-data-jpa ๋ง ์ถ๊ฐํด์ฃผ๋ฉด ๋๋ค. BaseTimeEntity.java @Getter @MappedSuperclass @EntityListeners(Audi..