Home > Backend Development > πŸ“š[Backend Development] findChildTopPath λ©”μ„œλ“œμ˜ μ‹€ν–‰ 결과와 λ™μž‘ 방식.

πŸ“š[Backend Development] findChildTopPath λ©”μ„œλ“œμ˜ μ‹€ν–‰ 결과와 λ™μž‘ 방식.
Backend Ddevelopment

β€œπŸ“š[Backend Development] findChildTopPath λ©”μ„œλ“œμ˜ μ‹€ν–‰ 결과와 λ™μž‘ 방식.”

βœ…1️⃣ μ˜ˆμ‹œ μ½”λ“œ.

package kobe.board.comment.entity;

import jakarta.persistence.Embeddable;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Getter
@ToString
@Embeddable
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class CommentPath {
	private String path;

	private static final String CHARSET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

	private static final int DEPTH_CHUNK_SIZE = 5;
	private static final int MAX_DEPTH = 5;

	// MIN_CHUNK = "00000", MAX_CHUNK = "zzzzz"
	private static final String MIN_CHUNK = String.valueOf(CHARSET.charAt(0)).repeat(DEPTH_CHUNK_SIZE);
	private static final String MAX_CHUNK = String.valueOf(CHARSET.charAt(CHARSET.length() - 1)).repeat(DEPTH_CHUNK_SIZE);

	public static CommentPath create(String path) {
		if (isDepthOverflowed(path)) {
			throw new IllegalStateException("depth overflowed");
		}

		CommentPath commentPath = new CommentPath();
		commentPath.path = path;
		return commentPath;
	}

	private static boolean isDepthOverflowed(String path) {
		return calculateDepth(path) > MAX_DEPTH;
	}

	private static int calculateDepth(String path) {
		// 25개의 λ¬Έμžμ—΄ / 5 = 5depth
		return path.length() / DEPTH_CHUNK_SIZE;
	}

	// CommentPath 클래슀의 path의 depthλ₯Ό κ΅¬ν•˜λŠ” λ§€μ„œλ“œ
	public int getDepth() {
		return calculateDepth(path);
	}

	// root인지 ν™•μΈν•˜λŠ” λ§€μ„œλ“œ
	public boolean isRoot() {
		// ν˜„μž¬μ˜ depthκ°€ 1인지 확인해주면 됨
		return calculateDepth(path) == 1;
	}

	// ν˜„μž¬ path의 parentPathλ₯Ό λ°˜ν™˜ν•΄μ£ΌλŠ” λ§€μ„œλ“œ
	public String getParentPath() {
		// 끝 5자리만 μž˜λΌλ‚΄λ©΄ 됨
		return path.substring(0, path.length() - DEPTH_CHUNK_SIZE);
	}

	// ν˜„μž¬ path의 ν•˜μœ„ λŒ“κΈ€μ˜ path을 λ§Œλ“œλŠ” λ§€μ„œλ“œ
	public CommentPath createChildCommentPath(String descendantsTopPath) {
		if (descendantsTopPath == null) {
			return CommentPath.create(path + MIN_CHUNK);
		}
		String childrenTopPath = findChildrenTopPath(descendantsTopPath);
		return CommentPath.create(increase(childrenTopPath));
	}
	// 00a0z 00002 00000 <- descendantsTopPath
	private String findChildrenTopPath(String descendantsTopPath) {
		return descendantsTopPath.substring(0, (getDepth() + 1) * DEPTH_CHUNK_SIZE);
	}
}

βœ…2️⃣ findChildrenTopPath(String descendantsTopPath) μ‹€ν–‰ κ²°κ³Ό.

  • descendantsTopPath에 β€œ00a0z0000200000” 값이 λ“€μ–΄κ°„λ‹€κ³  κ°€μ •ν•œλ‹€.
    • findChildrenTopPath λ©”μ„œλ“œλŠ” ν˜„μž¬ 객체의 depthλ₯Ό 기반으둜 descendantsTopPath의 νŠΉμ • 길이만큼 μž˜λΌλ‚Έ 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.
    • ν˜„μž¬ path의 depthλŠ” getDepth() λ©”μ„œλ“œλ₯Ό 톡해 κ³„μ‚°λ©λ‹ˆλ‹€.
    • getDepth()λŠ” ν˜„μž¬ path의 길이λ₯Ό DEPTH_CHUNK_SIZE(5)둜 λ‚˜λˆ„μ–΄ κ΅¬ν•©λ‹ˆλ‹€.

πŸ“Œ 예제 μ‹€ν–‰.

  • 예λ₯Ό λ“€μ–΄, CommentPath 객체가 path = β€œ00a0z”라면:
    • getDepth() = 1(λ¬Έμžμ—΄ 길이 5/5)
    • (getDepth() + 1) * DEPTH_CHUNK_SIZE = (1 + 1) * 5 = 10
    • descendantsTopPath.substring(0, 10)

πŸ“Œ κ²°κ³Όκ°’:

"00a0z00002"

βœ…3️⃣ findChildrenTopPath λ©”μ„œλ“œμ˜ λ™μž‘ 방식

private String findChildrenTopPath(String descendantsTopPath) {
    return descendantsTopPath.substring(0, (getDepth() + 1) * DEPTH_CHUNK_SIZE);
}

πŸ“Œ 단계별 λ™μž‘.

πŸ“Œ1️⃣ ν˜„μž¬ 객체의 depthλ₯Ό ꡬ함.

  • getDepth()λ₯Ό ν˜ΈμΆœν•˜μ—¬ ν˜„μž¬ pathκ°€ λͺ‡ 단계인지 계산.
  • getDepth()λŠ” path.length() / DEPTH_CHUNK_SIZE둜 계산됨.

πŸ“Œ2️⃣ (getDepth() + 1) * DEPTH_CHUNK_SIZE κ°’ 계산.

  • ν˜„μž¬ depthμ—μ„œ ν•˜μœ„ λŒ“κΈ€μ˜ depthλ₯Ό ν¬ν•¨ν•œ 길이λ₯Ό 계산.
  • 즉, λ‹€μŒ depthκΉŒμ§€ ν¬ν•¨ν•œ descendantsTopPath의 μΌλΆ€λ§Œ κ°€μ Έμ˜€λ„λ‘ μ„€μ •,

πŸ“Œ3️⃣ descendantsTopPath의 일뢀λ₯Ό 잘라 λ°˜ν™˜.

  • descendantsTopPath.substring(0, (getDepth() + 1) * DEPTH_CHUNK_SIZE);
  • descendantsTopPathμ—μ„œ μ•ž 뢀뢄을 가져와 childrenTopPathλ₯Ό 생성.

πŸš€ κ²°λ‘ 

  • findChildrenTopPath(β€œ00a0z0000200000”)의 μ‹€ν–‰ κ²°κ³ΌλŠ” β€œ00a0z00002”
  • 이 λ©”μ„œλ“œλŠ” descendantsTopPathμ—μ„œ ν˜„μž¬ depth κΈ°μ€€μœΌλ‘œ ν•œ λ‹¨κ³„λ§Œ 더 ν¬ν•¨ν•œ 경둜λ₯Ό 잘라 λ°˜ν™˜.
  • κ²°κ΅­ ν˜„μž¬ 객체의 ν•˜μœ„ λŒ“κΈ€λ“€μ΄ κ³΅ν†΅μ μœΌλ‘œ κ°€μ§€λŠ” prefixλ₯Ό μ°Ύμ•„μ£ΌλŠ” 역할을 ν•œλ‹€.