-
DB์ ํ ์ด๋ธ์ row๊ฐ ๋๋ฌด ๋ง์์ง๋ (์ ํ๋ฃจ์ 10๋ง๊ฑด์ฉ ๋์ ), ๋์ฒ ๋ฐฉ๋ฒ
- โํ๋ฃจ 10๋ง ๊ฑด์ฉ ๊ณ์ ๋์ โ์ด๋ฉด 1๋ ์ 3,650๋ง ๊ฑด์ ๋๋ค. ์ด๋ฐ์ ๋ฒํฐ์ง๋ง, ๋ช ๋ฌ๋ง ์ง๋๋ ์ฟผ๋ฆฌยท๋ฐฑ์ ยทVACUUM/OPTIMIZE ๋น์ฉ์ด ๊ธ์ฆํ์ฃ . ์๋ ์์๋๋ก ์ ์ฉํด๋ณด์ธ์.
1) ๋จผ์ ๊ฒฐ์ ํ ๊ฒ (์ด์ ์ ์ฑ )
- ๋ณด์กด ๊ธฐ๊ฐ: ์) โ6๊ฐ์์ ์จ๋ผ์ธ(ํซ), 2๋ ์ ์์นด์ด๋ธ(์ฝ๋), ๊ทธ ์ธ ์ญ์ โ
- ์ฃผ์ ์กฐํ ํจํด: ์ต๊ทผ N์ผ๋ง ์กฐํ? ํน์ ์ฌ์ฉ์/ํค ๊ธฐ์ค ์กฐํ? ์ง๊ณ ์์ฃผ?
- SLA/์ฑ๋ฅ: p95 ์๋ต์๊ฐ, ํ์ฉ ๊ฐ๋ฅํ ์ฐ๊ธฐ ์ง์ฐ
2) ์ฆ์ ํจ๊ณผ (์คํค๋ง/์ธ๋ฑ์ค/์ฐ๊ธฐ)
-
์ธ๋ฑ์ค ์ฌ๋ฆผํ: ์ค์ ์กฐ๊ฑด/์ ๋ ฌ์ ์ฐ๋ ์ปฌ๋ผ๋ง ์ธ๋ฑ์ค. ๋ถํ์ํ ๋ณตํฉ ์ธ๋ฑ์ค ์ ๊ฑฐ.
CreatedTue, 14 Oct 2025 11:25:18 +0900 -
HTTP API ํธ์ถ ์ access token์ ํค๋์ ๋ฐ๋์ ๋ณด๋ด๋ ๊ฒ ์ฌ์ด์๋ ๋ช ๊ฐ์ง ์ค์ํ ๋ณด์์ ์ฐจ์ด์ ์ด ์์ต๋๋ค:
์ฃผ์ ๋ณด์ ์ฐจ์ด์
1. ๋ก๊น ๋ฐ ๋ชจ๋ํฐ๋ง
- ํค๋: ๋๋ถ๋ถ์ ์น ์๋ฒ์ ํ๋ก์๋ ๊ธฐ๋ณธ์ ์ผ๋ก Authorization ํค๋๋ฅผ ๋ก๊ทธ์์ ๋ง์คํนํ๊ฑฐ๋ ์ ์ธํฉ๋๋ค
- ๋ฐ๋: ์์ฒญ ๋ฐ๋๋ ๋๋ฒ๊น ๋ชฉ์ ์ผ๋ก ๋ก๊ทธ์ ๊ธฐ๋ก๋ ๊ฐ๋ฅ์ฑ์ด ๋์ ํ ํฐ์ด ํ๋ฌธ์ผ๋ก ๋ ธ์ถ๋ ์ํ์ด ์์ต๋๋ค
2. ์บ์ฑ ๋์
- ํค๋: HTTP ์บ์๋ Authorization ํค๋๊ฐ ์๋ ์์ฒญ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์บ์ํ์ง ์์ต๋๋ค
- ๋ฐ๋: ๋ฐ๋์ ํ ํฐ์ด ์์ด๋ ์บ์ ์ ์ฑ ์ ๋ฐ๋ผ ์๋ต์ด ์บ์๋ ์ ์์ด, ์๋์น ์์ ํ ํฐ ๋ ธ์ถ ์ํ์ด ์์ต๋๋ค
3. ํ๋ก์ ๋ฐ ๋ฏธ๋ค์จ์ด ์ฒ๋ฆฌ
- ํค๋: ํ์ค ์ธ์ฆ ํค๋๋ก ์ธ์๋์ด ๋ณด์ ๋ฏธ๋ค์จ์ด์์ ์ ์ ํ ์ฒ๋ฆฌ๋ฉ๋๋ค
- ๋ฐ๋: ์ผ๋ฐ ๋ฐ์ดํฐ๋ก ์ทจ๊ธ๋์ด ๋ณด์ ์ฒ๋ฆฌ๊ฐ ๋๋ฝ๋ ์ ์์ต๋๋ค
4. ๋ธ๋ผ์ฐ์ ๊ฐ๋ฐ์ ๋๊ตฌ
- ํค๋: ๋คํธ์ํฌ ํญ์์ ๋ณผ ์๋ ์์ง๋ง, Authorization ํค๋์์ ๋ช ํํ ์ธ์ํ ์ ์์ต๋๋ค
- ๋ฐ๋: ์ผ๋ฐ ๋ฐ์ดํฐ์ฒ๋ผ ๋ณด์ฌ ๊ฐ๋ฐ์๊ฐ ๋ฏผ๊ฐํ ์ ๋ณด์์ ๋์น ์ ์์ต๋๋ค
๊ถ์ฅ์ฌํญ
// โ ๊ถ์ฅ: Authorization ํค๋ ์ฌ์ฉ fetch('/api/data', { headers: { 'Authorization': 'Bearer ' + accessToken, 'Content-Type': 'application/json' } }); // โ ๋น๊ถ์ฅ: ๋ฐ๋์ ํ ํฐ ํฌํจ fetch('/api/data', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accessToken: accessToken, otherData: data }) });๊ฒฐ๋ก : Authorization ํค๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด ๋ณด์์ ๋ ์์ ํ๋ฉฐ, HTTP ํ์ค์ ์ค์ํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ๋๋ถ๋ถ์ ๋ณด์ ๋๊ตฌ์ ์ธํ๋ผ๊ฐ ์ด๋ฅผ ์ ์ ๋ก ์ค๊ณ๋์ด ์์ด ๋ ๋์ ๋ณด์ ๋ณด์ฅ์ ์ ๊ณตํฉ๋๋ค.
CreatedFri, 12 Sep 2025 08:25:18 +0900 -
1) ์ด๋ฒคํธ ์ ์ (POJO/record ๊ถ์ฅ)
// src/main/java/com/example/user/event/UserSignedUpEvent.java package com.example.user.event; import java.time.Instant; public record UserSignedUpEvent(Long userId, String email, Instant occurredAt) {}Spring 6+/Boot 3์์๋
ApplicationEvent๋ฅผ ์์ํ ํ์๊ฐ ์์ต๋๋ค. ํ๋ฒํ POJO/record๊ฐ ์ข์์.
2) ์ด๋ฒคํธ ๋ฐํ (raise)
// src/main/java/com/example/user/service/SignUpService.java package com.example.user.service; import com.example.user.event.UserSignedUpEvent; import com.example.user.model.User; import com.example.user.repo.UserRepository; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.time.Instant; @Service public class SignUpService { private final UserRepository userRepository; private final ApplicationEventPublisher publisher; public SignUpService(UserRepository userRepository, ApplicationEventPublisher publisher) { this.userRepository = userRepository; this.publisher = publisher; } @Transactional public Long signUp(String email, String name) { User user = userRepository.save(new User(email, name)); // JPA ์ํฐํฐ ์ ์ฅ ๊ฐ์ // ์ด๋ฒคํธ ๋ฐํ (ํธ๋์ญ์ ์์์) publisher.publishEvent(new UserSignedUpEvent(user.getId(), user.getEmail(), Instant.now())); return user.getId(); } }
3) ๋๊ธฐ ๋ฆฌ์ค๋ (๊ธฐ๋ณธ)
// src/main/java/com/example/user/listener/AuditLogListener.java package com.example.user.listener; import com.example.user.event.UserSignedUpEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.event.EventListener; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; @Component public class AuditLogListener { private static final Logger log = LoggerFactory.getLogger(AuditLogListener.class); @Order(0) // ์ฌ๋ฌ ๋ฆฌ์ค๋๊ฐ ์์ ๋ ์์ ์ ์ด ๊ฐ๋ฅ (๋ฎ์์๋ก ๋จผ์ ) @EventListener public void onUserSignedUp(UserSignedUpEvent event) { log.info("AUDIT: userId={}, email={}, at={}", event.userId(), event.email(), event.occurredAt()); } }๊ธฐ๋ณธ์ โ๋๊ธฐ ์คํโ์ด๋ผ ๋ฐํ ์์ ์ ์ฆ์ ํธ์ถ๋ฉ๋๋ค.
CreatedMon, 01 Sep 2025 16:13:53 +0900 -
Java Spring์์ “reflection(๋ฆฌํ๋ ์ )“์ Java์ ๋ฐํ์ ์์ ์ ํด๋์ค, ๋ฉ์๋, ํ๋ ๋ฑ์ ์ ๊ทผํ๊ณ ์กฐ์ํ ์ ์๋ ๊ธฐ๋ฅ์ ์๋ฏธํฉ๋๋ค. ์ผ๋ฐ์ ์ธ ์ปดํ์ผ ์์ ์ด ์๋, ์คํ ์ค์ธ ์ ํ๋ฆฌ์ผ์ด์ ์ ๊ตฌ์กฐ๋ฅผ ๋์ ์ผ๋ก ๋ถ์ํ๊ฑฐ๋ ๋ณ๊ฒฝํ๋ ๋ฐ ํ์ฉ๋ฉ๋๋ค.
๐ก ๋ฆฌํ๋ ์ ์ด๋?
Java ๋ฆฌํ๋ ์ API๋
java.lang.reflectํจํค์ง๋ฅผ ํตํด ์ ๊ณต๋๋ฉฐ, ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค:- ํด๋์ค ์ด๋ฆ์ผ๋ก
Class๊ฐ์ฒด๋ฅผ ์ป๊ธฐ - ํด๋์ค์ ์์ฑ์, ๋ฉ์๋, ํ๋ ์ ๋ณด ์กฐํ
- ๋ฉ์๋ ํธ์ถ, ํ๋ ๊ฐ ์ฝ๊ธฐ/์ฐ๊ธฐ ๋ฑ ๋์ ์กฐ์
- ์ ๊ทผ ์ ํ์(private ๋ฑ) ๋ฌด์ํ๊ณ ์ ๊ทผ (
setAccessible(true))
๐ Spring์์ ๋ฆฌํ๋ ์ ์ด ์ฐ์ด๋ ์ฃผ์ ์
Spring ํ๋ ์์ํฌ๋ ๋ด๋ถ์ ์ผ๋ก ๋ฆฌํ๋ ์ ์ ๋งค์ฐ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉํฉ๋๋ค:
CreatedTue, 29 Jul 2025 14:07:45 +0900 - ํด๋์ค ์ด๋ฆ์ผ๋ก
-
Spring Boot 3 + JPA + MySQL ํ๊ฒฝ์์ ํน์ ํ ์ด๋ธ์ ๋ํด
find๋ฐsave์์ ์ row-level lock๋ง ์ฌ์ฉํ๊ณ table-level lock์ ํผํ๊ณ ์ถ์ ๊ฒฝ์ฐ, ๋ค์๊ณผ ๊ฐ์ ์ ๋ต์ ์ฌ์ฉํ ์ ์์ต๋๋ค.
โ ํต์ฌ ๊ฐ๋ ์์ฝ
-
MySQL InnoDB ์คํ ๋ฆฌ์ง ์์ง์ ๊ธฐ๋ณธ์ ์ผ๋ก row-level lock์ ์ง์ํ๋ฉฐ, JPA์ ๊ธฐ๋ณธ ๋์์ row-level lock์ ์ฌ์ฉํฉ๋๋ค.
-
๊ทธ๋ฌ๋ ๋ค์ ์กฐ๊ฑด์ ๋ง์กฑํ์ง ์์ผ๋ฉด innoDB๋ผ๋ table lock์ด ๋ฐ์ํ ์ ์์ต๋๋ค:
- WHERE ์ ์ ์ธ๋ฑ์ค๋ฅผ ์ ์ฌ์ฉํ์ง ๋ชปํ๊ฑฐ๋
- ๋ฝ ๋ชจ๋๊ฐ ๋ช ์๋์ง ์์๊ฑฐ๋
UPDATE๋SELECT ... FOR UPDATE์์ ๋ฒ์ ๊ฒ์์ ์ ๋๋ก ๊ตฌ์ฑํ์ง ์์๊ฑฐ๋
โ ์ ์ ์กฐ๊ฑด: ํ ์ด๋ธ์ด InnoDB ์์ง์ธ์ง ํ์ธ
SHOW TABLE STATUS WHERE Name = 'your_table_name';Engine์ปฌ๋ผ์ดInnoDB์ฌ์ผ row-level lock์ด ์ ์ฉ๋ฉ๋๋ค.- ๋ง์ฝ
MyISAM์ด๋ฉด row-level lock์ด ๋ถ๊ฐ๋ฅํ๋ฏ๋ก ๋ฐ๋์ InnoDB๋ก ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค:
ALTER TABLE your_table_name ENGINE = InnoDB;
โ JPA์์ row-level locking๋ง ์ ์ฉํ๊ธฐ
1.
@Lock(LockModeType.PESSIMISTIC_WRITE)๋๋@Lock(LockModeType.PESSIMISTIC_READ)@Repository public interface OrderRepository extends JpaRepository<Order, Long> { @Lock(LockModeType.PESSIMISTIC_WRITE) @Query("SELECT o FROM Order o WHERE o.id = :id") Optional<Order> findByIdForUpdate(@Param("id") Long id); }PESSIMISTIC_WRITE๋SELECT ... FOR UPDATE๋ฅผ ์คํํ์ฌ row-level exclusive lock์ ๊ฒ๋๋ค.- ์ด ์ฟผ๋ฆฌ๋ ํด๋น row๋ฅผ ๋ค๋ฅธ ํธ๋์ญ์ ์์ ๋ณ๊ฒฝํ์ง ๋ชปํ๊ฒ ๋ง์ต๋๋ค.
PESSIMISTIC_READ๋ ๊ณต์ ๋ฝ์ ๊ฑธ๋ฉฐ ์ฝ๊ธฐ๋ ํ์ฉํ๋ ์ฐ๊ธฐ๋ ๋ง์ต๋๋ค.
โ ๏ธ ์ฃผ์: ์ด ๋ฐฉ๋ฒ์ ๋ฐ๋์ ํธ๋์ญ์ (@Transactional) ์์์ ์ฌ์ฉ๋์ด์ผ ์ค์ ๋ก ๋ฝ์ด ์ ์ฉ๋ฉ๋๋ค.
CreatedThu, 24 Jul 2025 10:07:45 +0900 -
-
์๋์ Java Pathfinder (JPF) ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ์์ธํ ์๋ด๋๋ฆฝ๋๋ค. Java Pathfinder๋ ์๋ฐ ํ๋ก๊ทธ๋จ์ ๋ชจ๋ธ ์ฒดํน(model checking) ๋๊ตฌ๋ก, ํ๋ก๊ทธ๋จ์ ์ํ ๊ณต๊ฐ์ ํ์ํ์ฌ ๋ฒ๊ทธ๋ ๋ฐ๋๋ฝ ๋ฑ์ ์ฐพ๋ ๋ฐ ํ์ฉ๋ฉ๋๋ค.
์๋ ๋ด์ฉ์ ๋จ๊ณ๋ณ๋ก ์ค๋ช ๋๋ฆด๊ฒ์.
๐งญ 1. Java Pathfinder(JPF)๋?
**Java Pathfinder (JPF)**๋ ์๋ฐ ํ๋ก๊ทธ๋จ์ ์คํํ๋ฉฐ ์ํ๊ณต๊ฐ์ ์ฒด๊ณ์ ์ผ๋ก ํ์ํ๋ ํด์ ๋๋ค.
์ฃผ์ ๊ธฐ๋ฅ
- ๋ฉํฐ์ค๋ ๋ฉ ๋ฒ๊ทธ ํ์ง
- Assertion ์๋ฐ ๊ฒ์ถ
- Deadlock ํ์ง
- Non-deterministic ๋์ ๊ฒ์ฆ
- Symbolic execution (jpf-symbc) ์ง์
โ๏ธ 2. ์ค์น
JPF๋ GitHub ์ ์ฅ์์์ ์ง์ ๋น๋ํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค.
CreatedThu, 03 Jul 2025 10:49:24 +0900