회고

231119 코드스쿼드max 자유 프로젝트 5, 6주차 회고

지안22 2023. 11. 19. 22:16

코드스쿼드에서 제공했던 공식적인 프로젝트 기간 이후 팀원들끼리 정한 2주간의 추가 기간도 끝이 났다.
마지막 날에는 팀원 외의 코드스쿼드 멤버들을 추가해서 총 9명의 멤버들과 재즈바 답사를 가며 마무리를 지었다.

이번 2주 동안에는 어떤 것을 하고, 무엇을 고민했는지 돌아보자.

 

5주차

기능 추가

디자이너인 다니가 우리 서비스만의 차별점이 있으면 좋겠다고 말씀해주셔서 공연에 대한 목록을 조회할 수 있는 페이지를 추가하게 되었다.

예약은 직접 서비스를 제공할 수 있으면 좋겠지만, 스케일이 커질 것 같아 일단은 다른 서비스에서 제공하는 예약 링크로 이동하는 아이콘을 추가해서 간단히 해결했다.

재즈바마다 룰이 달라 재즈 입문이 어렵기 때문에 초심자를 위한 가이드 페이지도 있으면 좋겠다고 생각했지만 어떻게 정리해서 제공하면 좋을지에 대한 아이디어 부족으로 인해 일단 보류를 하게 되었다. (엑셀처럼 표 형식으로 제공 해버릴까..도 생각했다.)

 

이번주에는 기능 구현을 빠르게 끝내고, 보수는 다음주에 하기로 했고, 한 사람 당 하나의 도메인을 맡으면 집중도와 이해도가 오르기 때문에 3명이서 각자 공연장, 공연, 문의를 맡아 기능을 개발하게 되었다.

 

문제점 및 고민거리

나는 문의 쪽 도메인을 맡게 되었는데, 문의 종류를 enum으로 처리하게 되면서 연관관계 등 Entity 설계가 바뀌게 되어 너무 어려웠지만 팀원들이 도와준 덕분에 이해도가 오르게 되었다. 기본기가 부족해서 생기는 고민과 문제들이 많아서 사놓고 못듣던 김영한님 JPA 강의를 꼭 들어야겠다고 생각했다.

 

또한 MapStruct도 List를 인자로 받지 못하는 오류가 있어서 나는 mapper 클래스에 default 메서드를 만들고, 인자에 dummy를 넣어 야매로 해결하는 방법을 사용했었는데 팀원인 시오가 dummy 없이도 잘 동작할 수 있게 MapStruct의 버전을 올려 근본적인 방법으로 해결해줘서 똑똑한 팀원들이 있어 든든하고 도움이 많이 된다고 느꼈던 한 주 였다.

 

로그인 기능이 따로 없이, 문의 글 작성 시에 닉네임과 비밀번호를 입력해 문의 글을 작성할 수 있도록 했는데, 이 과정에서 비밀번호에 대한 암호화 기능을 추가되게 되었다.

처음에는 커스텀으로 암호화 클래스를 만들어서 사용했는데(SHA-256 알고리즘 + salt), 등록 시에는 문제가 없었으나 삭제 때 DB에 인코딩 된 비밀번호와 입력받은 raw 비밀번호를 맞춰보는 과정에서 비밀번호가 일치하지 않는 문제가 생겼다.

(디테일한 이유는 더 찾아봐야 하겠지만, 입력받은 (raw)비밀번호를 똑같은 로직으로 암호화를 해도 해시값이 달라져 해당 문제가 발생한 것으로 알고 있다.)

또, 고정된 salt 값으로 암호화를 하면 레인보우 테이블을 이용하여 암호화 로직 및 salt 값을 알아낼 수도 있기 때문에 보안상 더 좋은 security가 제공해주는 모듈 중 하나인 BCryptPasswordEncoder을 사용하기로 했다.

커스텀으로 만들었던 방식과 동일한 방식(SHA-2이상의 알고리즘 + salt)으로 암호화가 진행이 되는데, 커스텀으로 만들었던 클래스보다 보안이 더 강화 된 이유는 salt 값이 변경되기 때문이다.

또한 일치하는지 확인하기 위한 로직을 작성 할 필요 없이 matches(CharSequence rawPassword, String encodePassword) 를 제공해줘서 사용하기만 하면 된다.

spring security를 사용하게 되면 멋대로 설정해주는 보안 기능 때문에 우리가 security를 컨트롤 하는데 시간이 더 들까봐 사용하기를 꺼렸는데, 알고보니 spring security starter가 그런 역할을 하는 것이고, security가 제공해주는 모듈만 사용하려면 spring security core만 의존성에 추가하면 된다는 사실을 깨닫고 암호화 모듈을 커스텀 암호화 클래스에서 BCryptPasswordEncoder로 변경하게 되었다.

 

6주차

한 일

QA를 진행하게 되었다. 

아무래도 지도가 open API를 사용하다 보니 프론트에서 예상치못한 문제들이 많이 생겼다.

백엔드는 공연장 데이터를 DB에 수동으로 넣다보니 오타 등의 사소한 문제가 생겨 수정이 필요했던 것 외에는 별다른 문제는 없었다.

 

문제점 및 고민거리

저번주에 못다한 기능을 구현했는데, 문의에 대한 답변 수정 시 DB에는 적용이 되는데 반환되는 객체에 적용되지 않는 문제가 있었다.

알고보니 해당 수정 메서드에 @Transaction을 걸어놔서 해당 트랜잭션이 끝나야 update 쿼리가 발생하게 되는데 그 전에 수정되기를 희망하는 객체를 반환해서 적용이 안된 상태로 반환이 됐던 것이었다.

때문에 트랜잭션 중간에 inquiryAnswerRepository.flush()를 호출해 강제 커밋을 해서 수정된 객체가 반환되도록 해결했다.

 

이 과정에서 DB에 시작 시간을 자동으로 찍어주는 어노테이션인 @CreatedDate와 @CreationTimeStamp과 DB에 수정 시간을 자동으로 찍어주는 @LastModifiedDate와 @UpdateTimestamp의 차이가 궁금했다.

앞쪽은(@CreatedDate, @LastModifiedDate) springboot가 제공해주는 어노테이션이라 해당 문제를 수정하려면 BaseTimeEntity에 @EntityListeners(AuditingEntityListener.class) 어노테이션을 추가해서 이벤트를 발생시키고, 최상단에 Application 클래스에도 @EnableJpaAuditing를 추가하여 발생된 이벤트를 들어서 수정 사항을 객체에 적용하는 것을 추가해야하기 때문에 (시오 당근마켓 레포) 이러한 추가 설정이 필요없는 뒷쪽(@CreationTimeStamp, @UpdateTimestamp) 어노테이션을 사용하기로 결정했다.

- 김영한님은 하이버네이트가 제공해주는 어노테이션을 사용하지 않는게 추세라고 하셨지만 (인프런 답변) 그게 왜 추세인지에 대해서는 추가로 알아봐야 할 것 같다.

 

또, BaseTimeEntity를 추상 클래스로 만들어서 시간이 적용되는 모든 Entity 클래스가 해당 클래스를 상속 받도록 수정 할 수 있었다.

@Getter
@MappedSuperclass
public abstract class BaseTimeEntity {

	@CreationTimestamp
	private LocalDateTime createdAt;
	@UpdateTimestamp
	private LocalDateTime modifiedAt;
}
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
public class Inquiry extends BaseTimeEntity {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;
	@Getter
	@Column(nullable = false, length = 20)
	private String nickname;
	@Column(nullable = false, length = 200)
	private String password;
	@Getter
	@Column(nullable = false, length = 500)
	private String content;
	@Enumerated(value = EnumType.STRING)
	@Column(nullable = false, length = 10)
	private InquiryCategory category;
	@Enumerated(value = EnumType.STRING)
	@Column(nullable = false, length = 10)
	private InquiryStatus status;
	@OneToOne(mappedBy = "inquiry", cascade = CascadeType.REMOVE, orphanRemoval = true)
	private Answer answer;
    
    // 이하 생략
}

 

postman을 이용한 테스트 시, response로 받는 id 값을 저장하고 해당 id 값을 request로 사용하는 것을 자동화 하고 싶어서 postman 환경변수에 설정하도록 했다. (tests에서 설정 가능)

// response header의 Authorization(토큰)을 환경 변수로 설정하고 싶을 때
if (pm.response.code === 200) {
    const authorizationHeader = pm.response.headers.get('Authorization');
    const tokenWithoutBearer = authorizationHeader.replace('Bearer', '');
    pm.environment.set('accessToken', tokenWithoutBearer);
}
// response body의 id를 환경 변수로 설정하고 싶을 때
if (pm.response.code === 200) {
    const answerId = pm.response.json().id;
    pm.environment.set('answerId', answerId);
}

 

주말까지 공부를 진행해서 그런지 목요일에는 팀원들에게 양해를 구해서 한번 쉬었고,

마무리 겸 프로젝트 정리를 위해 이안과 함께 깃허브 레포지토리의 README.md와 Wiki를 정리하기로 했는데, 부끄럽지만 아직까지 제대로 정리한 적이 없어 멘토 겸 코드 리뷰어, 또 코드스쿼드 선배인 로치와 새리에게 조언을 얻게 되었다.

일반적으로 README는 잘 정리하는 것이 좋은데 Wiki는 우선순위가 낮다는 조언을 얻었고,

예상 가능한 당연한 기능이나 기술은 제외하고 특별한 기술이나 고민을 해결했던 내용, 또 테스트 커버리지에 대해 작성하면 좋을 것 같다는 조언을 얻었다.

여태까지 기능을 구현하느라 바빠서 테스트 커버리지는 생각을 못했던 부분이었는데 다음주부터 개선하면 좋을 것 같다는 생각이 들었다.

 

이후

프론트 팀원들도 그렇고, 우리도 아직까지 남은 과제들이 있기 때문에 프로젝트를 계속 진행할 예정이다.

하지만 각자 취업을 위한 준비도 해야하기 때문에 월~금, 코어타임(10-4시)에 모두 한 곳에 모여 진행하던 방식에서 일주일에 두 번, 회의를 하는 요일과 시간을 정했고 그 이후는 각자 자유롭게 시간을 내어 차근차근 개선하기로 했다.

이 방식으로 진행하게 되면 프로젝트 진행 진도는 늦어질 수 있겠지만, 오히려 회사에서처럼 일을 진행해볼 수 있을 것 같아 좋은 경험이 될 것 같다고 생각했다.

 

중간에 프로덕트 디자이너인 다니가 시간 상 하차하게 되어 더 이상의 디자인적인 지원은 받을 수 없게 되었지만, 간격 조정 등의 조그만 일만 남았기 때문에 최대한 우리끼리 해결해보기로 했다.

프로덕트 디자이너인 만큼 UX/UI 등 서비스의 전반적인 부분(주로 사용성과 서비스 차별점)에 대해 고려해주셨고, 그 덕분에 다양한 아이디어를 제공받아 새로운 시야를 얻게 되어 좋은 경험이 되었다.

디자이너와 함께 프로젝트를 진행 한 적이 처음이기 때문에 소통 방식에 있어서 미숙했던 것 같아 아쉬웠지만, 이 경험을 토대로 다음 디자이너와의 협업에서는 더 나은 소통으로 프로젝트를 진행할 수 있기를 기대해본다.

 

공연 데이터 자동화는 아직까지 풀지 못한 숙제인데, 사이트의 지속 가능성을 위해 꼭 해결해야하는 과제라고 생각한다.

공연 데이터는 각 재즈바의 인스타의 사진으로 올라와있는 곳이 많은데, 사진 속의 데이터 형식도 다르고, 사진에서 글자를 추출하는 방법, 또 우리 서버에 넣는 방법을 알아봐야할 것 같다.

파이썬을 사용하게 되면 여태까지 자바로 작성한 프로젝트와 어떻게 연결을 하면 좋을 지 여러가지고 고민이 많이 되지만, 어차피 안해봤기 때문에 겁이 나는 거라 고민을 많이 하는 것 보다는 일단 무작정 잘될거라고 생각하고 시도해보는게 좋을 것 같다!

아자아자 내 자신 화이팅!

 

(또 어드민 페이지로 공연, 공연장, 문의에 대한 답변을 등록, 수정, 삭제를 하기로 해서 로그인 등 프론트와 배포 환경에서 붙여봐야 할 기능이 아직 남았다.)

 

팀원들이 없었다면 이만큼 성실하게 임하며 많이 배우고 성장할 수 없었을 것 같아 고마움을 많이 느낀다.

젤로 쿤디 시오 이안 감사~~!!

좋은 환경을 제공해준 코드스쿼드도 감사~~!!!

좋은 자극이 되어 준 다른 코쿼 동료들도 감사~~!!