common: Auditing - takeoff-26/logistics-service GitHub Wiki

data ์ถ”์ /๊ฐ์‚ฌ๋ฅผ ์œ„ํ•œ auditing ์ •์ฑ…

๋ชจ๋“  Entity์— ์ ์šฉ๋  ์ถ”์ ์ด๋‚˜ ๊ฐ์‚ฌ๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ, ์ˆ˜์ •, ์‚ญ์ œ ์ผ์‹œ๋‚˜ ํ–‰์œ„์ž๋ฅผ ์ €์žฅํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์— ๋”ฐ๋ผ ๊ธฐ์กด ๋ชจ๋†€๋ฆฌํ‹ฑ์—์„œ๋Š” global ํŒจํ‚ค์ง€๋ฅผ ๊ตฌ์„ฑํ•ด ์ง„ํ–‰ํ–ˆ๋”๋ผ๋ฉด ์ด๋ฒˆ MSA์—์„œ๋Š” ๊ณตํ†ต ๋ชจ๋“ˆ์— ์„ค์ • ํ•ด์•ผ ํ–ˆ๋‹ค.


@Getter
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class BaseEntity {

	@CreatedBy
	@Column(updatable = false)
	private Long createdBy;

	@CreatedDate
	@Column(updatable = false)
	private LocalDateTime createdAt;

	@LastModifiedBy
	private Long updatedBy;

	@LastModifiedDate
	private LocalDateTime updatedAt;

	private Long deletedBy;

	private LocalDateTime deletedAt;

	public void delete(Long deletedBy) {
		this.deletedAt = LocalDateTime.now();
		this.deletedBy = deletedBy;
	}
}

์œ„์™€ ๊ฐ™์ด ๊ตฌ์„ฑํ–ˆ์œผ๋ฉฐ, ์ด์ „ ๋ชจ๋†€๋ฆฌํ‹ฑ์—์„œ์™€ ๊ฐ™์€ ๊ตฌ์กฐ๋ฅผ ๊ฐ€์กŒ๋‹ค.
ํ•˜์ง€๋งŒ ์ด์ „ ๋ชจ๋†€๋ฆฌํ‹ฑ์—์„  ํ•˜๋‚˜์˜ ํ”„๋กœ์ ํŠธ์—์„œ ์‹œํ๋ฆฌํ‹ฐ๊ฐ€ ์ „์ฒด์ ์œผ๋กœ ์ ์šฉ์ด ๋˜์—ˆ๋‹ค๋ฉด ์ด๋ฒˆ์—” ์‹œํ๋ฆฌํ‹ฐ์— ๋Œ€ํ•œ ์˜์กด์„ฑ์„ ๋ฐ›์ง€ ์•Š๋Š”๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์‹œํ๋ฆฌํ‹ฐ์—์„œ ์ œ๊ณตํ•ด์ฃผ๋˜ SecurityContextHolder๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋˜๋Š” ๊ฒƒ์ด๊ณ  ์ด๋ฅผ ๋Œ€์‹  ํ•ด์ค„ ๊ตฌํ˜„์ฒด๊ฐ€ ํ•„์š”ํ•˜๋‹ค.


package takeoff.logistics_service.msa.common.domain;

import java.util.Optional;
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Component
public class AuditorAwareImpl implements AuditorAware<Long> {

	private static final String USER_ID_HEADER = "X-User-Id";

	@Override
	public Optional<Long> getCurrentAuditor() {

		return Optional.ofNullable(RequestContextHolder.getRequestAttributes())
			.filter(ServletRequestAttributes.class::isInstance)
			.map(ServletRequestAttributes.class::cast)
			.map(ServletRequestAttributes::getRequest)
			.map(request -> request.getHeader(USER_ID_HEADER))
			.filter(userId -> !userId.isEmpty())
			.flatMap(this::parseUserId);
	}

	private Optional<Long> parseUserId(String userId) {
		try {
			return Optional.of(Long.parseLong(userId));
		} catch (NumberFormatException e) {
			return Optional.empty();
		}
	}
}

AuditorAware๋ฅผ ๊ตฌํ˜„ํ•ด์„œ RequestContextHolder๋ฅผ ํ†ตํ•ด ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ณ  ๊ทธ ์•ˆ์— Request์™€ ํ—ค๋”๋ฅผ ๊บผ๋‚ด ๊ฒ€์ฆํ•˜๊ณ  ๊ฒ€์ฆ๋œ ๊ฐ’์ด๋ผ๋ฉด ๊ฐ ํ•„๋“œ์—์„œ ์–ด๋…ธํ…Œ์ด์…˜์„ ํ†ตํ•ด ์ƒ์„ฑ์‹œ, ์ˆ˜์ •์‹œ์— ์ €์žฅ์ด ๋˜๊ฒŒ๋” ๊ตฌ์„ฑํ–ˆ์œผ๋ฉฐ, ์‚ญ์ œ๋Š” ๋ณ„๋„์˜ ๋‚ด๋ถ€ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌ์„ฑํ•ด ์ง„ํ–‰ํ•˜๋„๋ก ํ–ˆ๋‹ค.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ